mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			193 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| .. index:: analyse, asm
 | |
| 
 | |
| #############################
 | |
| Analysing the Compiler Output
 | |
| #############################
 | |
| 
 | |
| It is often useful to look at the assembly code generated by the compiler. The generated binary,
 | |
| i.e., the output of ``solc --bin contract.sol``, is generally difficult to read. It is recommended
 | |
| to use the flag ``--asm`` to analyse the assembly output. Even for large contracts, looking at a
 | |
| visual diff of the assembly before and after a change is often very enlightening.
 | |
| 
 | |
| Consider the following contract (named, say ``contract.sol``):
 | |
| 
 | |
| .. code-block:: Solidity
 | |
| 
 | |
|     // SPDX-License-Identifier: GPL-3.0
 | |
|     pragma solidity >=0.5.0 <0.9.0;
 | |
|     contract C {
 | |
|         function one() public pure returns (uint) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| The following would be the output of ``solc --asm contract.sol``
 | |
| 
 | |
| .. code-block:: none
 | |
| 
 | |
|     ======= contract.sol:C =======
 | |
|     EVM assembly:
 | |
|         /* "contract.sol":0:86  contract C {... */
 | |
|       mstore(0x40, 0x80)
 | |
|       callvalue
 | |
|       dup1
 | |
|       iszero
 | |
|       tag_1
 | |
|       jumpi
 | |
|       0x00
 | |
|       dup1
 | |
|       revert
 | |
|     tag_1:
 | |
|       pop
 | |
|       dataSize(sub_0)
 | |
|       dup1
 | |
|       dataOffset(sub_0)
 | |
|       0x00
 | |
|       codecopy
 | |
|       0x00
 | |
|       return
 | |
|     stop
 | |
| 
 | |
|     sub_0: assembly {
 | |
|             /* "contract.sol":0:86  contract C {... */
 | |
|           mstore(0x40, 0x80)
 | |
|           callvalue
 | |
|           dup1
 | |
|           iszero
 | |
|           tag_1
 | |
|           jumpi
 | |
|           0x00
 | |
|           dup1
 | |
|           revert
 | |
|         tag_1:
 | |
|           pop
 | |
|           jumpi(tag_2, lt(calldatasize, 0x04))
 | |
|           shr(0xe0, calldataload(0x00))
 | |
|           dup1
 | |
|           0x901717d1
 | |
|           eq
 | |
|           tag_3
 | |
|           jumpi
 | |
|         tag_2:
 | |
|           0x00
 | |
|           dup1
 | |
|           revert
 | |
|             /* "contract.sol":17:84  function one() public pure returns (uint) {... */
 | |
|         tag_3:
 | |
|           tag_4
 | |
|           tag_5
 | |
|           jump	// in
 | |
|         tag_4:
 | |
|           mload(0x40)
 | |
|           tag_6
 | |
|           swap2
 | |
|           swap1
 | |
|           tag_7
 | |
|           jump	// in
 | |
|         tag_6:
 | |
|           mload(0x40)
 | |
|           dup1
 | |
|           swap2
 | |
|           sub
 | |
|           swap1
 | |
|           return
 | |
|         tag_5:
 | |
|             /* "contract.sol":53:57  uint */
 | |
|           0x00
 | |
|             /* "contract.sol":76:77  1 */
 | |
|           0x01
 | |
|             /* "contract.sol":69:77  return 1 */
 | |
|           swap1
 | |
|           pop
 | |
|             /* "contract.sol":17:84  function one() public pure returns (uint) {... */
 | |
|           swap1
 | |
|           jump	// out
 | |
|             /* "#utility.yul":7:125   */
 | |
|         tag_10:
 | |
|             /* "#utility.yul":94:118   */
 | |
|           tag_12
 | |
|             /* "#utility.yul":112:117   */
 | |
|           dup2
 | |
|             /* "#utility.yul":94:118   */
 | |
|           tag_13
 | |
|           jump	// in
 | |
|         tag_12:
 | |
|             /* "#utility.yul":89:92   */
 | |
|           dup3
 | |
|             /* "#utility.yul":82:119   */
 | |
|           mstore
 | |
|             /* "#utility.yul":72:125   */
 | |
|           pop
 | |
|           pop
 | |
|           jump	// out
 | |
|             /* "#utility.yul":131:353   */
 | |
|         tag_7:
 | |
|           0x00
 | |
|             /* "#utility.yul":262:264   */
 | |
|           0x20
 | |
|             /* "#utility.yul":251:260   */
 | |
|           dup3
 | |
|             /* "#utility.yul":247:265   */
 | |
|           add
 | |
|             /* "#utility.yul":239:265   */
 | |
|           swap1
 | |
|           pop
 | |
|             /* "#utility.yul":275:346   */
 | |
|           tag_15
 | |
|             /* "#utility.yul":343:344   */
 | |
|           0x00
 | |
|             /* "#utility.yul":332:341   */
 | |
|           dup4
 | |
|             /* "#utility.yul":328:345   */
 | |
|           add
 | |
|             /* "#utility.yul":319:325   */
 | |
|           dup5
 | |
|             /* "#utility.yul":275:346   */
 | |
|           tag_10
 | |
|           jump	// in
 | |
|         tag_15:
 | |
|             /* "#utility.yul":229:353   */
 | |
|           swap3
 | |
|           swap2
 | |
|           pop
 | |
|           pop
 | |
|           jump	// out
 | |
|             /* "#utility.yul":359:436   */
 | |
|         tag_13:
 | |
|           0x00
 | |
|             /* "#utility.yul":425:430   */
 | |
|           dup2
 | |
|             /* "#utility.yul":414:430   */
 | |
|           swap1
 | |
|           pop
 | |
|             /* "#utility.yul":404:436   */
 | |
|           swap2
 | |
|           swap1
 | |
|           pop
 | |
|           jump	// out
 | |
| 
 | |
|         auxdata: 0xa2646970667358221220a5874f19737ddd4c5d77ace1619e5160c67b3d4bedac75fce908fed32d98899864736f6c637827302e382e342d646576656c6f702e323032312e332e33302b636f6d6d69742e65613065363933380058
 | |
|     }
 | |
| 
 | |
| Alternatively, the above output can also be obtained from `Remix <https://remix.ethereum.org/>`_,
 | |
| under the option "Compilation Details" after compiling a contract.
 | |
| 
 | |
| Notice that the ``asm`` output starts with the creation / constructor code. The deploy code is
 | |
| provided as part of the sub object (in the above example, it is part of the sub-object ``sub_0``).
 | |
| The ``auxdata`` field corresponds to the contract :ref:`metadata
 | |
| <encoding-of-the-metadata-hash-in-the-bytecode>`. The comments in the assembly output point to the
 | |
| source location. Note that ``#utility.yul`` is an internally generated file of utility functions
 | |
| that can be obtained using the flags ``--combined-json
 | |
| generated-sources,generated-sources-runtime``.
 | |
| 
 | |
| Similarly, the optimized assembly can be obtained with the command: ``solc --optimize --asm
 | |
| contract.sol``. Often times, it is interesting to see if two different sources in Solidity result in
 | |
| the same optimized code. For example, to see if the expressions ``(a * b) / c``, ``a * b / c``
 | |
| generates the same bytecode. This can be easily done by taking a ``diff`` of the corresponding
 | |
| assembly output, after potentially stripping comments that reference the source locations.
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|    The ``--asm`` output is not designed to be machine readable. Therefore, there may be breaking
 | |
|    changes on the output between minor versions of solc.
 |