Conversation
|
There are two systems (PawnPlus and amx-assembly) that already implement this to some extent. Obviously compiler support is better, but both existing versions use the full name |
|
How does it work with otherwise unused symbols? Does using this commit the symbol to the AMX? |
0a3bb43 to
3d24c40
Compare
Done.
Yes it does, as it marks them as |
3d24c40 to
9c107ce
Compare
|
Nice, this will be very useful! |
9c107ce to
3768ba4
Compare
|
Oops, I think I mistapped and re-requested review (sorry!) @YashasSamaga I think there shouldn't be anything that would prevent implementing address calculation for local variables at run time; I'll try to finish this today. |
3768ba4 to
50d54b9
Compare
|
I think a |
|
Unlike |
| @@ -0,0 +1,48 @@ | |||
| #include <console> | |||
|
|
|||
| const func1_addr = __addressof(Func1); // error | |||
There was a problem hiding this comment.
This is a little surprising. Functions can otherwise be used before declaration. Would this work if it were forwarded?
There was a problem hiding this comment.
Functions can otherwise be used before declaration.
This is because in order to call functions the compiler outputs call .funcname, so it could look up the function and obtain its address later, when assembling the code. But __addressof works as an expression, and expressions are handled at the first two compilation stages (parsing), and the compiler can't know a function/label address until it parses its definition at the 2'nd pass; it doesn't keep function addresses obtained at the 1'st pass since at the 2'nd one the generated code can change (e.g. because of #if defined <func> being used for conditional compilation). I think the only solution for this is to add an ability to force a "second" second pass, but this sounds more like a work for a separate PR, IMO.
There was a problem hiding this comment.
You could build up a list of unresolved addressof calls, just as CONST.pri locations (or however it is actually implemented), then iterate through them once the function is resolved. A third compiler pass would very probably break a lot of stuff.
There was a problem hiding this comment.
Or, as I said, would forward fix this? I somewhat doubt it as address isn't in the metadata that could be stored in that way. But maybe the pending addresses could be added to the metadata for a function, thus require forward for this case as well (for something like consistency).
There was a problem hiding this comment.
I just realised this works:
main()
{
new a = __emit(CONST.pri Func);
}
Func()
{
}There was a problem hiding this comment.
I just realised this works:
new a = __emit(CONST.pri Func);
Indeed. As I already mentioned, __emit implements its own code generation mechanism, so it isn't bound by the limits of the standard codegen. But either way it generates code, so it can't be used to initialize constants and/or global variables.
What this PR does / why we need it:
This PR implements operator
__addressofthat allows to obtain the address of the operand as a compile-time constant value.Example:
The operator can be used on:
NOTE: Functions and labels should be defined before they are used via
__addressof, because the compiler can't know their address in advance.While implementing this operator, I also made the following tweaks:
There's no point in suggesting native functions for the use in
__addressof.This should be useful not only for
__addressof, but also for__emitand#emit.count_referers()(sc1.c) and renamed it tohas_referers().When reducing the referers tree, the compiler doesn't really need to count all the referers for each symbol, it only needs to check if the symbol has been referenced at least once.
This change isn't really necessary for
__addressofto function properly, but I already had to modifycount_referers()to take in account the newly added "referenced globally" symbol flag (see above), so I also simplified the function while I was at it. This should slightly speed up the compilation process.Which issue(s) this PR fixes:
Fixes #
What kind of pull this is:
Additional Documentation: