-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cross-Inline-Assembly block functions. #1319
Comments
The solution regarding visibility of labels and macros could be the following: |
Somewhat related: #474 |
Some examples: // 64 bit unsigned multiplication with overflow detection
define mul_u64(x, y) -> z
{
z := mul(and(x, 0xffffffffffffffff), and(y, 0xffffffffffffffff))
jumpi(ErrorTag, gt(z, 0xffffffffffffffff))
} |
The macros I'd like to see (copied from #474):
// allocates a memory block
define alloc(size) -> offset
{
// current end of memory
offset := mload(0x40)
// new "end of memory" including padding
mstore(0x40, add(offset, and(add(size, 0x1f), bnot(0x1f))))
}
// allocates memory for a bytes/string type
define allocbytes(size) -> offset
{
offset := $alloc(add(size, 32))
mstore(offset, size)
} |
Your example usage shows that we have to refine our definition of macros with regards to their return values. As currently specified, What about adding the following part to the specification: If return parameters are provided, the macro is expanded with the following prefix and suffix: prefix: allocate a new stack slot for each return parameter, setting them to zero If no return parameters are provided (in the sense that they are named variables, the macro can still return values to the stack), there is no prefix and suffix. |
Changed the initial description to word it more towards making inline assembly functions accessible across inline assembly blocks. |
Actually I think the suggestion in the comment above could work rather well. We have to introduce another lookup method for function identifiers (and not just variable identifiers). Furthermore, inline assembly functions have to be registered at the compiler context, and not just the inline assembly AST node. Compiler-generated functions have a different prefix and thus cannot clash (but you can still use them if you want). |
If we are talking about macros, perhaps it would make sense introducing a symbol differentiating them from opcodes. One example is the exclamation mark from Rust: |
My general feeling is that epsilon engineering effort should go into improving inline assembly. Instead, Solidity should be looking at what people are building with inline assembly and figuring out higher level constructs that facilitate doing that in Solidity, so they don't need to drop to inline assembly. Anytime someone drops to inline assembly suggests a failure of the language, or at least an area where the language can improve. Also, inline assembly really isn't appropriate for smart contracts, which are supposed to be public, easily auditable code blocks and assembly makes the code harder to read/audit. |
"public, easily auditable code blocks" - exactly my words! I'm just drawing a different conclusion: Complicated code that is hidden in the compiler is worse than structured assembly code that can be easily found in a library that is linked together with the project. But it always depends on the use-case and what you do with inline assembly. What people do with it should be an inspiration for language features. |
This issue has been marked as stale due to inactivity for the last 90 days. |
Hi everyone! This issue has been automatically closed due to inactivity. |
TODO:
Most of the ideas below have been implemented. What we are missing is functions that can be used across multiple inline-assembly blocks. In the code generator, this is supported via "named labels".
It is not really supported in the assembly parser, though, but we could always prefix all known inline assembly functions that parsed correctly, perhaps even without body?
Solidity (inline) assembly should support macros in the following way:
The defined macro will be visible and usable in inline assembly blocks in the whole code unit (this includes the current contract, base contracts and internal functions of libraries that are called, but construction-time code is disconnected from runtime code).
Remark: currently labels are only visible in the current inline assembly block, so we should aligns those two behaviours.
It is an error to define two macros of the same name in the same code unit.
If the return parameters are not given, the compiler will try to infer the stack difference caused by the macro. If it is not able to do that or if there are two code paths with different stack differences, this is an error.
Inside the assembly code, both the parameters and the return parameters are available as variables and they are assigned contiguous stack slots (left: deep, right: top) where the first parameter and the first return parameter refer to the same slot. If there are more parameters than return parameters, the surplus stack items are popped automatically.
A macro can be used in the same way as an opcode can be used with the same restriction for usage in functional style notation.
Note that macros are more similar to custom opcodes - they are not a replacement system in that their arguments are evaluated before they are "called" just like with evm opcodes and not inserted literally into the macro's body.
If a macro is called, it is usually just replaced by its body, but it is also possible to use macros recursively. In this case, and also if it makes sense from an optimization perspective, the macro body is moved out-of-place and it is called like a function.
The compiler will also define several globally available macros. Those macros will always start with
$
and thus, such macro names can be considered reserved.The text was updated successfully, but these errors were encountered: