-
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
Fixes and improvements for emit/__emit #211
Conversation
The instruction name is copied in lower case anyway (see emit_parse_line()).
Conflicts: source/compiler/sc1.c
…() & emit_param_data()
…rgument type mismatch
This changes the way 'switch', 'casetbl' and 'case' are handled; now 'casetbl' can't be used directly and the arguments for the first case table entry (the number of entries and 'default' label) are specified to 'switch'. Example: emit { load.s.pri my_var switch 3 lbl_deafult case 0 lbl_0 case 2 lbl_2 case 4 lbl_4 }
It was copied from sc2.c with a check for a trailing '}' added and was too specific to be reused anywhere else.
Example: main() { new x; emit load.pri x } Before this commit: error 017: undefined symbol "x" After: error 001: expected token: "-data offset-", but found "-local variable-"
…ram_num() Now it should be possible to do this: const SOME_VAL = 1; emit const.pri -SOME_VAL or this: static some_array[] = { 0, 1, 2, 3, 4, 5 }; static some_var; emit { const.pri some_var }; new some_var_offset = emit { add.c -some_array };
Now the function takes the array itself before the array size, as the argument handlers in sc1.c do.
In that case, why not just branch based on the number of values, since |
It's not that simple. The results of the test above may differ on machines other than my PC, especially on those with different architecture. |
Anyway, I changed the syntax of // No need to use curly brackets with 'emit' within expressions anymore
new x = emit const.pri 1;
new y = (emit stack 0, emit move.pri);
// Now ';' can be optionally put at the end
// of the line for single-line syntax
emit const.pri 1;
emit zero.pri // Omitting ';' is still valid
// For multiline syntax putting ';' after the closing brace
// is no longer valid since it goes against all other syntax
emit{
nop
}; // error 036: empty statement |
I think this should respect the |
Don't want to sound rude or anything, but how would anyone benefit from this? |
Made the compiler issue an error if a label within the emit
{
my_label:
jump my_label
my_label:
} Before: <no errors/warnings> Also fixed a similar bug with regular labels, but made it as a separate PR since it's not related to |
Surely that's why the flag exists in the first place. The semi-colon is already optional, and you can already omit it if you choose. Or, you can choose to make it required with a flag. In that case, the user has made an explicit choice, and ignoring it for the sake of more "choice" is very counter-intuative. |
This logic could work in theory, but in reality the only people I've seen not using |
Another commit, now it should be possible to use constant expressions as opcode arguments. emit const.pri ((MAX_PLAYERS - 4 * 3) + 1);
new x = random(1);
emit
{
load.s.pri x
add.c (MAX_PLAYERS / 2) // MAX_PLAYERS / 2 + x
} Note that the expressions must be enclosed in parentheses. Expressions can be used with |
What poll? And this again comes back to the same issue I mentioned before about making this a full expression instead of unique extra syntax. Using braces and not semi-colons within expressions is not done anywhere else, although I like that it now supports the normal way of chaining expressions with #assert MAX_PLAYERS > 10
assert(GetPlayerPoolSize() > 10); Are these now possible: printf("%d", (emit LCTRL 3, emit HEAP -4, emit STOR.I, emit PUSH.alt)), emit HEAP 4;
printf("%d", emit { LCTRL 3; HEAP -4; STOR.I; PUSH.alt }), emit HEAP 4; ? I don't mind the brace syntax in that context quite so much, though if we were really following the standard syntax and precedence rules these could both be valid: printf("%d", (emit LCTRL 3, emit HEAP -4, emit STOR.I, emit PUSH.alt)), emit HEAP 4;
printf("%d", emit (LCTRL 3, HEAP -4, STOR.I, PUSH.alt)), emit HEAP 4; Again, no reason for new subtly different syntax when the existing syntax works. This would see |
printf("%d", (emit LCTRL 3, emit HEAP -4, emit STOR.I, emit PUSH.alt)), emit HEAP 4;
printf("%d", emit { LCTRL 3; HEAP -4; STOR.I; PUSH.alt }), emit HEAP 4;
Not exactly, you can't chain |
Fixed a bug that caused bad code generation when using const MAX_PLAYERS = 1000;
new x = 1 + emit const.pri (MAX_PLAYERS / 2) + 4; // x = MAX_PLAYERS / 2 + 5; This code caused the compiler to erase all code in the staging buffer that was before the I also fixed the instructions generated by new x = (emit const.pri 0, emit add.c 1, emit add.c 1); Code generated before the fix:
After:
|
…value', 'data offset', 'local variable' and 'function'
…ine()' Conflicts: source/compiler/sc1.c
Since a compiled script that uses both Now when emit sysreq.n printf 8; With
but with
The similar rule applies to These changes won't really affect SA-MP users since macro opcodes won't work on the SA-MP server, but
|
Apparently the 'anti-optimisation' trick for instructions within I also made some improvements to the syntax, now when emit(const.pri 0, add.c 1, add.c 2);
printf("%d, %d", emit const.pri 0, emit(const.pri 0, add.c 1, add.c 2));
emit const.pri 0, printf(""), emit(const.pri 0, add.c 1, add.c 2); A trailing emit const.pri 0 // error 001: expected token: ";", but found "emit"
emit const.pri 0; // ok |
Updated the 1'st comment with all of the latest changes. I suppose this PR should be considered ready to be merged, since there are no any further suggestions (of course, the final decision is yours, @Zeex ). |
Now multiple instructions can be put within a single `emit` by being enclosed in parentheses.
Example:
Also single-line
emit
statements require a trailing semicolon.Example:
Note that the expression should be enclosed in parentheses in order to be properly recognized by the compiler.
Also it's possible to use the "-" sign before single named constants.
Example:
Output before this PR:
After:
Example:
This is because in order to call native functions the compiler uses either 'sysreq.n' or 'sysreq.c', not both, so having both 'sysreq.c' and 'sysreq.n' instructions in one script can be considered invalid.
For the same reason
emit sysreq.n <ntvid> <argsize>
is turned into a sequence of non-macro instructions when macro-optimisations aren't enabled, so nowsysreq.n
can be safely used in SA-MP gamemodes as a macro for native function calls.Additionally all macro-opcodes can be automatically replaced by non-macro ones.
Example:
When compiled with no macro-optimisations the code above turns into
This should allow to write more elegant and portable code with the
emit
/__emit
operator."Invalid range" is probably not the best description for this kind of error, but I'm not sure if adding a new error type to sc5.c (093?) is a good idea, so I'm leaving it as is for now.
The number of further case table entries and the 'default' label are now passed to 'casetbl', not the leading 'case' entry.
Before this PR:
After:
Example of code that could have made the compiler crash (before this PR):
(Also fixed the same bug in '#emit'.)