This means we don't have to pass it around as an argument.
This change was made because I'm about to start creating pointer types
during expression evaluation, and I didn't want to add an arena
argument to all the expression functions.
Factor ARM integer binary operation setup code into a function.
Don't pass redundant pType information into loadR0FromR0, storeR0ToTOS,
gcmp, gUnaryCmp, li
Separate inc/dec from variable loading. Generates worse code, but now
we handle pointer inc/dec and char inc/dec.
Don't segfault if the right-hand operand of a binary operator is missing.
Don't segfault if a semicolon is missing at the end of a forward
declaration.
Support floating-point if/while statements: if(1.0) { ... }
Support reading values from float and double pointers.
And some additional error checking.
Detect malformed "return" statements
Detect passing the results of "void" functions as arguments.
Doesn't add any new capabilities, but we now generate error
messages if you attempt casts we don't support,
and we also found and fixed some bugs in declaration parsing.
+ Tokens are now simple IDs, rather than ids or maybe pointers.
+ We can now allocate data that's freed automatically when
compilation end or when a block goes out of scope.
+ Renamed our Array utility class to Vector, and made its
api work a little more like the STL vector template class.
Until now we faked local variables -- they only worked correctly if
there was no overlap between local variables and global variables.
Use a symbol table stack instead of a string list.
Fix bug with looking up undefined symbols.
It makes it harder to deal with memory allocation.
Also fix bug in the otcc-ansi.c test, where the wrong part of the
code buffer was being mprotected, so that if the code buffer happened
to be allocated across a page boundary, some code would no receive
execute permission.
Set execute permission on code before running it.
Handle negative relative offsets for global variables.
Add printfs to report the progress of nested compiles.
Change way we detect whether we can run the host compiler
or not. We used to check if we were running on a 32-bit
Linux. Now we check if the executable is a 32-bit Linux
executable.
main(argc, argv) --> int main(int argc, char** argv)
Although we accept int, void, and char types, and pointers to same,
we actually still treat everything as an int.