I read the assembly docs but I am still a bit unsure regarding when I should apply the ("memory-safe")
dialect, and when not.
For instance, take the following examples taken from PRBMath:
function frac(UD60x18 x) pure returns (UD60x18 result) {
assembly {
result := mod(x, uUNIT)
}
}
And:
function msb(uint256 x) pure returns (uint256 result) {
// 2^128
assembly {
let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// ...
}
The docs say this:
Inline assembly that neither involves any operations that access memory nor assigns to any Solidity variables in memory is automatically considered memory-safe and does not need to be annotated.
The first example simply reads a variable from the stack and a const, so my instinct would say there is no need for the dialect because the code is memory safe by default. But the second example assigns to result
, which is part of returndata, so here I am not so sure. My questions are:
- Do the examples above count as code snippets that do not involve any operations that access memory?
- Does it hurt if I add the
("memory-safe")
dialect to a code snippet that doesn’t actually need it (e.g. a code that “neither involves any operations that access memory nor assigns to any Solidity variables in memory”)?