mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Replaced tabs with spaces
This commit is contained in:
parent
d6f05a6d36
commit
51fe1bd9c2
@ -246,8 +246,8 @@ arising when writing manual assembly by the following features:
|
|||||||
We now want to describe the inline assembly language in detail.
|
We now want to describe the inline assembly language in detail.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
Inline assembly is still a relatively new feature and might change if it does not prove useful,
|
Inline assembly is still a relatively new feature and might change if it does not prove useful,
|
||||||
so please try to keep up to date.
|
so please try to keep up to date.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@ -258,23 +258,23 @@ idea is that assembly libraries will be used to enhance the language in such way
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
library GetCode {
|
library GetCode {
|
||||||
function at(address _addr) returns (bytes o_code) {
|
function at(address _addr) returns (bytes o_code) {
|
||||||
assembly {
|
assembly {
|
||||||
// retrieve the size of the code, this needs assembly
|
// retrieve the size of the code, this needs assembly
|
||||||
let size := extcodesize(_addr)
|
let size := extcodesize(_addr)
|
||||||
// allocate output byte array - this could also be done without assembly
|
// allocate output byte array - this could also be done without assembly
|
||||||
// by using o_code = new bytes(size)
|
// by using o_code = new bytes(size)
|
||||||
o_code := mload(0x40)
|
o_code := mload(0x40)
|
||||||
// new "memory end" including padding
|
// new "memory end" including padding
|
||||||
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
|
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), bnot(0x1f))))
|
||||||
// store length in memory
|
// store length in memory
|
||||||
mstore(o_code, size)
|
mstore(o_code, size)
|
||||||
// actually retrieve the code, this needs assembly
|
// actually retrieve the code, this needs assembly
|
||||||
extcodecopy(_addr, add(o_code, 0x20), 0, size)
|
extcodecopy(_addr, add(o_code, 0x20), 0, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline assemmbly could also be beneficial in cases where the optimizer fails to produce
|
Inline assemmbly could also be beneficial in cases where the optimizer fails to produce
|
||||||
efficient code. Please be aware that assembly is much more difficult to write because
|
efficient code. Please be aware that assembly is much more difficult to write because
|
||||||
@ -283,24 +283,24 @@ you really know what you are doing.
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
library VectorSum {
|
library VectorSum {
|
||||||
// This function is less efficient because the optimizer currently fails to
|
// This function is less efficient because the optimizer currently fails to
|
||||||
// remove the bounds checks in array access.
|
// remove the bounds checks in array access.
|
||||||
function sumSolidity(uint[] _data) returns (uint o_sum) {
|
function sumSolidity(uint[] _data) returns (uint o_sum) {
|
||||||
for (uint i = 0; i < _data.length; ++i)
|
for (uint i = 0; i < _data.length; ++i)
|
||||||
o_sum += _data[i];
|
o_sum += _data[i];
|
||||||
}
|
}
|
||||||
// We know that we only access the array in bounds, so we can avoid the check.
|
// We know that we only access the array in bounds, so we can avoid the check.
|
||||||
// 0x20 needs to be added to an array because the first slot contains the
|
// 0x20 needs to be added to an array because the first slot contains the
|
||||||
// array length.
|
// array length.
|
||||||
function sumAsm(uint[] _data) returns (uint o_sum) {
|
function sumAsm(uint[] _data) returns (uint o_sum) {
|
||||||
for (uint i = 0; i < _data.length; ++i) {
|
for (uint i = 0; i < _data.length; ++i) {
|
||||||
assembly {
|
assembly {
|
||||||
o_sum := mload(add(add(_data, 0x20), i))
|
o_sum := mload(add(add(_data, 0x20), i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Syntax
|
Syntax
|
||||||
------
|
------
|
||||||
@ -487,7 +487,7 @@ Strings are stored left-aligned and cannot be longer than 32 bytes.
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
assembly { 2 3 add "abc" and }
|
assembly { 2 3 add "abc" and }
|
||||||
|
|
||||||
Functional Style
|
Functional Style
|
||||||
-----------------
|
-----------------
|
||||||
@ -497,7 +497,7 @@ adding `3` to the contents in memory at position `0x80` would be
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
3 0x80 mload add 0x80 mstore
|
3 0x80 mload add 0x80 mstore
|
||||||
|
|
||||||
As it is often hard to see what the actual arguments for certain opcodes are,
|
As it is often hard to see what the actual arguments for certain opcodes are,
|
||||||
Solidity inline assembly also provides a "functional style" notation where the same code
|
Solidity inline assembly also provides a "functional style" notation where the same code
|
||||||
@ -505,7 +505,7 @@ would be written as follows
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
mstore(0x80, add(mload(0x80), 3))
|
mstore(0x80, add(mload(0x80), 3))
|
||||||
|
|
||||||
Functional style and instructional style can be mixed, but any opcode inside a
|
Functional style and instructional style can be mixed, but any opcode inside a
|
||||||
functional style expression has to return exactly one stack slot (most of the opcodes do).
|
functional style expression has to return exactly one stack slot (most of the opcodes do).
|
||||||
@ -536,18 +536,18 @@ It is planned that the stack height changes can be specified in inline assembly.
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
contract c {
|
contract c {
|
||||||
uint b;
|
uint b;
|
||||||
function f(uint x) returns (uint r) {
|
function f(uint x) returns (uint r) {
|
||||||
assembly {
|
assembly {
|
||||||
b pop // remove the offset, we know it is zero
|
b pop // remove the offset, we know it is zero
|
||||||
sload
|
sload
|
||||||
x
|
x
|
||||||
mul
|
mul
|
||||||
=: r // assign to return variable r
|
=: r // assign to return variable r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Labels
|
Labels
|
||||||
------
|
------
|
||||||
@ -558,19 +558,19 @@ jumps easier. The following code computes an element in the Fibonacci series.
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
{
|
{
|
||||||
let n := calldataload(4)
|
let n := calldataload(4)
|
||||||
let a := 1
|
let a := 1
|
||||||
let b := a
|
let b := a
|
||||||
loop:
|
loop:
|
||||||
jumpi(loopend, eq(n, 0))
|
jumpi(loopend, eq(n, 0))
|
||||||
a add swap1
|
a add swap1
|
||||||
n := sub(n, 1)
|
n := sub(n, 1)
|
||||||
jump(loop)
|
jump(loop)
|
||||||
loopend:
|
loopend:
|
||||||
mstore(0, a)
|
mstore(0, a)
|
||||||
return(0, 0x20)
|
return(0, 0x20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Please note that automatically accessing stack variables can only work if the
|
Please note that automatically accessing stack variables can only work if the
|
||||||
assembler knows the current stack height. This fails to work if the jump source
|
assembler knows the current stack height. This fails to work if the jump source
|
||||||
@ -583,19 +583,19 @@ will have a wrong impression about the stack height at label `two`:
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
{
|
{
|
||||||
jump(two)
|
jump(two)
|
||||||
one:
|
one:
|
||||||
// Here the stack height is 1 (because we pushed 7),
|
// Here the stack height is 1 (because we pushed 7),
|
||||||
// but the assembler thinks it is 0 because it reads
|
// but the assembler thinks it is 0 because it reads
|
||||||
// from top to bottom.
|
// from top to bottom.
|
||||||
// Accessing stack variables here will lead to errors.
|
// Accessing stack variables here will lead to errors.
|
||||||
jump(three)
|
jump(three)
|
||||||
two:
|
two:
|
||||||
7 // push something onto the stack
|
7 // push something onto the stack
|
||||||
jump(one)
|
jump(one)
|
||||||
three:
|
three:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Declaring Assembly-Local Variables
|
Declaring Assembly-Local Variables
|
||||||
@ -610,19 +610,19 @@ be just `0`, but it can also be a complex functional-style expression.
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
contract c {
|
contract c {
|
||||||
function f(uint x) returns (uint b) {
|
function f(uint x) returns (uint b) {
|
||||||
assembly {
|
assembly {
|
||||||
let v := add(x, 1)
|
let v := add(x, 1)
|
||||||
mstore(0x80, v)
|
mstore(0x80, v)
|
||||||
{
|
{
|
||||||
let y := add(sload(v), 1)
|
let y := add(sload(v), 1)
|
||||||
b := y
|
b := y
|
||||||
} // y is "deallocated" here
|
} // y is "deallocated" here
|
||||||
b := add(b, v)
|
b := add(b, v)
|
||||||
} // v is "deallocated" here
|
} // v is "deallocated" here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Assignments
|
Assignments
|
||||||
@ -640,12 +640,12 @@ For both ways, the colon points to the name of the variable.
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
assembly {
|
assembly {
|
||||||
let v := 0 // functional-style assignment as part of variable declaration
|
let v := 0 // functional-style assignment as part of variable declaration
|
||||||
let g := add(v, 2)
|
let g := add(v, 2)
|
||||||
sload(10)
|
sload(10)
|
||||||
=: v // instruction style assignment, puts the result of sload(10) into v
|
=: v // instruction style assignment, puts the result of sload(10) into v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Things to Avoid
|
Things to Avoid
|
||||||
@ -681,6 +681,6 @@ arrays are pointers to memory arrays. The length of a dynamic array is stored at
|
|||||||
first slot of the array and then only the array elements follow.
|
first slot of the array and then only the array elements follow.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
Statically-sized memory arrays do not have a length field, but it will be added soon
|
Statically-sized memory arrays do not have a length field, but it will be added soon
|
||||||
to allow better convertibility between statically- and dynamically-sized arrays, so
|
to allow better convertibility between statically- and dynamically-sized arrays, so
|
||||||
please do not rely on that.
|
please do not rely on that.
|
||||||
|
Loading…
Reference in New Issue
Block a user