-
Notifications
You must be signed in to change notification settings - Fork 72
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
Operator '__addressof' #445
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realised this works:
main()
{
new a = __emit(CONST.pri Func);
}
Func()
{
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
__addressof
that 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__emit
and#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
__addressof
to 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: