Compare commits

...

2154 commits

Author SHA1 Message Date
Dale Weiler
297eab9e5e reset framevalue on includes like fteqcc 2021-07-09 14:05:01 -04:00
Dale Weiler
da63ad7e07 fix -fsort-operands 2021-07-09 14:04:28 -04:00
Dale Weiler
ddcae703e3 allow dots in frame names to compile hypnotic 2021-07-09 12:17:02 -04:00
Dale Weiler
6cf25c0ec6 allow comparing explicitly against nil 2021-07-07 23:11:17 -04:00
Dale Weiler
663723f00a fixed mixing of old and new framemacro syntax 2021-07-07 22:58:13 -04:00
Dale Weiler
1e8ce1733b fix bug 197, 198, and 199 properly 2021-04-06 14:47:35 -04:00
Dale Weiler
47475bb455 fix bug #188 2021-03-27 20:45:40 -04:00
Dale Weiler
71138cbe1a rewrite dead code elimination for conditionals 2021-03-27 20:32:24 -04:00
Dale Weiler
85c79d2f1c fclose when fopen actually succeeds 2021-03-26 19:02:27 -04:00
Dale Weiler
13bcb5c5b1 set m_op as well when doing a-(-b) => a+b peephole 2021-03-26 18:57:31 -04:00
Dale Weiler
465941f357 pass parent scope to parse_statement_or_block
previous behavior when parsing a statement where a block is typically expected would fail to associate the statement with the parent block it's in, resulting in variable declarations ending up in global scope.

this fixes #197
2021-03-02 10:46:05 -05:00
Dale Weiler
237722c0b2 fix crash when cleaning up functions related to [[accumulate]] 2020-10-27 19:40:30 -04:00
Dale Weiler
f971f89e1e new makefile 2020-04-17 13:28:27 -04:00
Wolfgang Bumiller
94c2936bfa tests: xor peephole optimization regression test
Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
2019-09-15 10:27:26 +02:00
Wolfgang Bumiller
2d4a054440 ir: fix generation of multi-op vinstrs
Do not assume that the destination is a temporary location,
as our peephole optimizer will break this. For example, the
following IR code (generated via from `x ^= gety()`):

    (0) binst6 <- BITXOR   x,      call5
    (0) x <- STORE_F       binst6

after peephole optimization becomes:

    (7) x <- BITXOR        x,      call5

Therefore we cannot assume that the output of the virtual
xor instruction can be utilized as a temporary value.

BITXOR becomes `(x | y) - (x & y)`, which would wrongly be
generated as:
    x = x | y;
    temp0 = x & y;
    x = x - temp0;

While this particular case can be fixed by using temp0 first
and then x, the cross-product case would not be so simple.

Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
Fixes #190
2019-09-15 10:23:47 +02:00
Wolfgang Bumiller
031f827da5 introduce another vinstr temp
Some vinstrs are currently broken when using peephole
optimization as they appear as writing to a temporary ssa
output before being stored into their real destination,
causing the store to be optimized out, but the generated
code relies on having the destination as another temporary
value available.

Let's just add a 2nd temp to be used in those cases.

Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
2019-09-15 10:12:40 +02:00
Dale Weiler
451873ae52
Merge pull request #187 from divVerent/patch-1
Fix printing of floating poing values in -dumpfin.
2019-02-04 09:20:23 -05:00
divVerent
9c81ff263a
Fix printing of floating poing values in -dumpfin.
%g is not lossless for single precision floats - %.9g is (other than distinguishing NaNs, who cares).
2019-02-04 06:14:58 -08:00
Dale Weiler
620bd76e76 fix __builtin_nan and add some missing builtins 2018-11-14 08:43:22 -05:00
Dale Weiler
2d99ce609d fix octals 2018-10-30 17:32:21 -04:00
Dale Weiler
0904a1ceb7 fixes for progs.src 2018-09-01 00:48:18 -04:00
Dale Weiler
c74fabffda Merge branch 'master' of github.com:graphitemaster/gmqcc 2018-05-09 21:19:39 -04:00
Dale Weiler
092067482f added -fdefault-eraseable which is the same as adding [[eraseable]] to all definitions
instead the opposite behavior can be controlled with [[noerase]] attribute
2018-05-09 21:18:37 -04:00
Dale Weiler
dac058107a
Delete .travis.yml 2018-05-05 15:44:21 -04:00
Dale Weiler
9a21c638fa error if a function is called from global scope opposed to crashing 2018-05-05 15:38:12 -04:00
Wolfgang Bumiller
97a74eb677 catch broken vector member access
These kinds of expressions currently cannot be handled
without pionter support in the qcvm without scanning the
ast from within ast_member::codegen for an assignments as
seen in the added test case.

This change makes code like that return a pointer type which
will cause an error that we did not get a vector or field
back. With pointer support this pointer could actually be
used instead.

So at least it shouldn't silently produce broken code
anymore.

Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
2018-01-14 10:58:29 +01:00
Wolfgang Bumiller
f84c8ea629 add variable search order test
Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
2018-01-14 09:33:05 +01:00
Wolfgang Bumiller
e920766b10 Make parser_find_local only actually search locals
Fixes #163
Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
2018-01-14 09:33:05 +01:00
Wolfgang Bumiller
e006aa8238 Revert "search for funciton param first before function locals, this fixes #163"
This reverts commit 3cf2c52fce.
2018-01-14 09:33:05 +01:00
Dale Weiler
73d3d7eec1 fix some UB 2017-12-01 13:55:19 -05:00
Dale Weiler
3cf2c52fce search for funciton param first before function locals, this fixes #163 2017-12-01 12:24:50 -05:00
Dale Weiler
1580c23556 Merge branch 'master' of github.com:graphitemaster/gmqcc 2017-11-26 17:48:13 -05:00
Dale Weiler
b14a02e735 don't generate storep for vector field unless it's an ent field 2017-11-26 17:47:27 -05:00
Dale Weiler
679e3771de
Merge pull request #177 from xonotic/terencehill/warning_removal
Get rid of a warning on Windows
2017-11-26 17:30:42 -05:00
Dale Weiler
d9127bf28a
Merge pull request #180 from xonotic/mem_leak_fix_on_failure_paths
two small memory leak fixes on failure paths
2017-11-26 17:30:30 -05:00
Dale Weiler
fa7dce495b fix writing of globaldefs for vector subcomponents so that FTE field remapping works 2017-11-26 17:26:00 -05:00
Dale Weiler
02b20dbd09 fix member binops on entity fields to generate STOREP, this fixes stuff like ent.vec.x += value. 2017-11-26 17:09:38 -05:00
Wolfgang Bumiller
6ad5f18ef1 cleanup: 'move of a temporary object prevents copy elision' 2017-07-23 10:11:31 +02:00
Wolfgang Bumiller
047ecd426f move more parser code to c++, fix crashes with gcc
we initialized the parser with malloc -> memset to zero ->
placement new. With gcc the latter caused the memset to be
optimized out, causing uninitialized value accesses.
2017-07-23 10:11:31 +02:00
Wolfgang Bumiller
fb3af2831b cleanup some silly more warnings 2017-07-23 10:11:31 +02:00
Wolfgang Bumiller
5a0d645ede cleanup: silence fallthrough warnings 2017-07-23 10:11:31 +02:00
terencehill
27c0886ffb Get rid of a warning on Windows 2017-06-23 16:21:22 +02:00
Wolfgang Bumiller
163c4b99a4 tests: add check for vector negation 2017-06-22 08:45:38 +02:00
Wolfgang Bumiller
eb2d478770 qcvm: add stov builtin #16 2017-06-22 08:45:18 +02:00
Wolfgang Bumiller
3f5305af58 ir: fix vector negation using the nil value
We cannot use OFS_NULL as it is only a single value and
overlaps with OFS_RETURN.
2017-06-22 08:44:36 +02:00
David Carlier
8538658e83 two small memory leak fixes on failure paths 2017-05-23 21:56:03 +01:00
Wolfgang Bumiller
8b2149e315 sanitize: shift 1u (unsigned) for flag bits 2017-02-14 19:24:04 +01:00
Wolfgang Bumiller
c285eb385d c++: exec.cpp 2017-02-11 11:43:58 +01:00
Wolfgang Bumiller
2dde6d903e c++: ir_function::m_params 2016-12-03 21:42:15 +01:00
Wolfgang Bumiller
4bf63bb379 c++: ir: function_allocator 2016-12-03 21:39:09 +01:00
Wolfgang Bumiller
95d232ca72 c++: ir_block::m_instr 2016-12-03 21:30:33 +01:00
Wolfgang Bumiller
90f190f5e1 c++: ir_block::m_exits 2016-12-03 20:34:42 +01:00
Wolfgang Bumiller
566c17a964 c++: ir_block::m_entries 2016-12-03 20:32:26 +01:00
Dale Weiler
a5636899f2 Cleaner way to set the mask for -Wunused-component 2016-11-24 19:54:17 +00:00
Dale Weiler
17c0812ae4 Just mark LOCAL_RETURN noref instead of checking for '#' in the name 2016-11-24 15:50:48 +00:00
Dale Weiler
3a7848d67c Remove parser m_uses in favor of {IR,AST}_FLAG_NOREF instead 2016-11-24 15:33:58 +00:00
Dale Weiler
def1a26b12 Add -Wunused-component like -Wunused-variable but warns about unused components of vector 2016-11-24 14:52:57 +00:00
Dale Weiler
eab20602b1 more intelligent handling of unused vector fields 2016-11-24 14:44:28 +00:00
Dale Weiler
69fa4f8dbd Fix #158 2016-11-24 14:08:38 +00:00
Dale Weiler
966991601c Fix #161 2016-11-24 13:41:26 +00:00
Dale Weiler
01f3447e5b Fix #171 2016-11-24 13:40:22 +00:00
Dale Weiler
9821b6a075 Fix fieldfuncs test and track unused variables through writes as well. 2016-11-19 12:19:00 +00:00
Dale Weiler
6938567c6c Don't generate unused warnings for unused constants 2016-11-19 11:46:32 +00:00
Wolfgang Bumiller
0b94d7583c fix access to fields of vector members
When ast_member encounters the result of an ast_entfield it
has to replace the ast_entfield's codegen as we cannot
evaluate the field access first.

We then perform the same action as ast_entfield but call
vectorMember on the field before issuing the load/address
instruction.

This effectively turns the codegen of the following ast
structure:
    member_of {
        field_of {
            entity,
            a_vector
        }
        memberid
    }
into the one of this structure:
    field_of {
        entity,
        member_of {
            a_vector
            memberid
        }
    }
2016-11-19 16:22:18 +01:00
Wolfgang Bumiller
4c48bae203 Revert "Fix ent.vec.{x,y,z} writes"
This reverts commit ad1cfcfeaa.
2016-11-19 16:22:13 +01:00
Dale Weiler
ad1cfcfeaa Fix ent.vec.{x,y,z} writes 2016-11-19 10:42:33 +00:00
Dale Weiler
eca4e2c309 Unused globals even if they have an initial value should produce unused diagnostic 2016-11-19 10:05:58 +00:00
Dale Weiler
167207e98c Warning 2016-05-23 16:47:40 -04:00
Wolfgang Bumiller
e06ad170de update .gitignore 2016-02-10 19:01:12 +01:00
Dale Weiler
3714a507c2 Merge pull request #172 from TimePath/cmake
Add CMakeLists.txt
2016-01-03 01:15:18 -05:00
TimePath
63c679ee81 Add CMakeLists.txt 2016-01-03 17:14:02 +11:00
Dale Weiler
be64736dd4 Fixes 2016-01-03 00:38:58 -05:00
Dale Weiler
f6bc9705d2 eh 2016-01-03 00:35:12 -05:00
Dale Weiler
5d8c18dcab Fix makefile 2016-01-03 00:34:29 -05:00
Dale Weiler
1a18ff5294 Merge branch 'master' into cleanup 2016-01-02 22:30:35 -05:00
Dale Weiler
3f4659b5d5 oops 2015-12-28 08:00:54 -05:00
Dale Weiler
6024e377ba Fix unary negation (-) 2015-12-28 07:58:54 -05:00
Wolfgang Bumiller
ee3c1e43c9 tempcommitting a whole bunch of to-c++ conversions 2015-05-02 09:48:24 +02:00
Wolfgang Bumiller
a9ac6987a6 remove a bunch of unnecessary c-casts to ast_expression* 2015-02-01 12:15:30 +01:00
Wolfgang Bumiller
fab640da4c Merge branch 'cleanup' of git://github.com/graphitemaster/gmqcc into cleanup 2015-02-01 12:13:59 +01:00
Wolfgang Bumiller
fd0cc40b9c fix std::string constructed from nullptr 2015-02-01 12:13:22 +01:00
Wolfgang Bumiller
6d4539814e ast_unary::make: safer double-negation optimization check 2015-02-01 12:13:05 +01:00
Wolfgang Bumiller
896d4c53a3 fix backward propagateSideEffect impl 2015-02-01 12:12:40 +01:00
Wolfgang Bumiller
d8e9b1b35d destructor call order is important here 2015-02-01 11:52:58 +01:00
Wolfgang Bumiller
66d908f39b ir_instr_delete_quick needs to clear _m_ops 2015-02-01 11:49:46 +01:00
Wolfgang Bumiller
45236a644f ast conversion mostly finished 2015-02-01 11:44:00 +01:00
Dale Weiler
fa21d85820 Same on the cleanup branch 2015-01-30 00:46:25 -05:00
Dale Weiler
e922403aa8 Don't allocate globals for constants that aren't read 2015-01-30 00:40:59 -05:00
Dale Weiler
ff37abb0c7 Constant folding for strings 2015-01-30 00:25:10 -05:00
Dale Weiler
90b5a6538a Merge branch 'cleanup' of github.com:graphitemaster/gmqcc into cleanup 2015-01-30 00:20:41 -05:00
Dale Weiler
866fc3e247 Constant folding for string comparisons too 2015-01-30 00:18:52 -05:00
Dale Weiler
41a76ab91d Fix for loops 2015-01-29 23:33:59 -05:00
Dale Weiler
b640049912 For now 2015-01-29 23:13:55 -05:00
Wolfgang Bumiller
9335bc2f4f BROKEN: more ast nodes converted 2015-01-29 20:29:34 +01:00
Wolfgang Bumiller
49f4fedecf add another test that we just didn't have anywhere else yet 2015-01-25 09:29:02 +01:00
Wolfgang Bumiller
6149f6a1d0 BROKEN: in the middle of converting ast nodes to c++ with constructors and methods 2015-01-25 09:24:26 +01:00
Wolfgang Bumiller
9d98805dfb a whole lotta 'm_'s 2015-01-24 12:25:46 +01:00
Wolfgang Bumiller
e7d1e701c4 why didn't gcc catch that... 2015-01-24 10:26:43 +01:00
Wolfgang Bumiller
5c64437189 fix for loops 2015-01-20 20:55:27 +01:00
Wolfgang Bumiller
5968e3faa0 for now just call the dtors like this 2015-01-20 20:33:07 +01:00
Wolfgang Bumiller
566e761546 more c++ migration for ast/ir/code; reached a working condition here 2015-01-20 20:25:56 +01:00
Wolfgang Bumiller
f09c6a5d63 temp committing major c++ification 2015-01-20 16:43:58 +01:00
Wolfgang Bumiller
794396df79 making ast nodes derive from ast_expression 2015-01-19 14:00:04 +01:00
Wolfgang Bumiller
380fb3d44f this can be a move 2015-01-19 13:46:30 +01:00
Wolfgang Bumiller
dedb3a49bd ast_expression: params -> type_params 2015-01-19 13:46:10 +01:00
Wolfgang Bumiller
9535805c02 renaming ast_function::vtype to function_type 2015-01-19 13:37:22 +01:00
Wolfgang Bumiller
44b0d7f658 ast_expression now derives from ast_node 2015-01-19 13:33:39 +01:00
Wolfgang Bumiller
1826971301 renaming some ast_node members before making ast_expression an ast_node to use the compiler to help find possible clashes 2015-01-19 13:32:26 +01:00
Dale Weiler
db9c37d18b Rewrite constant folder in C++ 2015-01-15 20:27:17 -05:00
Dale Weiler
7e0e041527 Forgot about this file 2015-01-15 18:12:54 -05:00
Dale Weiler
e2ba77a546 Rewrite intrinsic system in C++ 2015-01-15 18:11:41 -05:00
Dale Weiler
76278e8b97 s/NULL/nullptr/ 2015-01-15 15:18:33 -05:00
Dale Weiler
6e68526680 Use std::vector for static_names 2015-01-15 15:15:35 -05:00
Dale Weiler
0ecfe18f49 Cleanup 2015-01-15 15:11:30 -05:00
Dale Weiler
e8fbae4b3e Not needed 2015-01-15 15:10:02 -05:00
Dale Weiler
f38e6b48db Use std::vector for SYA 2015-01-15 15:08:50 -05:00
Dale Weiler
a1f13499f9 Use std::vector for break and continue ast blocks 2015-01-15 14:22:22 -05:00
Dale Weiler
539dc4a3dc Use std::vector for ast switch cases 2015-01-15 14:19:07 -05:00
Dale Weiler
2e037832d3 Use std::vector for ast blocks 2015-01-15 14:15:44 -05:00
Dale Weiler
987f765c20 std::vector for initlist 2015-01-15 14:07:26 -05:00
Dale Weiler
b345b4e21b Eliminate use of vec_ in intrin.cpp 2015-01-15 03:01:26 -05:00
Dale Weiler
9c31c53cc5 Eliminate use of vec_ in fold.c 2015-01-15 02:47:42 -05:00
Dale Weiler
fe95b28a35 More std::vector 2015-01-15 02:17:37 -05:00
Dale Weiler
317e0499f7 More std::vector 2015-01-15 01:57:40 -05:00
Dale Weiler
b5d8b44503 More std::vector 2015-01-15 01:35:56 -05:00
Dale Weiler
35a8c3c9af More std::vector migration 2015-01-15 01:22:21 -05:00
Dale Weiler
2e3b3569bf Stop using vec_* in testsuite code 2015-01-15 00:29:37 -05:00
Dale Weiler
878195bdec Use C++ naming for structures 2015-01-15 00:05:48 -05:00
Dale Weiler
aabefd1bfe Use C++ naming for structures 2015-01-14 23:56:52 -05:00
Dale Weiler
4de08db0e7 More std::vector migration 2015-01-14 23:45:00 -05:00
Dale Weiler
67a3c9b031 Initial movement to std::vector 2015-01-14 23:34:43 -05:00
Dale Weiler
d4deaa35ca Fast math is too fast for clang 2015-01-14 21:58:04 -05:00
Dale Weiler
51a7b8e6a7 Make travis update to newer compilers 2015-01-14 21:54:41 -05:00
Dale Weiler
65362d93aa .c -> .cpp 2015-01-14 21:48:47 -05:00
Dale Weiler
a7b45ea14d More cleanup 2015-01-13 21:46:52 -05:00
Dale Weiler
9d89a059aa More cleanup 2015-01-13 21:43:48 -05:00
Dale Weiler
dc510baf4f This is supposted in C99 2015-01-13 21:39:19 -05:00
Dale Weiler
b5ac2745d6 Remove license headers. The LICENSE file is sufficent 2015-01-13 21:38:40 -05:00
Dale Weiler
0a00807e57 More cleanup 2015-01-13 21:36:09 -05:00
Dale Weiler
ff526954b6 Minifi README 2015-01-13 21:30:23 -05:00
Dale Weiler
42b3640bc5 Remove these too 2015-01-13 21:29:09 -05:00
Dale Weiler
6caaedd269 Remove msvc project files and misc stuff 2015-01-13 21:28:26 -05:00
Dale Weiler
8b250457ab Remove hash.c 2015-01-13 21:27:36 -05:00
Dale Weiler
644a807731 Remove all the support stuff 2015-01-13 21:26:44 -05:00
Dale Weiler
724bca0eec Remove fs.c ansi.c and PORTING guide 2015-01-13 21:25:17 -05:00
Dale Weiler
2c421c3b71 Major cleanup of platform/fs stuff 2015-01-13 21:18:47 -05:00
Dale Weiler
5b9e0a62ab Add qcvm rule to makefile 2015-01-13 20:36:25 -05:00
Dale Weiler
d6bf906647 Update travis file 2015-01-13 20:30:28 -05:00
Dale Weiler
1ad849d939 Include dependencies in the makefile 2015-01-13 20:29:46 -05:00
Dale Weiler
044f8b396d Linker flags after objects 2015-01-13 20:27:45 -05:00
Dale Weiler
893f204b30 Remove stat_info calls 2015-01-13 20:25:44 -05:00
Dale Weiler
486b215706 Remove memory tracker 2015-01-13 20:25:01 -05:00
Dale Weiler
d8c09c200a Simpler hash function 2015-01-13 20:10:44 -05:00
Dale Weiler
e452c176b4 Remove MSVC support code. Simplified makefile 2015-01-13 20:07:17 -05:00
Dale Weiler
833f315a16 Remove gmpak 2015-01-13 19:55:49 -05:00
Dale Weiler
a77797d6a6 Remove spelling corrector 2015-01-13 19:48:57 -05:00
Dale Weiler
783b7b6594 Update license headers 2015-01-09 14:53:35 -05:00
Dale Weiler
114a1d3b14 Fix variable declarations in for-loop initializers 2015-01-08 23:42:46 -05:00
Dale Weiler
6fee3ec363 More comments 2015-01-06 20:39:20 -05:00
Dale Weiler
2b10d588e4 grammar 2015-01-06 20:33:31 -05:00
Dale Weiler
e3577912c8 Fix the soft float implementation. Comment it as well. 2015-01-06 20:30:17 -05:00
Dale Weiler
ac8c7d730a Merge branch 'cooking'
Conflicts:
	test.c
2014-12-10 02:43:42 -05:00
Dale Weiler
5d5b9a379a When storing to a vector member as part of an entity field we must use STOREP 2014-12-10 02:40:35 -05:00
Dale Weiler
8f7242d314 Implement support for #include MACRO and #include __LINE__ 2014-11-07 03:12:34 -05:00
Dale Weiler
103e549615 Don't emit whitespace when stringifying TOKEN_WHITE.
Other aspects of the preprocessor already skip whitespace leading up to a token. The only situation in which a TOKEN_WHITE can
exist as part of the token stream during stringification, is when the whitespace is trailing after a token. This is situation is
really only possible in the context of a macro argument. This behaviour is inconsistent.

Consider the following
FOO( space_before)
FOO(space_after )

The former will reduce to "space_before" since the preprocessor will skip whitespace leading up to the token `space_before', while
the latter will reduce to "space_after ".

The C preprocessor doesn't preserve whitespace, so we won't either. This doesn't break any existing code.
2014-11-07 02:01:17 -05:00
Dale Weiler
ab841b94f7 Allow negation to propagate inexactness in constant folder by using neg(x) = x*-1 2014-11-04 14:32:56 -05:00
Wolfgang Bumiller
624e6201e8 manpage/init: -fsplit-vector-parameters description 2014-10-18 14:39:14 +02:00
Wolfgang Bumiller
8b25e95553 we like to spell things properly - if this commit message contains a typo I don't catch before pushing then that's totally intentional 2014-10-18 14:27:16 +02:00
Wolfgang Bumiller
ddb0b7dd9d ir_builder_imm_float: add IR_FLAG_ERASEABLE 2014-10-18 14:25:28 +02:00
Wolfgang Bumiller
806850e408 ir_builder_imm_float: mark them as const, otherwise they end up getting saved 2014-10-18 13:53:15 +02:00
Wolfgang Bumiller
09109bb176 split-vectors test 2014-10-18 13:51:25 +02:00
Wolfgang Bumiller
3df51c5979 adding -fsplit-vector-parameters, todo: float-lookup should get optimized as commented 2014-10-18 13:49:13 +02:00
Wolfgang Bumiller
2a00b386ba renaming the length operator to _length and fixing the lexing of that operator, generic names for operators is really a bad idea 2014-10-18 13:47:23 +02:00
Dale Weiler
15b31e7dc5 Support text type escape sequences \b and \s. 2014-10-17 19:37:01 -04:00
Dale Weiler
fa7d44e0c7 Converting a literal to null pointer produces a warning 2014-10-16 22:55:16 -04:00
Dale Weiler
859e9fe3da Fix tests 2014-09-29 03:38:08 -04:00
Dale Weiler
de22dec56b Some fixes 2014-09-28 20:28:56 -04:00
Dale Weiler
641136fee3 Make it a function 2014-09-27 04:50:50 -04:00
Dale Weiler
b08195e2da Implemented length operator. This closes #130 2014-09-27 04:15:32 -04:00
Dale Weiler
31cd263e33 Implement ini [includes] area like Trac. This closes #65 2014-09-27 02:32:02 -04:00
Dale Weiler
a502a5453f Make that unsigned 2014-09-27 01:52:33 -04:00
Dale Weiler
2208136403 Implement support for indirect macro expansions in the preprocessor. This closes #36 2014-09-27 01:48:03 -04:00
Dale Weiler
faacfa018a silly clang warning is silly 2014-09-26 19:58:32 -04:00
Dale Weiler
1a8bb31d2a Fix hash strlen properly instead of blindly disabling it 2014-09-26 19:53:50 -04:00
Wolfgang Bumiller
459356a48d accidentally left those in 2014-09-26 15:32:14 +02:00
Wolfgang Bumiller
beaba494b5 For now I'll just disable this 2014-09-26 15:25:33 +02:00
Wolfgang Bumiller
3e576bd1f3 hopefully sanitize field creation logic a bit 2014-09-26 15:08:49 +02:00
Dale Weiler
25caf4b8e8 Fix 2014-08-11 20:59:34 -04:00
Dale Weiler
d5690074e1 Set name for is_varargs too. 2014-07-31 13:13:43 -04:00
Dale Weiler
823b053e60 Fix T...name 2014-07-31 12:37:26 -04:00
Dale Weiler
4c1c1bc051 Remove debug info from parse error. 2014-07-31 00:44:42 -04:00
Dale Weiler
bca1a7143d Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2014-07-31 00:43:42 -04:00
Dale Weiler
161bbec262 Parameter omitting in fteqcc is disallowed. 2014-07-31 00:43:08 -04:00
Wolfgang Bumiller
3e43056f5f fixing wrong paths in the uninstall target 2014-06-15 11:05:16 +02:00
Dale Weiler
c33755b007 Handle encoding errors for platform_vasprintf 2014-05-28 21:51:29 -04:00
Dale Weiler
e7d81937ae Make it compile as C++ code. 2014-05-26 21:36:13 -04:00
Dale Weiler
53e9ed0d96 Merge branch 'arithmetic_exceptions' into cooking
Conflicts:
	doc/gmqcc.1
	gmqcc.ini.example
	opts.def
	parser.c
2014-05-25 03:01:47 -04:00
Dale Weiler
05b349c72f Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2014-05-25 02:56:40 -04:00
Dale Weiler
463426ad47 Some fixes 2014-05-25 02:27:02 -04:00
Dale Weiler
655c2482c9 Fix vec3_cross. Added optimization to Makefile since we've been compiling gmqcc without it since forever. 2014-05-25 02:04:10 -04:00
Dale Weiler
0c85bac71b More work on vector arithmetic exceptions. 2014-05-25 02:00:41 -04:00
Dale Weiler
aed893b6b8 More work for arithmetic exception on vectors. 2014-05-24 23:21:20 -04:00
Dale Weiler
337d7ddbf4 soft float state defaults. 2014-05-24 22:40:14 -04:00
Dale Weiler
ff80bf1aa2 Only when arithmetic exceptions are enabled. 2014-05-24 22:13:47 -04:00
Dale Weiler
1497191e3c Perliminary work in arithmetic exception handling for vector operations in constant evaluator / folder. 2014-05-24 22:12:05 -04:00
Dale Weiler
3945f26d92 Put this back in global scope, we have a local scope test 2014-05-24 20:36:09 -04:00
Dale Weiler
4fa694fe82 Some CLZ for other toolchains. 2014-05-24 20:33:57 -04:00
Wolfgang Bumiller
edb38ce70e local compile-time const values are now created as globals, thus they're now subject to constant-folding 2014-05-24 19:13:49 +02:00
Wolfgang Bumiller
536138273f propagate the 'inexact' flag on when initializing a constant 2014-05-24 17:53:29 +02:00
Dale Weiler
68c2baa7c1 Mage inexact travel across constants. 2014-05-24 11:50:16 -04:00
Dale Weiler
05e20bcdda Some things. Fix testsuite as well. One test will fail (inexact). 2014-05-24 11:42:10 -04:00
Wolfgang Bumiller
f1ab19ba0b this should be NULL 2014-05-24 17:15:25 +02:00
Wolfgang Bumiller
b7b60e7468 Merge branch 'master' into cooking 2014-05-24 17:13:05 +02:00
Dale Weiler
bbeb2517c0 Arithmetic exception flag and a plethora of tests. 2014-05-24 10:38:02 -04:00
Dale Weiler
2917d39ef1 Don't forget the BSDmakefile too. 2014-05-24 10:04:14 -04:00
Dale Weiler
cc20d7e4e9 Disable stupid clang warning. 2014-05-24 10:02:58 -04:00
Dale Weiler
5dc7e62b19 Use flags instead. 2014-05-24 09:59:43 -04:00
Dale Weiler
6424ebaf98 Perliminary work on arithmetic exception handling in the constant evaluator. We can safely check for arithmetic underflow, overflow, divison by zero and inexactness now. Inexactness of expressions are propagated through the AST such that using an inexact value in a comparison will trigger a warning with -Winexact-compares. 2014-05-24 09:53:38 -04:00
Dale Weiler
7024ebfe7f Merge branch 'master' into cooking 2014-05-13 23:22:25 -04:00
Dale Weiler
a371c4ee27 On platforms that the byte order check fails on the runtime test is concluded instead. It still needs these swap functions at compile time since the runtime test has to run. This fixes a FTBFS on BE selected ARMs. 2014-05-09 02:39:25 -04:00
Wolfgang Bumiller
ba0ac97372 add tests for INSTR_STATE and -femulate-state 2014-04-08 14:35:11 +02:00
Wolfgang Bumiller
8dafdfc5e2 use INSTR_STATE by default, add -femulate-state to switch to emulation, and -state-fps=NUM to set its emulation FPS 2014-04-08 14:34:55 +02:00
Wolfgang Bumiller
0d8b0d419c implement INSTR_STATE in the qcvm 2014-04-08 14:34:26 +02:00
Dale Weiler
0d1a740bc7 Fix style 2014-04-08 05:06:16 -04:00
Dale Weiler
0db41f4279 Only increment the buffer location for macro output whitespace stripping if the situation is actually stripable, otherwise macros like #define foo(X) bar(#X), with foo(test) will expand to bartest) instead of bar(test). This should fix Xonotic builds. 2014-04-08 04:02:23 -04:00
Dale Weiler
15d1277158 Added memory protection to prevent mismatching of mem_d or vec_free on pointers which are otherwise unknown to be allocated memory or allocated vectors. Also fixed the preprocessor to only strip on ' ' and '\t' around macros. 2014-04-08 03:26:08 -04:00
Wolfgang Bumiller
2b7b2ea455 fix a silly macro issue 2014-04-07 14:28:11 +02:00
Wolfgang Bumiller
e8133893a0 Merge remote-tracking branch 'origin/master' into cooking 2014-04-07 14:23:35 +02:00
Dale Weiler
f1650c42d9 Match C's preprocessor semantics for token pasting with '##'. 2014-04-07 06:00:04 -04:00
Dale Weiler
606d7ac110 Eliminate debug log 2014-04-05 05:16:36 -04:00
Dale Weiler
90533079c8 Rework distro package build system. 2014-04-05 05:16:15 -04:00
Dale Weiler
fe14d1b056 Order 2014-04-05 02:53:03 -04:00
Dale Weiler
8250124c51 Consistency 2014-04-05 02:52:01 -04:00
Dale Weiler
8c0a280a3e Fixed Windows builds. Now we also build Win64 packages. 2014-04-05 02:50:07 -04:00
Dale Weiler
9e5d02dab0 Less parens 2014-03-17 10:24:48 -04:00
Dale Weiler
827826b9f9 Remove the qcint cast. 2014-03-17 10:23:13 -04:00
Dale Weiler
763e85b3ae Use powf instead of pow. 2014-03-17 09:43:17 -04:00
Dale Weiler
b21e967581 Fix left/right shift constant fold. 2014-03-17 09:41:53 -04:00
Dale Weiler
06e2cb2b1b Add qc_pow. 2014-03-17 09:39:59 -04:00
Wolfgang Bumiller
581c48e337 Merge pull request #142 from CurrentResident/big_endian_testsuite
Big endian testsuite
2014-02-23 12:31:01 +01:00
Jim Thoenen
56edc3db9c White space tweak 2014-02-22 22:21:29 -06:00
Jim Thoenen
52adc2113f Tweak for coding convention 2014-02-22 21:22:41 -06:00
Jim Thoenen
69b89dc6ac Allow testsuite to pass on big endian
Move the progs header and body byteswapping into util functions and
call those functions when either reading or writing the progs.
2014-02-10 20:31:54 -06:00
Wolfgang Bumiller
f7e074d88f Merge branch 'master' into cooking 2014-02-08 10:33:50 +01:00
Dale Weiler
7ffda37513 s/atanhf/atanh/ 2014-02-08 02:50:06 -05:00
Wolfgang Bumiller
24763aad65 moving the length multiplication for 64 bit types from util_endianswap into util_swap64; renaming length parameter to count 2014-02-02 11:04:18 +01:00
Dale Weiler
360389638b Merge pull request #141 from CurrentResident/big_endian_swap_fix
Big endian swap fix
2014-02-02 02:00:15 -08:00
Jim Thoenen
2ddb5ad50d Update per IRC peer review feedback
Restore the swap function's original name, remove convenience function,
use %u in log message, whitespace tweak.
2014-02-02 02:32:50 -06:00
Jim Thoenen
3070c03fc0 Oops, scale int64 count into int32 count for swapper. 2014-02-02 01:52:50 -06:00
Jim Thoenen
1bf9ebabcc Big-endian: Byteswap only the field contents when writing progs.dat
The previous code swapped not just the fields' contents themselves, but
also field positions within several of the structs, resulting in a
non-working progs.dat when compiled on big endian (ppc in my case).
Swapping on a field-by-field basis now.

Also:
* Addresses weird swap size requests (30+ bytes in one case)

* Take a guess at the right way to log a weird swap request before dying

* Fix swap array length scaling

* Rename the main swap function to reflect its native->little-endian
  purpose.  Figued that was okay because progs.dat is required to be
  always little-endian...

* Add a non-array version of the swap function for convenience
2014-02-02 00:57:02 -06:00
Wolfgang Bumiller
9cc4fe1ed2 Merge branch 'master' into cooking 2014-01-26 12:38:00 +01:00
Wolfgang Bumiller
fee2986907 Merge pull request #140 from Sicness/gmqcc.1-hyphen
Fix hyphen-used-as-minus-sign in gmqcc.1
2014-01-26 03:37:33 -08:00
Anton Balashov
669a055594 Fix hyphen-used-as-minus-sign in gmqcc.1
I: gmqcc: hyphen-used-as-minus-sign usr/share/man/man1/gmqcc.1.gz:338
N:
N:    This manual page seems to contain a hyphen where a minus sign was
N:    intended. By default, "-" chars are interpreted as hyphens (U+2010) by
N:    groff, not as minus signs (U+002D). Since options to programs use
minus
N:    signs (U+002D), this means for example in UTF-8 locales that you
cannot
N:    cut and paste options, nor search for them easily. The Debian
groff
N:    package currently forces "-" to be interpreted as a minus sign due
to
N:    the number of manual pages with this problem, but this is a
N:    Debian-specific modification and hopefully eventually can be
removed.
N:
N:    "-" must be escaped ("\-") to be interpreted as minus. If you
really
N:    intend a hyphen (normally you don't), write it as "\(hy" to
emphasise
N:    that fact. See groff(7) and especially groff_char(7) for details,
and
N:    also the thread starting with
N:
http://lists.debian.org/debian-devel/2003/debian-devel-200303/msg01481.html
N:
N:    If you use some tool that converts your documentation to groff
format,
N:    this tag may indicate a bug in the tool. Some tools convert dashes
of
N:    any kind to hyphens. The safe way of converting dashes is to
convert
N:    them to "\-".
N:
N:    Because this error can occur very often, Lintian shows only the
first 10
N:    occurrences for each man page and give the number of suppressed
N:    occurrences. If you want to see all warnings, run Lintian with the
N:    -d/--debug option.
N:
N:    Refer to /usr/share/doc/groff-base/README.Debian and the
groff_char(7)
N:    manual page for details.
N:
N:    Severity: wishlist, Certainty: possible")"
2014-01-26 12:14:18 +04:00
Dale Weiler
24f9313952 Screw clang 2014-01-07 13:13:25 -05:00
Dale Weiler
a140b749ff Fix lshift/rshift for runtime and const-fold consistency. 2014-01-07 12:58:53 -05:00
Wolfgang Bumiller
0f506e768b sometimes I hate travis 2014-01-07 15:04:29 +01:00
Wolfgang Bumiller
792c1afd95 Do not create coverage calls on array accessors. 2014-01-07 15:01:52 +01:00
Wolfgang Bumiller
4ff68e07e8 Adding coverage support:
The -coverage option causes all values have AST_FLAG_BLOCK_COVERAGE
set by default.
The coverage attribute can be used to control coverage:
It takes an optional list of coverage types, currently only "block"
and "none" is recognized.
[[coverage]] defaults to [[coverage(block)]].
Use [[coverage(none)]] or [[coverage()]] to disable.
2014-01-07 14:36:00 +01:00
Dale Weiler
5a160b0e88 Happy new year redux! 2014-01-01 06:25:00 -05:00
Dale Weiler
a934e0fe4b Happy new year! 2014-01-01 06:24:16 -05:00
Wolfgang Bumiller
b6b4a87cbf That's not how it should fail :P 2014-01-01 12:21:00 +01:00
Wolfgang Bumiller
acdc559d1f improved test of last attribute 2014-01-01 12:18:54 +01:00
Wolfgang Bumiller
5319caaaea definite -> last keyword; testcase updated too 2014-01-01 12:16:19 +01:00
Dale Weiler
0b6637cc67 Cleanup some code duplication. This whole parser ugh I just want to rm -rf all of it. Time for GMQCC2. 2014-01-01 05:32:24 -05:00
Dale Weiler
1e30c2b81d Remove final attribute and bareword. [[definite]] is now old [[final]]. There is no bareword definite either. 2014-01-01 05:12:21 -05:00
Dale Weiler
26ab792f9c More cleanup 2013-12-15 01:45:36 -05:00
Dale Weiler
7e88247ed5 hash cleanups. 2013-12-15 01:37:24 -05:00
Dale Weiler
f24bdced10 Remove SSE hash, t's just too much effort to maintain. 2013-12-14 17:30:51 -05:00
Dale Weiler
31e13e6e64 Fix some stuff 2013-12-14 15:07:04 -05:00
Dale Weiler
103bca7284 Partially fix that. 2013-12-14 14:57:10 -05:00
Dale Weiler
d43a270142 typo 2013-12-14 06:02:39 -05:00
Dale Weiler
4c5a0ff662 Do not include this function unless !defined(__SSE__) 2013-12-14 01:34:33 -05:00
Dale Weiler
4d4851e179 Faster hashing reaching 16 GB/s on Phenom II X4. 2013-12-14 01:23:39 -05:00
Dale Weiler
58cd326d85 Only optimize (a - (-b)) into (a + b) when the unary operand is a negation. This fixes (a - (!b)) being turned into (a + b). 2013-12-08 19:01:44 -05:00
Wolfgang Bumiller
50f905b821 adding 'final' 2013-12-06 22:41:15 +01:00
Dale Weiler
072bff44e6 Bitshifting operators <<, >>, and compound assignment versions now work in non-constant expressions 2013-12-03 17:40:15 -05:00
Dale Weiler
af53c0cb83 Mask out the math constant precedence stuff unless -fftepp-mathdefs 2013-12-01 10:52:42 -05:00
Dale Weiler
6a44b72db3 Mask ftepp math constants with a compiler flag 2013-12-01 10:45:43 -05:00
Dale Weiler
b20e2a9d34 User supplied math constants take precedence 2013-12-01 10:30:24 -05:00
Dale Weiler
11ecc6cb0b Ignore emitting implicit math constants in the preprocessor if they exist. 2013-12-01 10:26:36 -05:00
Dale Weiler
2024b3bd71 Merge branch 'master' into cooking 2013-11-30 13:14:04 -05:00
Dale Weiler
78b615fce5 Merge pull request #139 from ignatenkobrain/update_fedora
fedora: Update .spec and INSTALL
2013-11-30 10:13:26 -08:00
Dale Weiler
892746056e Merge pull request #138 from ignatenkobrain/fix_authors
s/brian/brain/ ;)
2013-11-30 10:13:19 -08:00
Dale Weiler
d14c757076 Merge pull request #137 from ignatenkobrain/fix_build_big_endian
fix build on big endian arches
2013-11-30 10:13:12 -08:00
Igor Gnatenko
320784b20d fedora: Update .spec and INSTALL
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-11-30 12:35:07 +04:00
Igor Gnatenko
7b7d012255 s/brian/brain/ ;)
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-11-30 12:31:21 +04:00
Igor Gnatenko
a20127b063 fix build on big endian arches
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-11-30 12:28:59 +04:00
Dale Weiler
9b92cb0897 Simplify 2013-11-29 13:50:06 -05:00
Dale Weiler
43e9885a08 Fix fold_op_cmp 2013-11-29 13:48:03 -05:00
Dale Weiler
ac7e1a557d Fixes 2013-11-29 13:36:35 -05:00
Dale Weiler
ea801acdb8 oops 2013-11-29 13:18:50 -05:00
Dale Weiler
4583cb8280 cleanup 2013-11-29 13:13:39 -05:00
Dale Weiler
cb97b7f672 Cleanup lexer old cruft 2013-11-29 07:15:49 -05:00
Dale Weiler
1d347eaf66 Handle byte order mark for unicode. (0xEFBBBF) 2013-11-29 07:03:55 -05:00
Wolfgang Bumiller
c3cc6f184e static variables now don't get re-initialized in functions; cannot be initialized with non-constants anymore; and a counter has been added so you can use the same name in a different scope for another static variable again. 2013-11-28 12:04:01 +01:00
Dale Weiler
bf127088ca Make log use the slightly improved algorithm for small values. 2013-11-25 14:08:05 -05:00
Dale Weiler
9749ec350a Reorder intrinsics table 2013-11-25 13:44:00 -05:00
Dale Weiler
e5fc8fdded out isn't used 2013-11-25 13:42:17 -05:00
Dale Weiler
2d0f0a3607 Never mind 2013-11-25 13:32:02 -05:00
Dale Weiler
25e86c04eb Only g++ is this retarded 2013-11-25 13:30:45 -05:00
Dale Weiler
f19d32b29b Another one 2013-11-25 13:26:24 -05:00
Dale Weiler
dc48af195d Pregenerate 2.0 for const folder since it's used often 2013-11-25 13:25:29 -05:00
Dale Weiler
33c0c83d59 Implemented __builtin_ln, __builtin_log, __builtin_log10, __builtin_log2 and __builtin_logb. This algorithm is nuts. 2013-11-25 13:21:27 -05:00
Dale Weiler
02c6076bfd Fix 2013-11-25 11:29:36 -05:00
Dale Weiler
3209aaa996 Implement __builtin_nan, __builtin_inf and __builtin_epsilon to generate machine nan, inf and epsilon values (at runtime). 2013-11-25 11:26:16 -05:00
Dale Weiler
8a26ed7664 Fix CRC16 2013-11-25 02:11:45 -05:00
Dale Weiler
50d1bfe783 Fix 2013-11-23 21:17:35 -05:00
Dale Weiler
63c0917d24 More compiler intrinsics for math functions 2013-11-23 21:14:13 -05:00
Dale Weiler
87a43777ab strength reduct (a - (-b)) into (a + b) 2013-11-23 13:13:21 -05:00
Dale Weiler
23904bad52 Better exp algorithm from divVerent 2013-11-23 12:45:22 -05:00
Dale Weiler
52cda620b2 Fix comments 2013-11-23 11:15:28 -05:00
Dale Weiler
1c33bcfceb Fixed pow 2013-11-23 11:14:42 -05:00
Dale Weiler
db182819ae Guard against nullfunc 2013-11-23 10:58:03 -05:00
Dale Weiler
ab2a4f1318 Some math constants 2013-11-23 10:31:51 -05:00
Dale Weiler
80adfebd23 Implement isinf intrinsic 2013-11-23 10:16:48 -05:00
Dale Weiler
aee68d80ea Cull back on the TODO 2013-11-23 08:02:56 -05:00
Dale Weiler
457a1b9690 Undefine macros after using them 2013-11-23 07:47:16 -05:00
Dale Weiler
943cb2ca64 Mark restrict on input too 2013-11-23 07:45:45 -05:00
Dale Weiler
556a84a46f Mark const for better generated code 2013-11-23 07:44:34 -05:00
Dale Weiler
b52cf4d47e Add comment abotu CRC16 2013-11-23 07:42:38 -05:00
Dale Weiler
e2bfaf8109 Implemented exp2 intrinsic 2013-11-23 07:37:26 -05:00
Dale Weiler
c68a5c29e1 Simplify 2013-11-23 07:27:09 -05:00
Dale Weiler
11f79bb1a6 Use '#' in nullfun identifier to prevent it from being used in code 2013-11-23 07:25:24 -05:00
Dale Weiler
54f331a64a Fix intrinsics for self-inclusion of other intrinsics. 2013-11-23 07:21:12 -05:00
Dale Weiler
74b58c5bb8 Cleaner handling since intrin_func deals with alias 2013-11-23 07:02:45 -05:00
Dale Weiler
292c8150b4 Resolve undefined functions to compiler builtins if they exist. 2013-11-23 06:57:40 -05:00
Dale Weiler
b1fd85b711 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-11-23 06:41:24 -05:00
Dale Weiler
d9572e3e30 Fixed pow/exp using fast approximation until the fractional part is hit. Once fractional is reached a binary search is used to get close to the value. 2013-11-23 06:40:27 -05:00
Wolfgang Bumiller
0860b7a68b crc16 slice-by-8 table generator code included for reference 2013-11-23 11:58:20 +01:00
Wolfgang Bumiller
759fca6921 slice-by-8 crc16 2013-11-23 11:50:30 +01:00
Dale Weiler
3b6e7d0ce1 indent 2013-11-23 03:54:11 -05:00
Dale Weiler
ae9d3d42cf A better mod implementation 2013-11-23 03:53:07 -05:00
Dale Weiler
29f2cc302b Add reference tool 2013-11-23 03:10:09 -05:00
Dale Weiler
7011a2ef2c Faster CRC16 algorithm based on the Slicing-by-8 algorithm, by Michael E. Kounavis and Frank L. Berry from Intel Corp. 2013-11-23 01:00:32 -05:00
Wolfgang Bumiller
ec03b55d1a now it parses and has the desired precedence 2013-11-16 14:34:24 +01:00
Wolfgang Bumiller
9131644412 ** precedence was wrong 2013-11-16 14:26:46 +01:00
Wolfgang Bumiller
49bb172a09 folder: change ~ for floats too 2013-11-14 11:41:11 +01:00
Dale Weiler
73c4015046 Fix unary minus on vector 2013-11-13 08:57:14 -05:00
Dale Weiler
1900262df4 Use a branch instead of math on enum types 2013-11-13 04:57:18 -05:00
Wolfgang Bumiller
f43106017f bit more concise 2013-11-12 16:28:11 +01:00
Wolfgang Bumiller
eb4486a7ac working fold_op_cmp implementation 2013-11-12 16:15:02 +01:00
Wolfgang Bumiller
1d5229ee8c vec3_not: be consistent with compile-time behavior here 2013-11-12 16:05:54 +01:00
Wolfgang Bumiller
eee7d0aac1 vec3_pbool: or, not and 2013-11-12 15:56:04 +01:00
Wolfgang Bumiller
de12a24bc9 folder: fix -fperl-logic 2013-11-12 14:39:25 +01:00
Wolfgang Bumiller
6ea88c9a3f subtracting != adding 2013-11-12 14:31:11 +01:00
Wolfgang Bumiller
de14d514f3 fix 0-x being turned into x 2013-11-06 16:57:04 +01:00
Wolfgang Bumiller
99de3cf4f5 regular procedure... bumping PKGBUILDs, GMQCC_VERSION macros, adding back GMQCC_VERSION_TYPE_DEVEL 2013-10-31 22:17:53 +01:00
Wolfgang Bumiller
7f2b2061e6 0.3.5 commit 2013-10-31 22:13:42 +01:00
Dale Weiler
1d745fd1f9 Merge branch 'cooking' 2013-10-31 08:22:54 -04:00
Wolfgang Bumiller
7a29f65683 Nothing in there requires unistd.h 2013-10-28 11:37:08 +01:00
Wolfgang Bumiller
1ca36b7e49 Revert "oh my god, make it stop >.<"
This reverts commit a120209567.
2013-10-27 20:11:41 +01:00
Wolfgang Bumiller
a120209567 oh my god, make it stop >.< 2013-10-27 19:19:11 +01:00
Wolfgang Bumiller
b1016c7f48 fold_binary now used instead of ast_binary_new, which calls fold_superfluous 2013-10-25 13:40:31 +02:00
Dale Weiler
91c894d4da Disable it on master too since Xonotic compiles are failing. 2013-10-24 11:56:23 -04:00
Wolfgang Bumiller
065a870e7a build again 2013-10-23 14:04:20 +02:00
Wolfgang Bumiller
b87eb89853 This is not allowed 2013-10-23 14:01:56 +02:00
Dale Weiler
c90807dec6 Some correctly-sized type flags for the AST and IR, this culls back memory usage a little. 2013-10-19 23:39:37 -04:00
Dale Weiler
0695ad1659 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-10-19 02:53:46 -04:00
Dale Weiler
b5b9559d6f Make preprocessor predefs use their own context opposed to the lexer context. 2013-10-19 02:52:47 -04:00
Wolfgang Bumiller
3988aae73e type and argument parsing improved to handle the field/vararg ambiguity; tests added 2013-10-18 16:28:28 +02:00
Dale Weiler
0f6c44d671 We're doing it this way. 2013-10-18 05:37:26 -04:00
Wolfgang Bumiller
8d5e719026 replacing the current [[accumulate]] implementation: shorter and simpler, and also supports non-void return types 2013-10-18 11:26:41 +02:00
Dale Weiler
0cfc275f82 Fix 2013-10-17 20:35:56 -04:00
Dale Weiler
c210340081 Undo fix and actually use a macro in the accumulation test .. just incase. 2013-10-17 20:34:16 -04:00
Dale Weiler
c675ba8086 Does this fix it? 2013-10-17 20:25:02 -04:00
Dale Weiler
9f54610fbd Implement support for octal constants, this closes #97. 2013-10-17 05:17:30 -04:00
Dale Weiler
02a1d9f4a1 Fix 'declaration does not declare anything' regression i.e this closes #132. 2013-10-17 05:06:09 -04:00
Dale Weiler
97217b55d1 Ignore generating a return instruction in accumulated functions, eventually we'll have a way to merge these into one function but for now the RETURN is a waste. 2013-10-17 04:45:24 -04:00
Dale Weiler
dd33f4e498 Update deps 2013-10-17 04:27:34 -04:00
Dale Weiler
f8949e17c8 Cleaner traces 2013-10-17 04:23:53 -04:00
Dale Weiler
d6f020fd6a Fix memory dump console printing alignment and also trace expressions for allocations. 2013-10-17 04:21:25 -04:00
Dale Weiler
05ac126d6f Use "##" to ensure the names of the accumulated functions are striped by the IR. 2013-10-17 03:47:26 -04:00
Dale Weiler
cfea900afd Update changes 2013-10-17 03:44:33 -04:00
Dale Weiler
8a9c4edce8 Add a test for function accumulation attribute 2013-10-17 03:43:05 -04:00
Dale Weiler
4da820ef61 Enforce void type on accumulatable functions. 2013-10-17 03:39:14 -04:00
Dale Weiler
2c975bb344 Implemented [[accumulate]] attribute. This will hopefully be used by Xonotic to replace it's ACCUMULATE_FUNCTION stuff. 2013-10-17 03:21:30 -04:00
Dale Weiler
1b14c49815 Use .dat extension on generated binaries in testsuite to prevent them from being sourced as task template files. This will fix the async builds on travis.ci 2013-10-17 00:18:07 -04:00
Dale Weiler
8699053887 Fix handling on intrinsic folding, this closes #118. 2013-10-17 00:14:42 -04:00
Dale Weiler
003bb9dfb4 Prevent aliasing functions through forward declared prototypes. This closes #125 2013-10-16 23:37:39 -04:00
Dale Weiler
0f479f3e88 Another one 2013-10-16 21:47:12 -04:00
Dale Weiler
c63bebd7d8 float and double shouldn't be used here, this is what qcfloat_t is for. This fixes the memcmp bug in the folder. 2013-10-16 21:32:31 -04:00
Dale Weiler
b147602d78 Fix option string allocated/non allocated storage. 2013-10-16 20:14:49 -04:00
Dale Weiler
f53502c9ca Make it valid C++ code, such that it can compile as C++ code. 2013-10-16 19:54:21 -04:00
Dale Weiler
50d165e173 Some intrinsic code cleanup. The args check is handled anyways in the parser. We use a generated array alongside to prevent generating the intrinsic multiple times instead of using static storage. Other various cleanups as well. 2013-10-16 00:04:39 -04:00
Dale Weiler
eca82511c6 divVerent suggestion to use memcmp here 2013-10-14 22:40:36 -04:00
Dale Weiler
6d8d7ee923 Make divVerent happy about handling divison by zero/inf/nan and negitive versions. This code now assumes IEEE 754. 2013-10-14 22:31:37 -04:00
Dale Weiler
c8413a9a04 Clang is so anal 2013-10-14 21:03:24 -04:00
Dale Weiler
8e8b3608fb Cleanups 2013-10-14 20:58:36 -04:00
Dale Weiler
65a2b83abd Cleanup for builds 2013-10-14 02:17:45 -04:00
Wolfgang Bumiller
19331ee385 who let the cat out? 2013-10-11 15:53:59 +02:00
Dale Weiler
ef51b30387 Fix windows builds, add strip target for makefiles, update distro build makefiles to use it for release builds. 2013-10-11 09:51:08 -04:00
Dale Weiler
f008cc257d Some cleanups 2013-10-11 09:32:46 -04:00
Dale Weiler
ccb46d7e3b Update README 2013-10-11 08:14:37 -04:00
Wolfgang Bumiller
42a9784804 Merge branch 'cooking' of git://github.com/graphitemaster/gmqcc into cooking 2013-10-11 14:11:40 +02:00
Wolfgang Bumiller
82afdb1e2c Merge branch 'cooking' of git://github.com/graphitemaster/gmqcc into cooking 2013-10-11 14:10:57 +02:00
Wolfgang Bumiller
62ac7e9966 first part of parsing TOKEN_DOTS as part of a type when needed; allows declarations like: ...float x; 2013-10-11 14:10:47 +02:00
Dale Weiler
6da151eba1 Update dependencies 2013-10-11 08:10:32 -04:00
Dale Weiler
856949a5f9 I need to test this code on msvc now. 2013-10-11 08:08:36 -04:00
Dale Weiler
d8b3faa871 Fix that (newer clang will fail on it) 2013-10-11 08:06:10 -04:00
Dale Weiler
92c0d6157c Merge branch 'cleanup' into cooking 2013-10-11 08:04:02 -04:00
Dale Weiler
fa14550d38 Last piece of documentation for platform.h 2013-10-11 08:02:28 -04:00
Dale Weiler
604c9d25bf More documentation for platform.h 2013-10-11 07:40:31 -04:00
Dale Weiler
4d0bf1607a Some documentation 2013-10-11 07:16:48 -04:00
Dale Weiler
63fdab8422 Some more cleanup 2013-10-11 06:36:05 -04:00
Dale Weiler
87d9371a5c Refactor some util/platform usage and extend file system file interface to accept its own flags and EOF 2013-10-11 06:12:56 -04:00
Wolfgang Bumiller
3d5fedcf39 distro/archlinux/this/Makefile: TARCOMP variable contains the compression flag, rather than using -J in the makerule but provide the .xz extension in a variable 2013-10-11 11:17:03 +02:00
Wolfgang Bumiller
637651f4e1 distro/archlinux/this/Makefile: tar -> bsdtar 2013-10-11 11:14:46 +02:00
Dale Weiler
e9bde1e4e4 Add back the correct directory handling for msvc 2013-10-11 05:09:55 -04:00
Dale Weiler
34c18ab860 Make it compile with mingw32 again 2013-10-11 04:58:49 -04:00
Dale Weiler
dab528acda Add a porting guide 2013-10-11 04:55:26 -04:00
Dale Weiler
e8955f17ea More cleanups, gmqcc.h doesn't need to include stdio.h now! 2013-10-11 04:06:52 -04:00
Dale Weiler
033cf7c7d3 More cleanups 2013-10-11 03:59:25 -04:00
Dale Weiler
5138a25420 More cleanup 2013-10-11 03:21:44 -04:00
Dale Weiler
12a864abf5 Some more platform / compiler specific code refactoring. 2013-10-11 03:02:38 -04:00
Dale Weiler
151606e255 Initial platform / compiler specific code refactoring. 2013-10-11 02:39:30 -04:00
Dale Weiler
14ef6a1c42 This can actually be much smaller, 204 bytes! 2013-10-11 00:22:27 -04:00
Dale Weiler
9dabb68d7f More typos 2013-10-10 22:12:03 -04:00
Dale Weiler
f73f2f1ba9 typo 2013-10-10 22:11:03 -04:00
Dale Weiler
e263506b3f Document what the utf8 table actually is 2013-10-10 22:10:36 -04:00
Dale Weiler
3e362e872c Wrong operand order it's 0xf4u-0xc2u i.e 0x32. 2013-10-10 22:03:13 -04:00
Dale Weiler
f83cc1b91d Less flexible more economical utf8 decoder. 2013-10-10 21:44:40 -04:00
Dale Weiler
6bd6379c87 Don't echo it 2013-10-05 23:39:05 -04:00
Dale Weiler
a02e44100e Fix some things: get all the Quake mods to compile again (I broke binary expressions .. oops) Fix the check-proj script, using $? for status was invalid because of pipes. The ir now properly considers negation virtual instruction to be operations (as it should). 2013-10-05 23:36:48 -04:00
Dale Weiler
99e3ae9773 Update CHANGES files 2013-10-05 22:34:55 -04:00
Dale Weiler
300fb9905b Fix fold_superfluous 2013-10-04 07:10:58 -04:00
Dale Weiler
ffdd6df828 Only when peephole optimization is on 2013-10-04 07:02:06 -04:00
Dale Weiler
2cf5046d38 Handle proper expression type assignment 2013-10-04 06:53:09 -04:00
Dale Weiler
cc69370575 Another peephole optimization which removes superfluous expressions such as (A + 0), (A - 0), (A * 1) and (A / 1). 2013-10-04 06:46:54 -04:00
Dale Weiler
263fcfbc2f Refactor intrinsic stuff 2013-10-02 13:00:34 -04:00
Dale Weiler
2ebf571129 Update documentation 2013-09-30 16:03:22 -04:00
Dale Weiler
90824c2093 Add seperate warning flag for directive in macro. 2013-09-30 15:59:36 -04:00
Dale Weiler
8f359f3849 Warn when preprocessor directive is found inside a macro body. 2013-09-30 15:57:01 -04:00
Dale Weiler
08891068c8 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-09-30 14:33:57 -04:00
Dale Weiler
b6f08e7fb1 Fix negation type for VINSTR_NEG_V. Source operand for optimization instead of the expression (to handle double negation elision properly.) 2013-09-30 14:32:21 -04:00
Wolfgang Bumiller
fa14ca93d2 Merge branch 'master' into cooking 2013-09-30 15:02:03 +02:00
Wolfgang Bumiller
dfbd093348 Merge pull request #134 from Sicness/hyphen
Fixed hyphen-used-as-minus-sign in gmqcc.1
2013-09-30 06:01:22 -07:00
Anton Balashov
e928cabfb2 Fixed hyphen-used-as-minus-sign in gmqcc.1
Accortding to lintian report:
I: gmqcc: hyphen-used-as-minus-sign usr/share/man/man1/gmqcc.1.gz:156
N:
N:    This manual page seems to contain a hyphen where a minus sign was
N:    intended. By default, "-" chars are interpreted as hyphens (U+2010) by
N:    groff, not as minus signs (U+002D). Since options to programs use minus
N:    signs (U+002D), this means for example in UTF-8 locales that you cannot
N:    cut and paste options, nor search for them easily. The Debian groff
N:    package currently forces "-" to be interpreted as a minus sign due to
N:    the number of manual pages with this problem, but this is a
N:    Debian-specific modification and hopefully eventually can be removed.
N:
N:    "-" must be escaped ("\-") to be interpreted as minus. If you really
N:    intend a hyphen (normally you don't), write it as "\(hy" to emphasise
N:    that fact. See groff(7) and especially groff_char(7) for details, and
N:    also the thread starting with
N:    http://lists.debian.org/debian-devel/2003/debian-devel-200303/msg01481.html
N:
N:    If you use some tool that converts your documentation to groff format,
N:    this tag may indicate a bug in the tool. Some tools convert dashes of
N:    any kind to hyphens. The safe way of converting dashes is to convert
N:    them to "\-".
N:
N:    Because this error can occur very often, Lintian shows only the first 10
N:    occurrences for each man page and give the number of suppressed
N:    occurrences. If you want to see all warnings, run Lintian with the
N:    -d/--debug option.
N:
N:    Refer to /usr/share/doc/groff-base/README.Debian and the groff_char(7)
N:    manual page for details.
N:
N:    Severity: wishlist, Certainty: possible
N:
N:    Check: manpages, Type: binary
N:
I: gmqcc: hyphen-used-as-minus-sign usr/share/man/man1/gmqcc.1.gz:354
I: gmqcc: hyphen-used-as-minus-sign usr/share/man/man1/gmqcc.1.gz:676
2013-09-30 16:43:57 +04:00
Dale Weiler
03b56bd41f Handle double negation case specially. Update TODO 2013-09-30 05:12:28 -04:00
Dale Weiler
7249c2ec18 Simplify parse stage for unary - operator. 2013-09-29 22:08:09 -04:00
Dale Weiler
353455e1ad Remove pointless thinking comment, fix builds for clang. 2013-09-29 22:06:26 -04:00
Dale Weiler
b10de1b240 Make unary - operator act as an ast_unary node. This allows for consistency (no sense in making unary use binstore nodes, it doesn't make much sense). It also allows for the peephole optimization on unary chains that cancel each other to take place; i.e code like "-(-a)" simplifies to "a", thus eliminating instructions. 2013-09-29 22:01:46 -04:00
Dale Weiler
3c931ecbf1 Eh, only if peephole optimizations are turned on. 2013-09-28 06:41:40 -04:00
Dale Weiler
c6056d441b Less casts. 2013-09-28 06:36:00 -04:00
Dale Weiler
7c25af973c It was much easier in the AST, really. 2013-09-28 06:33:15 -04:00
Dale Weiler
81df8fa139 Remove the rest of it. 2013-09-28 06:10:02 -04:00
Dale Weiler
8a294683bb Remove it, maybe it can be done in the AST instead. 2013-09-28 06:09:24 -04:00
Dale Weiler
c4e92df106 Eh. 2013-09-28 05:36:09 -04:00
Dale Weiler
2b3663e18d Optimize for superfluous cases of NOT, i.e !!!!x can be simplified to !!x. 2013-09-28 05:34:53 -04:00
Dale Weiler
0d1f20fea3 Move it over 2013-09-28 03:41:18 -04:00
Igor Gnatenko
95b7056427 Optimizng compile flags
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-09-28 03:37:58 -04:00
Igor Gnatenko
c8a1b6563e Update to 0.3.0 (improved new package: gmqpak)
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-09-28 03:37:58 -04:00
Igor Gnatenko
48211572e5 Initial release
Add spec and patch

Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-09-28 03:37:58 -04:00
Dale Weiler
d61c5d3b16 Fix alias type check 2013-09-26 08:09:55 -04:00
Dale Weiler
15b0555546 Implement constant folding on ternary operations via fold_cond. 2013-09-26 06:51:49 -04:00
Dale Weiler
cf2352893f Consistency 2013-09-25 16:19:33 -04:00
Dale Weiler
894e1976e3 Cheap quick hack for ignoring #pragma to EOL 2013-09-25 15:35:18 -04:00
Wolfgang Bumiller
904c45060b remove -printf option from find; remove the misplaced 'local's 2013-09-25 11:16:15 +02:00
Wolfgang Bumiller
87fcf8d8e8 there's no pushd/popd in my sh 2013-09-25 11:14:59 +02:00
Dale Weiler
d2405a9ad8 Some grammar 2013-09-25 04:24:09 -04:00
Dale Weiler
d664b9f607 Fix some stuff for xonotic and make check-proj actually use the options line correctly. 2013-09-25 04:23:06 -04:00
Dale Weiler
13ef558fff Add export utility for Nexuiz, now check-proj handles it. 2013-09-25 04:03:37 -04:00
Dale Weiler
3968dc84fd Got Xonotic stuff for check-proj to function. 2013-09-25 03:52:48 -04:00
Dale Weiler
330111d5fc Fix the xonotic export script for check-proj.sh 2013-09-24 07:53:51 -04:00
Dale Weiler
fac4e411bf Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-09-24 07:32:23 -04:00
Dale Weiler
73eca0848c Fix QuakeWorld compilation by treating assignment to constants as a warning when -std=qcc. 2013-09-24 07:31:53 -04:00
Dale Weiler
37a4265e06 Update .travis.yml 2013-09-22 08:43:47 -04:00
Dale Weiler
69efb404bf Update .travis.yml 2013-09-22 08:43:24 -04:00
Wolfgang Bumiller
99422d0cf4 this is still there twice... 2013-09-19 21:05:40 +02:00
Wolfgang Bumiller
8d2a6ca419 moving the QCVM_EXECUTOR ifdef in conout.c - these are used in the executor 2013-09-19 21:05:39 +02:00
Dale Weiler
f25fff1e3d Remove debug printfs 2013-09-18 19:18:10 -04:00
Dale Weiler
e18849fa42 Generate (non_const_float * (1.0 / constant_float)) for (non_const_float / constant_float) expressions. 2013-09-18 19:15:24 -04:00
Wolfgang Bumiller
5a47dd5e62 since we don't bail on some of the warnings right away, (that is, with -Werror), also check the compile_errors count in main rather than just the return values 2013-09-18 16:20:25 +02:00
Wolfgang Bumiller
b6da3613ac making irwarning warn on an unused result 2013-09-18 16:20:24 +02:00
Dale Weiler
241637a980 Don't need that, each directory already has its own progs.src 2013-09-12 17:18:47 -04:00
Dale Weiler
9726d80e05 Output the dat name for xonotic export tool (first line of prog.src) 2013-09-12 17:08:40 -04:00
Dale Weiler
94e477e466 Added -progsrc commandline switch to specify progs.src files of different names. Cleaned up xonotic export script, fixed check-doc on linux systems by disabling mandoc check. 2013-09-12 17:06:20 -04:00
Dale Weiler
5bb245a33a Added xonotic_export.sh utility that when run from a xonotic-data.pk3dir will eliminate redundant files and create prog.src files for csprogs, progs(server) and menu. This tool will be used for check-proj.sh for exporting xonotic changes to our server. 2013-09-12 15:06:36 -04:00
Dale Weiler
6a235dc25f Support options for check-proj now 2013-09-11 17:09:03 -04:00
Dale Weiler
207d391fcd Allow running from root of gmqcc repo as well. 2013-09-11 16:50:33 -04:00
Dale Weiler
f44c127fbd Proper gmqcc sourcing for check-proj 2013-09-11 16:48:01 -04:00
Dale Weiler
c52ad67a7c Test for gmqcc in check-proj 2013-09-11 16:38:18 -04:00
Wolfgang Bumiller
35f9aef729 fix: declaring locals with the name of a parameter now treats the parameter as the local's prototype to avoid it being double-freed later 2013-09-11 11:25:44 +02:00
Dale Weiler
46fa12cb26 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-09-10 19:16:14 -04:00
Dale Weiler
8ddd126378 Added check-proj misc tool that downloads various QuakeC projects and tries to compile them with gmqcc, sort of like an additional test. 2013-09-10 19:15:28 -04:00
Wolfgang Bumiller
ce07e8fe28 distro/archbsd/this - as we don't depend on glibc there, just libc; also changed DESTDIR in archlinux/this/Makefile so it can be easily changed from the bsd Makefile 2013-09-09 12:18:30 +02:00
Wolfgang Bumiller
7af8c70bf9 distro/archlinux/this: generate the .MTREE file 2013-09-09 12:08:57 +02:00
Wolfgang Bumiller
3f151321f6 qcvm: exit on error 2013-09-08 21:31:56 +02:00
Dale Weiler
c2cf41baf9 Merge branch 'master' into cooking 2013-09-08 13:05:20 -04:00
Dale Weiler
9908209f58 Fix dependincies 2013-09-08 13:04:07 -04:00
Dale Weiler
6800d15872 Always print the char the lexer fails on for a token. 2013-08-31 16:52:46 -04:00
Dale Weiler
b2c8f3ebc5 Vector cross product virtual instruction, now >< operator works for non-constant vectors. Thanks divVerent for the help. 2013-08-31 14:49:06 -04:00
Dale Weiler
64661f54ea Implemented >< (vector cross product operator). Currently support for constants only. 2013-08-31 13:41:25 -04:00
Dale Weiler
69252071ba Prevent divide by zero for / and % operations in constant folding (previously caused compiler SIGFPE), instead "inf" is generated for both cases. This closes #124 2013-08-31 12:57:24 -04:00
Dale Weiler
9032e78349 There is no bug since the testsuite uses -o for preprocessed output (thus the printf never gets involved) if the testsuite read the preprocessor output from stdout than things would be wrong, since however it isn't there is no bug. 2013-08-31 09:53:19 -04:00
Wolfgang Bumiller
702a7664de Don't allow a stale 'some_type;' declaration without an actual variable name; Same for typedef; closes #119 2013-08-31 11:35:12 +02:00
Wolfgang Bumiller
2ff9adecb2 this one can be reached - make it a little more helpful 2013-08-31 10:55:03 +02:00
Wolfgang Bumiller
4600f1d7ff more thorough check for whether an ast node starts a new label; closes #121 2013-08-31 10:48:24 +02:00
Wolfgang Bumiller
79219ae201 factor check for assignment-to-constant into a function; improve its error output; closes #122 2013-08-31 10:39:31 +02:00
Wolfgang Bumiller
87b9fca732 fix unhelpful error message; fixes #123 2013-08-31 10:19:10 +02:00
Dale Weiler
98cb23ca63 Logic elsewhere handles this (no need to duplicate) 2013-08-30 07:23:15 -04:00
Dale Weiler
a50635bcd7 intrinsic folding cleanups (and improvements.) 2013-08-30 07:12:16 -04:00
Dale Weiler
76c37d9cc0 Rid of util_debug 2013-08-30 06:49:24 -04:00
Dale Weiler
c8b4eac618 Make -fshort-logic -funtyped-nil -fvariadic-args default for -std=gmqcc 2013-08-29 07:56:22 -04:00
Dale Weiler
f8af7adcd7 Remove &~= operator from gmqccs operator table, only fteqcc supports it. 2013-08-29 07:19:19 -04:00
Dale Weiler
dd289ed0e1 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-08-29 07:08:03 -04:00
Dale Weiler
3ed200d08a Some changes changes 2013-08-29 07:07:43 -04:00
Wolfgang Bumiller
ff6d55aafc this should allow for better detection of precedence issues 2013-08-29 10:22:48 +02:00
Wolfgang Bumiller
fa468e0673 also warn about mixing logical and/or operations without parenthesis 2013-08-29 08:26:17 +02:00
Wolfgang Bumiller
f140c39063 warn when mixing different bitops without parenthesis around them 2013-08-29 08:18:06 +02:00
Dale Weiler
51ef277e21 Fix folding logic for conditions. 2013-08-29 00:18:48 -04:00
Dale Weiler
a7c1f6f021 Implement [[eraseable]] attribute. When used with a function it instructs the AST (which than transfers logic to the IR) that the function (or variable) is potentially unused (verified by checking the read count). This than propogates through the IR and prevents the IR from generating both the definition and global/function. The intrinsics system uses this as well to prevent intrinsic functions from being generated unless they're used. 2013-08-29 00:05:37 -04:00
Dale Weiler
ceb79f1897 Fix build on clang 2013-08-28 13:01:46 -04:00
Dale Weiler
3b4a5667ea Constant fold intrinsics if their arguments are constant. TODO: reference count intrinsics such that they're not generated unless they're used, currently when an intrinsic can be folded-away it's marked for generation and makes it to the final output binary even though it isn't used. 2013-08-28 12:46:22 -04:00
Dale Weiler
bbe4927a20 Implemented a __builtin_fabs intrinsic. 2013-08-28 11:28:27 -04:00
Dale Weiler
ee428b9081 Fix fold-dce for if(0) 2013-08-28 10:39:48 -04:00
Wolfgang Bumiller
40bcec5044 Add missing -width to .Bl in doc/gmqpak.1 2013-08-28 14:40:23 +02:00
Wolfgang Bumiller
a80aa89e09 Fix bad use of .D1 in doc/qcvm.1 2013-08-28 14:38:51 +02:00
Wolfgang Bumiller
660a22d647 misc/check-doc.sh: run mandoc -Tlint -Wall on the manpages 2013-08-28 14:33:09 +02:00
Wolfgang Bumiller
494c30a239 allow initializing shadowed locals outside of -std=gmqcc - in this case it becomes a regular assignment to the old declaration which is consistent with fteqcc 2013-08-28 14:20:33 +02:00
Dale Weiler
71e7db63aa Cleanups 2013-08-28 03:45:40 -04:00
Dale Weiler
8aaa268423 Handle return status from compiler, this fixes false positivies in the testsuite when the compiler segfaults and the testsuite still reports succeeded, now it won't hopefully. 2013-08-28 03:40:35 -04:00
Dale Weiler
a75746d610 Don't ignore empty newlines when match in the testsuite, instead only ignore when procedure type is -pp (i.e preprocessing). 2013-08-28 03:34:05 -04:00
Dale Weiler
045bd4dbda Some style fixes for tests 2013-08-27 06:41:03 -04:00
Dale Weiler
28cd3a3f8f Forgot this one 2013-08-27 06:39:51 -04:00
Dale Weiler
f21216ecad A test for that xor stuff (the same one I used to cause the bug to manifest in the first place). 2013-08-27 06:35:58 -04:00
Rudolf Polzer
abfe98ce8a Fix XOR maths for overlapping inputs by setting the lifetimes correctly.
Signed-off-by: Rudolf Polzer <divverent@xonotic.org>
2013-08-27 12:27:20 +02:00
Wolfgang Bumiller
988b4b4960 ast_binary->right_first and an execution order check 2013-08-27 10:42:13 +02:00
Dale Weiler
4937fa51c0 Merge divVerent/ftypeless-stores, but rid of the macro abuse. 2013-08-27 04:28:22 -04:00
Dale Weiler
1b3d515777 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-08-27 04:28:11 -04:00
Wolfgang Bumiller
b26f53125d error on uninitialized arrays of unspecified size; otherwise it errors about a size overflow 2013-08-27 10:19:05 +02:00
Wolfgang Bumiller
844e84fc16 bail out when encountering an invalid array size in the ast as it's likely to cause breakage when trying to generate them anyway 2013-08-27 10:09:31 +02:00
Dale Weiler
581d0dfc15 Merge branch 'divVerent/ftypeless-stores' of git://git.xonotic.org/xonotic/gmqcc into cooking 2013-08-27 04:07:17 -04:00
Wolfgang Bumiller
147a6df629 fix testcase workarounds 2013-08-27 10:00:24 +02:00
Dale Weiler
b3c1b46925 And there she goes, them space swallowing whores. 2013-08-27 03:57:09 -04:00
Rudolf Polzer
f4f805f4c9 New options: -ftypeless-stores and -fsort-operands
These flags reduce entropy, but not size, of the generated assembly
code. This helps compressability of the files.

Additionally, -ftypeless-stores might SLIGHTLY improve engine
performance due to less instructions being used (so branch prediction
might work better). Probably cannot be measured though.

Signed-off-by: Rudolf Polzer <divverent@xonotic.org>
2013-08-27 09:55:00 +02:00
Dale Weiler
fc57fa4064 Add support for columns to LNOF files. 2013-08-26 14:14:33 -04:00
Dale Weiler
0e077c6e42 Fix testsuite for when a process crashes (do not consider it a success) 2013-08-26 13:10:38 -04:00
Dale Weiler
a1f1ec6d65 Fix testsuite 2013-08-26 13:05:54 -04:00
Wolfgang Bumiller
ba94df47f0 reset the column counter on a newline 2013-08-26 18:53:09 +02:00
Dale Weiler
454234ef5f Merge branch 'divVerent/submit/vector-bitops' of git://git.xonotic.org/xonotic/gmqcc into cooking 2013-08-26 12:36:17 -04:00
Rudolf Polzer
e50b7a2719 Support vector bitor/bitand/bitxor.
Signed-off-by: Rudolf Polzer <divverent@xonotic.org>
2013-08-26 18:32:28 +02:00
Wolfgang Bumiller
5958687795 error when trying to pass a TYPE_NOEXPR value to ir_instr_op 2013-08-26 10:23:20 +02:00
Wolfgang Bumiller
69cecb74df ir_builder now has a vinstr_temp array, a bunch of temps (currently 1) which can be used for virtual instruction translation 2013-08-26 10:23:03 +02:00
Dale Weiler
95138b1e5b Some typos 2013-08-21 23:28:49 -04:00
Dale Weiler
efa571043b Make makes output consistent with BSD makes output for make 2013-08-21 09:49:26 -04:00
Wolfgang Bumiller
4990434db7 archlinux PKGBUILDs: don't use install's -D switch - now they should work for both ArchLinux and ArchBSD 2013-08-21 10:45:28 +02:00
Dale Weiler
bbab8969d1 Generate PDF documentation from man pages for windows releases. 2013-08-21 04:29:33 +00:00
Dale Weiler
834e8d0d7d Mark the beginning of the next release, master is now stable. 2013-08-19 23:31:57 +00:00
Dale Weiler
a7fdbbe35b Fix that 2013-08-19 23:18:03 +00:00
Dale Weiler
6a4e175f86 Slackware support to website generation. 2013-08-19 23:15:41 +00:00
Dale Weiler
a93a28230d Merge pull request #117 from matthiaskrgr/master_PKGBUILD
Master pkgbuild
2013-08-19 16:06:03 -07:00
Matthias Krüger
701363347f Merge remote-tracking branch 'upstream/master' into master_PKGBUILD 2013-08-20 00:06:01 +02:00
Matthias Krüger
a1a9438319 PKGBUILD: release: update 2013-08-20 00:04:55 +02:00
Matthias Krüger
491a706610 PKGBUILD: git: update 2013-08-19 23:50:10 +02:00
Dale Weiler
963e93e8e8 This should be the tag 2013-08-19 21:38:18 +00:00
Dale Weiler
c13285092c Mark release, ready to tag it and bag it. 2013-08-19 21:34:49 +00:00
Dale Weiler
ccd8f1acc6 Added style + indent rule, fixed some indenting as well 2013-08-19 02:16:16 +00:00
Dale Weiler
a31eacf1bd Newline rule 2013-08-19 00:59:41 +00:00
Dale Weiler
e15046d66c Please the Samual 2013-08-18 23:44:23 +00:00
Dale Weiler
78a3c5d571 Fix that rule 2013-08-17 23:50:21 +00:00
Dale Weiler
e6809acf63 Added whitespace fix rule to include.mk 2013-08-17 23:49:47 +00:00
Dale Weiler
c64005966f Remove some trailing whitespace 2013-08-17 23:43:41 +00:00
Dale Weiler
2a79339735 Remove that idiom, and use GMQCC_ARRAY_COUNT. 2013-08-17 23:39:06 +00:00
Dale Weiler
dd512ec36a Forgot about this one 2013-08-17 22:19:40 +00:00
Dale Weiler
e7dab06f82 They don't go there, fuck you grep. 2013-08-17 22:17:14 +00:00
Dale Weiler
94139513db Cleanups and update CHANGES 2013-08-17 22:16:40 +00:00
Dale Weiler
7108c61bec Fix the build 2013-08-16 09:09:56 +00:00
Dale Weiler
772dbfae26 Make it compile in visual studio again, without warnings. 2013-08-16 09:03:36 +00:00
Dale Weiler
b30c3ff8d4 Update documentation 2013-08-16 08:16:03 +00:00
Dale Weiler
d5d38e94ef Some testing for valgrind in the makefile 2013-08-16 07:33:57 +00:00
Dale Weiler
89893f9a24 Valgrind integration for our memory allocator. 2013-08-16 07:22:01 +00:00
Dale Weiler
079ed491a9 Update the ini example, holy hell we have more options than I imagined. 2013-08-16 04:22:53 +00:00
Dale Weiler
a622d5163b Rework some build stuff for better output and to enable strict prototypes 2013-08-16 03:28:02 +00:00
Dale Weiler
7df42c95d2 Make our allocator slightly faster with branch hinting. 2013-08-15 06:09:28 +00:00
Dale Weiler
91c7209146 Track constant folds in opts_optimization list .. this could be handled better I assume. 2013-08-15 03:45:50 +00:00
Dale Weiler
ade8626df7 Perform some strict aliasing all over this biatch. We ain't trippin on code that breaks it. 2013-08-14 10:16:04 +00:00
Wolfgang Bumiller
3ece4a964f remove the 'opts' global from test.c and exec.c as opts.c defines it and is linked into both the testsuite and qcvm 2013-08-14 12:09:26 +02:00
Dale Weiler
586a70ea1d Handle some more errors 2013-08-14 07:41:09 +00:00
Dale Weiler
bee14a6df7 Some bug fixes 2013-08-14 07:19:49 +00:00
Dale Weiler
0a5353532b Remove my MT impl for PRNG, it's full of buffer overflows that I don't want to fix. Just fallback to using srand/rand 2013-08-14 06:22:32 +00:00
Dale Weiler
1201f06a55 Remove vec_upload 2013-08-14 06:19:48 +00:00
Dale Weiler
f82097b6b8 Update deps 2013-08-14 06:12:43 +00:00
Dale Weiler
73d9aa29c4 Made intrinsics seperate from the parser. 2013-08-14 06:02:15 +00:00
Dale Weiler
85ee52128c Fix 2013-08-14 04:27:11 +00:00
Dale Weiler
a68f0fcb35 Cleanups 2013-08-14 04:24:06 +00:00
Dale Weiler
5e54db46c4 Some statistics as Samual wanted. 2013-08-14 04:08:00 +00:00
Dale Weiler
b654594adb Disable statistics that are irrelevant to QuakeC coders 2013-08-14 03:24:00 +00:00
Dale Weiler
b10a2d1fd5 Remove the attempt at ast_intrinsic node 2013-08-14 03:05:14 +00:00
Dale Weiler
216330a7e2 Some intrinsic cleanups 2013-08-14 03:03:49 +00:00
Dale Weiler
90e2e5a4ad Some typos 2013-08-14 02:07:12 +00:00
Dale Weiler
7669a99c7f increment the optimization counter for DCE'd folds, also enable -O3 for compilation. 2013-08-01 14:24:10 +00:00
Dale Weiler
69c4dce477 Testsuite now returns the correct value on test failures (also prints how many tests failed .. if any fail) 2013-08-01 07:20:02 +00:00
Dale Weiler
db69d14995 Disable the macros to keep clang happy (just uncomment them for when more constant folding optimizations need them) 2013-08-01 07:12:21 +00:00
Dale Weiler
6f749d61b1 Added -Oconst-fold-dce (dead code elimination optimization for when constant expressions form the basis of the dead code, i.e if else with constant expression). Fixed deps and added documentation. Cleaned up folds for ir_value (can now use the same macros as the ast_value ones). 2013-08-01 07:07:59 +00:00
Dale Weiler
24fc2e5146 Fix that typecast 2013-07-31 19:36:09 +00:00
Dale Weiler
10b75fd8b9 Move const-branch-elision into fold.c 2013-07-31 19:34:38 +00:00
Dale Weiler
3e24b5a74b Remove debugging aid and left over cruft. 2013-07-31 18:54:38 +00:00
Dale Weiler
960cb7034a The problem was so subtle 2013-07-31 18:53:00 +00:00
Dale Weiler
3fa74da2b5 Fixes 2013-07-31 17:24:32 +00:00
Dale Weiler
5f2b7e3d57 fixed vector ops constant folding. 2013-07-31 17:05:43 +00:00
Dale Weiler
d0ee56f25f more fixes 2013-07-31 16:31:45 +00:00
Dale Weiler
1538e69f93 Fixes 2013-07-31 15:56:56 +00:00
Dale Weiler
fa5ad1212e Operator constant folding rewrite almost complete, just need to track down why two tests are failing. 2013-07-31 15:49:45 +00:00
Dale Weiler
86adb94d7d folding for lteqgt (less than equal to or greater than) operator a.k.a <=> which maps values to -1,0,1 depending on the result (think of the result as a troolan) .. it's a perl thing :P 2013-07-31 12:59:34 +00:00
Dale Weiler
9ed62eee58 Feed clang demon 2013-07-31 12:17:52 +00:00
Dale Weiler
c3da9b237b && and || op folding 2013-07-31 12:11:03 +00:00
Dale Weiler
b0460de935 Fold for div op 2013-07-31 11:48:43 +00:00
Dale Weiler
8dd125c8f3 Added constant folding support for '*' .. Clever ascii trick prevail :D 2013-07-31 10:40:17 +00:00
Dale Weiler
5e38c800f6 Some cleanups and more support for constant folding. 2013-07-31 09:56:45 +00:00
Dale Weiler
920dbaf1e0 Work in progress constant-folding rewrite. 2013-07-31 09:04:19 +00:00
Dale Weiler
d8b931fbcf Experimental/Initial try at in-ast constant folding. (for TYPE_FLOAT currently .. since comparisions on UTF8 strings need to be worked out yet ..) 2013-07-30 18:06:42 +00:00
Dale Weiler
2c975fe48f I'm in a state of confusion as to why constant folding was never done on comparisions, now it is ;) 2013-07-30 17:27:54 +00:00
Dale Weiler
d6ca5673dc Use the _t consistency naming scheme. Also various cleanups. 2013-07-30 16:00:51 +00:00
Dale Weiler
a9ab865add Move some things around 2013-07-30 15:32:24 +00:00
Dale Weiler
c8c25ef6f7 Some cleanups and smaller binaries! 2013-07-28 00:23:15 +00:00
Dale Weiler
6c0c7aac0f cherry-pick diagnostics testsuite into cooking. We can now create compiler diagnostic tests, i.e if the compiler errors on syntax, we can match the error messages. 2013-07-28 00:02:48 +00:00
Dale Weiler
9e2b17e715 Merge pull request #116 from ignatenkobrain/cooking
Add instruction for Fedora and other RPM distros
2013-07-27 11:29:14 -07:00
Igor Gnatenko
ab79dbd22a add instruction
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-07-27 22:24:43 +04:00
Igor Gnatenko
23af0c0209 add updated spec and rename it
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-07-27 22:09:39 +04:00
Igor Gnatenko
bee93f28b3 not needed yet
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2013-07-27 22:08:43 +04:00
Dale Weiler
d684e99d86 Clear out for now. 2013-07-27 17:57:29 +00:00
Dale Weiler
557ad9da1a Make COMPILER_QCC default to please the stuborn Quake community. 2013-07-27 17:56:46 +00:00
Dale Weiler
ec0aaa72a3 Some typos 2013-07-27 16:39:17 +00:00
Dale Weiler
ce7a9d5a3d Not to be included 2013-07-27 16:35:15 +00:00
Dale Weiler
0291726c09 Fedora spec files (0.2.9 and 0.3.0) + INSTALL documentation, thanks Igor Gnatenko. 2013-07-27 16:33:33 +00:00
Dale Weiler
c7679722fb Please the whitespace gods 2013-07-27 11:48:55 +00:00
Dale Weiler
8db9724c5d Revert "Smaller memory footprint, 4/8 bytes vs 12/24 for individual token lex_ctx's. Use to be a 'shallow' copy of the details in lex_file, now it's a pointer to the contents in lex_file."
This reverts commit cddf70f46b.
2013-07-26 16:17:41 +00:00
Dale Weiler
cddf70f46b Smaller memory footprint, 4/8 bytes vs 12/24 for individual token lex_ctx's. Use to be a 'shallow' copy of the details in lex_file, now it's a pointer to the contents in lex_file. 2013-07-26 16:09:26 +00:00
Dale Weiler
4a3794ea2b Track strdup memory too 2013-07-26 14:57:21 +00:00
Dale Weiler
44d5481828 There was too many 16-sized buckets when compiling xonotic, increase the size: this is cheaper on memory and slightly faster. 2013-07-26 14:50:37 +00:00
Dale Weiler
629fe05083 Fix the ctype replacements to work with macro arguments that have side-effect, with exception to isspace which *might* need to become a function. 2013-07-26 12:28:02 +00:00
Dale Weiler
d411d60685 Eeasy fix for that 2013-07-21 22:07:22 +00:00
Dale Weiler
2bfea938b3 One last one 2013-07-21 22:00:07 +00:00
Dale Weiler
96ec279663 Another one 2013-07-21 21:56:03 +00:00
Dale Weiler
697ad9d3a7 Technically GCC was wrong here, since opts_ini_parse is guranteed to change error. 2013-07-21 21:51:34 +00:00
Dale Weiler
764b9abaf4 Cleanups 2013-07-19 11:43:22 +00:00
Dale Weiler
84ad8ec37a Update gmqcc.ini.example 2013-07-04 15:24:55 -04:00
Wolfgang Bumiller
17318af62f fix typo 2013-07-01 10:37:51 +02:00
Wolfgang Bumiller
b39a748984 actually no :) 2013-06-22 20:31:50 +02:00
Dale Weiler
b534aca263 Fix a case of the uninitialized blues 2013-06-22 02:25:19 +00:00
Dale Weiler
adc9e7bf22 Fix some more bugs (coverity you're a life saver) 2013-06-22 02:05:04 +00:00
Dale Weiler
560b45dd16 Buffer overflow! 2013-06-22 01:58:20 +00:00
Dale Weiler
bbffdde2dc Fix some bugs and a memleak in the testsuite. 2013-06-22 01:56:22 +00:00
Dale Weiler
063c50fce4 More bug fixes and dead code elimination 2013-06-22 01:23:59 +00:00
Dale Weiler
5429b6f189 Fix out of bound access 2013-06-22 01:16:24 +00:00
Dale Weiler
d39fb653aa Fix some more bugs, and use dup2 because dup leaks on some implementations. 2013-06-22 01:14:13 +00:00
Dale Weiler
e08f00bfcd Update clean rules in makefiles to remove coverity stuff 2013-06-22 00:16:44 +00:00
Dale Weiler
edf59e4f73 Fixed possible bug in VM. Added coverity rules to makefiles. 2013-06-22 00:15:25 +00:00
Dale Weiler
52e7394418 Fix uninitialized data 2013-06-22 00:00:17 +00:00
Dale Weiler
a982d4e524 Fix a sizeof bug 2013-06-21 23:55:47 +00:00
Dale Weiler
458cfcb48c I'm assuming this is a bug since all other read tests compare with itself's ir_value, and only this one doesn't. Otherwise why would you need to load to an ir_value for vec? 2013-06-21 23:54:09 +00:00
Dale Weiler
5bdf0aff81 Catch that one too 2013-06-21 23:51:49 +00:00
Dale Weiler
1929b129ee Improper use of a possible negative value. 2013-06-21 23:49:08 +00:00
Dale Weiler
ce23e95d0b Remove a ton of dead code and document the one really insane case. 2013-06-21 23:40:51 +00:00
Dale Weiler
684112474b cppcheck had the right idea, but the wrong scope on this one. 2013-06-21 23:29:50 +00:00
Dale Weiler
fe296de42f Fix more bugs (mostly possible NULL pointer dereferences) 2013-06-21 23:26:49 +00:00
Dale Weiler
996d998ebb Fix possible NULL pointer dereference 2013-06-21 23:21:12 +00:00
Dale Weiler
125d039e3d Fix some bugs 2013-06-21 23:16:00 +00:00
Dale Weiler
6db2e69f9a Oh my god microsoft you suck 2013-06-20 11:20:56 +00:00
Dale Weiler
82fd7fcf68 Move code generator into ir_builder for earlier free. It's also a much more cleaner design than load parser->code for all ast/ir operations. We also have a proper chain'd design now (so making this a library will be easier). 2013-06-20 10:52:58 +00:00
Dale Weiler
a2c3388e49 Fix some comments 2013-06-18 07:31:09 +00:00
Dale Weiler
944ec75687 Retarded clang warning is retarded. 2013-06-18 07:26:07 +00:00
Dale Weiler
3b8b76328c Holy mexicans 15% better hashing == 5% faster compiles. 2013-06-18 07:22:03 +00:00
Dale Weiler
e6c1d66c35 Merge branch 'master' into cooking
Conflicts:
	opts.def
2013-06-17 20:14:26 +00:00
Dale Weiler
51eb94f251 Enable it for gmqcc and fteqcc modes. 2013-06-17 20:13:21 +00:00
Dale Weiler
7e76b42f11 Merge branch 'master' of github.com:graphitemaster/gmqcc 2013-06-17 20:12:02 +00:00
Dale Weiler
23cb7f4e09 Fix some bugs 2013-06-17 20:11:37 +00:00
Dale Weiler
a04c0d2aa2 make source a dependency for the c.o rule 2013-06-16 08:35:58 +00:00
Dale Weiler
ad8d76b212 Fixed 2013-06-16 08:24:13 +00:00
Dale Weiler
de8974d03e Use includes for makefile consistency. Added make depend rule for BSDmakefile. 2013-06-16 08:21:23 +00:00
Wolfgang Bumiller
f8db5a7c6d reclassify_token should only deal with tokens < TOKEN_START... should fix #113 2013-06-16 09:56:21 +02:00
Wolfgang Bumiller
e6bb7697f9 reclassify_token should only deal with tokens < TOKEN_START... should fix #113 2013-06-16 09:53:11 +02:00
Dale Weiler
a3e1342bdb Update 2013-06-16 07:51:55 +00:00
Dale Weiler
ba85107a85 Better scheme 2013-06-16 07:48:41 +00:00
Dale Weiler
0e392f91d2 A new batch of fresh hot dependencies for both 2013-06-16 07:23:51 +00:00
Dale Weiler
685925398c Dependency consistency 2013-06-16 07:22:37 +00:00
Dale Weiler
ec6de55d3c Update some things 2013-06-16 07:21:40 +00:00
Dale Weiler
00d1d237bc Update install file 2013-06-16 07:16:44 +00:00
Dale Weiler
6de7c45618 A Makefile for BSD make. 2013-06-16 07:08:07 +00:00
Dale Weiler
004832f6ec Make it compile with g++ again 2013-06-16 05:59:41 +00:00
Dale Weiler
82e92811e4 Uhh forgot to save file 2013-06-16 03:46:07 +00:00
Dale Weiler
9a6316221c Fix memleak 2013-06-16 03:45:06 +00:00
Dale Weiler
2d654ddcff Update 2013-06-16 02:48:31 +00:00
Dale Weiler
5d2b57394e Add the good old xor swap trick to the xor test, yes it works :P 2013-06-16 02:24:10 +00:00
Dale Weiler
17ae2dbe4d Make ^ legal for vector ^ vector, and vector ^ float (read the huge comment that explains why and what this does). Currently only works for constants (don't know how to do expression for multiple vector components yet). 2013-06-16 02:17:29 +00:00
Dale Weiler
a27b7ee6a5 Make them tests work now 2013-06-15 11:05:25 +00:00
Dale Weiler
5694c77d16 I added it for a reason, because I was smart. I forgot about it because of life :( 2013-06-15 11:04:08 +00:00
Dale Weiler
0c58509417 This is easier 2013-06-15 09:53:12 +00:00
Dale Weiler
202fc67f93 Correct order 2013-06-15 09:52:22 +00:00
Dale Weiler
b9cf1f1262 Fix bug 2013-06-15 09:50:02 +00:00
Dale Weiler
a8fddbb7d3 Implemented bitwise xor operator. 2013-06-15 09:48:40 +00:00
Dale Weiler
04406b191f Less terse, it confuses people. 2013-06-15 08:56:34 +00:00
Wolfgang Bumiller
290d065a79 again with the comments... 2013-06-15 09:49:15 +02:00
Wolfgang Bumiller
3fab06941a fix a call typecheck issue 2013-06-15 09:46:44 +02:00
Wolfgang Bumiller
f78d653b1e manpage update 2013-06-15 09:46:44 +02:00
Wolfgang Bumiller
179da9241c working on vararg piping: detecting several error cases, adding -Wunsafe-types and -funsafe-varargs 2013-06-15 09:46:44 +02:00
Dale Weiler
7115176c0e Strlen idiot 2013-06-15 07:42:01 +00:00
Dale Weiler
fee7794789 Limit corrections on strings to <= 16 bytes. Otherwise memory usage spikes instantly on errors, and causes Windows DEP to kill gmqcc. 2013-06-15 07:40:42 +00:00
Dale Weiler
5012616cb0 Limit corrections on strings to <= 16 bytes. Otherwise memory usage spikes instantly on errors, and causes Windows DEP to kill gmqcc. 2013-06-15 07:39:36 +00:00
Dale Weiler
90a016c6e0 Fix a possible issue 2013-06-15 05:28:38 +00:00
Dale Weiler
6617684a8d Some fixes 2013-06-15 02:25:19 +00:00
Dale Weiler
8afd373e4f Fixed whitespace 2013-06-14 21:36:16 +00:00
Dale Weiler
3e75750ad6 What the fuck are we talking about? 2013-06-14 21:26:33 +00:00
Dale Weiler
17fd017d6f Revert "Actually works now"
This reverts commit daa1487aef.
2013-06-13 22:23:07 +00:00
Dale Weiler
daa1487aef Actually works now 2013-06-13 22:20:17 +00:00
Wolfgang Bumiller
f023b7097f fix pedantic compile issue 2013-06-12 16:04:40 +02:00
Wolfgang Bumiller
2c59385633 fixing double-free in initialzied string arrays, using them in the testcase 2013-06-12 15:53:07 +02:00
Wolfgang Bumiller
b30368f026 array testcase for previous commit 2013-06-12 15:47:59 +02:00
Wolfgang Bumiller
8ce331b563 allow array size to be inferred from the initializer 2013-06-12 15:47:11 +02:00
Wolfgang Bumiller
dc91918c1f error about too many elements in initializer; added test for initialized arrays: arrays2.tmpl/qc 2013-06-12 14:41:38 +02:00
Wolfgang Bumiller
633d2ba8a4 make the ast use the initlist 2013-06-12 14:36:59 +02:00
Wolfgang Bumiller
bc4a66e9f7 setting initializing values 2013-06-12 14:32:34 +02:00
Wolfgang Bumiller
7a36a8bdd8 parsing array initializers 2013-06-12 14:32:12 +02:00
Wolfgang Bumiller
d631c517b6 forgot to add that one 2013-06-12 13:56:40 +02:00
Dale Weiler
b773702a47 Fix builds 2013-06-09 00:11:52 +00:00
Dale Weiler
0eab97283f Merge branch 'cooking'
Conflicts:
	.gitignore
2013-06-06 06:20:58 +00:00
Dale Weiler
ad92a5f27d Fix indexing 2013-06-06 06:20:11 +00:00
Dale Weiler
144672fada Strict prototyping 2013-06-06 02:51:13 +00:00
Dale Weiler
4f02d4b556 Update 2013-06-04 18:38:16 +00:00
Wolfgang Bumiller
923e0187bd Merge branch 'cooking' of git://github.com/graphitemaster/gmqcc into cooking 2013-06-04 20:36:58 +02:00
Wolfgang Bumiller
52d39b7260 slackware pkg build files 2013-06-04 20:32:06 +02:00
Dale Weiler
81b27ea84a Consistency 2013-06-04 18:07:18 +00:00
Dale Weiler
0d52f1ae7c Update changelog 2013-06-04 18:02:02 +00:00
Dale Weiler
0f98f0fd4a Some typos. 2013-06-04 17:44:45 +00:00
Dale Weiler
af80d9956b Gentoo ebuilds 2013-06-04 17:43:20 +00:00
Dale Weiler
e29b4d35b3 Add license header 2013-06-04 02:53:44 +00:00
Dale Weiler
77cf1f8685 Doh 2013-06-04 02:49:49 +00:00
Dale Weiler
11179a2a71 Major header reworking, this respects the namespaces properly. Makes object dependency more obvious, allows for better make caches, and prevents misuse of library features, i.e use con_* instead of printf. 2013-06-04 02:47:07 +00:00
Wolfgang Bumiller
b2348e1de0 remove the ast tree earlier - saves over 3% peak memory usage 2013-06-02 12:35:53 +02:00
Dale Weiler
06cccbb646 Fix a divide by zero error 2013-06-02 09:50:39 +00:00
Dale Weiler
c1a9ce3404 Fix output 2013-06-02 08:52:30 +00:00
Dale Weiler
c569e87bd0 Fix two bugs 2013-06-02 08:49:16 +00:00
Dale Weiler
100eaf9137 Merge pull request #112 from matthiaskrgr/master
mmmeeerging eeeet
2013-06-02 01:38:47 -07:00
Dale Weiler
ee42d2a570 Some cleanups 2013-06-02 08:37:22 +00:00
Dale Weiler
564cac859a Fix the peak 2013-06-02 08:28:56 +00:00
Matthias Krüger
69b55ccc03 gitignore: add gmqcc, gmqpak, qmcvm, testsuite, pak. 2013-06-02 10:26:27 +02:00
Dale Weiler
7ea67748fa Holy whoops 2013-06-02 08:25:00 +00:00
Dale Weiler
9af3c502da Major utility rewrite for compiler memory utilization statistics. Cleanups everywhere, no more NOTRACK stuff, all allocates are tracked. Major identifier cleanups as well. 2013-06-02 08:21:06 +00:00
Dale Weiler
ec7bf4767a Some static 2013-06-02 05:32:37 +00:00
Dale Weiler
1ce8d2ea6e Hashtable statistics too 2013-06-02 05:09:28 +00:00
Dale Weiler
f884bd2217 Track hashtables too 2013-06-02 04:45:04 +00:00
Dale Weiler
79a7aa70b9 Track strdups too in the statistics 2013-06-02 04:38:20 +00:00
Dale Weiler
c8daf483f3 This was an experiment that snuk it's way inside that commit. 2013-06-02 04:32:20 +00:00
Dale Weiler
166b79720c Vector tracing, step two in determining how to lower memory usage. 2013-06-02 04:29:53 +00:00
Dale Weiler
121e080697 Guart statistics by option. 2013-06-02 00:07:54 +00:00
Dale Weiler
280dfdd3f8 Add statistics for vector usage to the output. Step one in lowering memory usage. ONE FUCKING MILLION VECTORS for XONOTIC.. 2013-06-02 00:03:27 +00:00
Wolfgang Bumiller
d85e86141c fix a leak on a parse-error 2013-06-01 23:36:05 +02:00
Dale Weiler
655822ec1a Doh 2013-06-01 20:20:25 +00:00
Dale Weiler
062180e9a8 Fix some possible memleaks. 2013-06-01 20:18:53 +00:00
Wolfgang Bumiller
9f2b9e1b46 Merge branch 'master' into cooking 2013-06-01 20:12:27 +02:00
Wolfgang Bumiller
ff63e5bd73 fix the INCLUDE_DEF flag getting applied regardless of dotranslate... 2013-06-01 20:12:14 +02:00
Wolfgang Bumiller
1dce501b70 Merge branch 'master' into cooking 2013-06-01 18:16:56 +02:00
Wolfgang Bumiller
ed585f8c04 fix: dotranslate now sets AST_FLAG_INCLUDE_DEF to not get removed by -Ostrip-constant-names 2013-06-01 18:16:50 +02:00
Dale Weiler
b0a0769534 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-05-30 19:36:37 +00:00
Dale Weiler
0b6269f607 column printing for warnings and errors now 2013-05-30 19:36:01 +00:00
Wolfgang Bumiller
ba781c53ef now a bare 'return;' is not required anymore if return has been assigned anywhere 2013-05-29 17:08:03 +02:00
Wolfgang Bumiller
a76702cb36 make sure missing return values still warn 2013-05-29 17:01:26 +02:00
Wolfgang Bumiller
5aba29006b return assignment factorial test 2013-05-29 16:58:18 +02:00
Wolfgang Bumiller
9167de1631 fixing that comment... 2013-05-29 16:56:39 +02:00
Wolfgang Bumiller
afdc0c9dc8 assignable return value now lives in ast_function, as globals can get overwritten randomly; removed parser_find_retval; updated parse_return 2013-05-29 16:51:59 +02:00
Dale Weiler
db6ca6c5f8 Make static 2013-05-29 11:32:42 +00:00
Dale Weiler
fd5506b376 Update test template. 2013-05-29 11:30:26 +00:00
Dale Weiler
1b71caa1fe Update man page 2013-05-29 11:29:52 +00:00
Dale Weiler
6d6a2efada Experimental support for implicit return assignments. This closes #107. To enable return assignment support use -freturn-assignments. This allows you to do the following in QC code. T name() { return = expr_eval_T; return; /* returns expr_eval_T */ }. It allows for concise code and to rid locals in functions. It also saves a tremendous amount of space since only types of certian globals need to be allocated for returns. 2013-05-29 11:13:42 +00:00
Dale Weiler
2923b718e1 Merge branch 'union-replacement' into cooking
Conflicts:
	ast.c
2013-05-29 03:43:49 +00:00
Dale Weiler
e3f4ae3038 Add back that splint flag 2013-05-29 03:39:38 +00:00
Dale Weiler
d45956f55e Fix that memory leak that I spent hours trying to find months ago and didn't succeed at. 2013-05-29 03:35:51 +00:00
Dale Weiler
f892b32335 Major export cleanup. Anything that was exported but wasn't used outside where it was implemented has been turned into static, and their exports have been removed. This actually makes the compiler compile slightly faster. 2013-05-29 03:29:04 +00:00
Dale Weiler
df8b486c98 Prevent negitive numbers from being used as the left operand of shift operator. 2013-05-29 02:37:45 +00:00
Dale Weiler
e02ebfe486 Result of shift operation on signed integers is bad. 2013-05-29 02:24:12 +00:00
Dale Weiler
f281de7a3c Cleanups and fixes 2013-05-29 02:16:50 +00:00
Wolfgang Bumiller
d70b571769 killing the union types 2013-05-11 22:34:01 +02:00
Wolfgang Bumiller
ef6e2bd583 first step to getting rid of those unions we don't use anyway 2013-05-11 22:05:30 +02:00
Wolfgang Bumiller
a0fa90ddd5 less confusing 2013-05-07 20:35:20 +02:00
Wolfgang Bumiller
802005f571 be more strict here 2013-05-07 20:13:19 +02:00
Wolfgang Bumiller
4d0a5af475 removing this dead code_init call 2013-05-07 19:59:06 +02:00
Wolfgang Bumiller
c5225b2fa1 fixing a few leaks - code_write doesn't delete the code object anymore, code_cleanup has to be called 2013-05-07 19:56:41 +02:00
Wolfgang Bumiller
8c8ae71d65 changing a few ast_delete to ast_unref in places where the to-be-deleted maybe coming from some other place 2013-05-07 19:39:10 +02:00
Wolfgang Bumiller
3e7cd8a98b Merge pull request #111 from matthiaskrgr/cooking_stuff
.gitignore: add binarys
2013-05-05 04:12:14 -07:00
Matthias Krüger
9823b294df .gitignore: add binarys 2013-05-05 12:53:58 +02:00
Dale Weiler
c07c78c666 Escape strings in executor for -printdefs 2013-05-02 19:18:59 +00:00
Dale Weiler
79a5ed0482 Implemented support for having codegen (and lno files) be wrote out to memory, this essentially allows us to embed the compiler in applications now. 2013-04-28 04:29:20 +00:00
Dale Weiler
721b581376 Fix deps (remove duplicates with clever make tricks) 2013-04-28 03:50:22 +00:00
Dale Weiler
3d115760a0 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-04-28 03:42:04 +00:00
Dale Weiler
a8e2a47da8 Less general name for PAK utility, added install targets for PAK utility, added manpag for PAK utility, this closes #108 2013-04-28 03:41:03 +00:00
Wolfgang Bumiller
f6792c3a05 Merge branch 'master' into cooking 2013-04-27 19:05:06 +02:00
Wolfgang Bumiller
bc4749d95a Merge pull request #109 from matthiaskrgr/PKGBUILD_master
PKGBUILD: archlinux: fix build by applying a patch (4c4aa5534c) on 0.2.9 package.
Accepting this with a patch in order for it to keep the 0.2.9 version info.
2013-04-27 10:04:43 -07:00
Matthias Krüger
90eed12e97 PKGBUILD: archlinux: fix build by applying a patch (4c4aa5534c) on 0.2.9 package. 2013-04-27 18:45:26 +02:00
Wolfgang Bumiller
2058ce69a4 Merge branch 'master' into cooking 2013-04-27 17:52:54 +02:00
Wolfgang Bumiller
4c4aa5534c dup is marked as warn-unused-result 2013-04-27 17:51:51 +02:00
Dale Weiler
dc6a7436ee Expression has undefined behavior (left operand modifies code->globals->used, used by right operand): (code->globals)[(((vector_t*)((void *)code->globals)) - 1)->used++] = (code_genstring(code, global->constval.vstring)) Code has unspecified behavior. Order of evaluation of function parameters or subexpressions is not defined, so if a value is used and modified in different places not separated by a sequence point constraining evaluation order, then the result of the expression is unspecified. 2013-04-27 15:20:01 +00:00
Wolfgang Bumiller
35120caf80 debian Makefile had the same flaw as archlinux/this... fixing 2013-04-27 17:00:27 +02:00
Wolfgang Bumiller
9ace0811ce Merge branch 'master' into cooking 2013-04-27 16:55:28 +02:00
Wolfgang Bumiller
d4b0e1f588 updating archbsd and archlinux release/PKGBUILD files 2013-04-27 16:54:53 +02:00
Wolfgang Bumiller
18cf3641b1 Merge branch 'master' into cooking 2013-04-27 16:33:55 +02:00
Wolfgang Bumiller
01ead27dd9 Update CHANGES file 2013-04-27 16:33:47 +02:00
Wolfgang Bumiller
b8e536d409 Starting point of 0.3.0 2013-04-27 16:30:35 +02:00
Wolfgang Bumiller
219508e478 this should be tagged 0.2.9 2013-04-27 16:30:03 +02:00
Wolfgang Bumiller
75ceab8f51 fix distro/ Makefiles 2013-04-26 17:56:08 +02:00
Wolfgang Bumiller
5007fd7f71 don't overwrite ldflags/libs env vars 2013-04-26 17:44:44 +02:00
Dale Weiler
50ff9e4fd0 Fix OSX compiles 2013-04-26 15:43:13 +00:00
Wolfgang Bumiller
7e0d6bdd87 don't overwrite ldflags/libs env vars 2013-04-26 17:33:56 +02:00
Wolfgang Bumiller
9f8bee4bf1 ast_value now has an initializer list array, still unused but it's there for later 2013-04-26 10:47:55 +02:00
Wolfgang Bumiller
b3e9ef3ad9 an = before an { is also always required when the declared variable is not a function; adding because of planned array initializers 2013-04-26 10:31:38 +02:00
Dale Weiler
1077eb2061 Add expressions for builtins test 2013-04-25 17:39:05 +00:00
Wolfgang Bumiller
d4f8e4a0dd solve it, not hide it 2013-04-25 19:18:50 +02:00
Wolfgang Bumiller
35692c0b57 Revert "Just fucking initialize everything"
This reverts commit aed2b1031c.
2013-04-25 19:18:11 +02:00
Wolfgang Bumiller
b9fb29d740 manpage and ini update 2013-04-25 19:17:58 +02:00
Dale Weiler
aed2b1031c Just fucking initialize everything 2013-04-25 17:11:15 +00:00
Dale Weiler
68ca2c4962 Pushing the -fexpressions-for-builtins stuff and the modff for catching fractional-part builtin numbers. 2013-04-25 17:08:02 +00:00
Wolfgang Bumiller
ce73074d51 this allows builtin numbers to be constant expressions, not just constants 2013-04-25 18:47:54 +02:00
Wolfgang Bumiller
c3f4b7153b change the value of TOKEN_EOF 2013-04-25 17:39:12 +02:00
Dale Weiler
2eddc464d5 Less extern 2013-04-25 12:22:34 +00:00
Dale Weiler
3d8e8cd80d cleaner 2013-04-25 12:08:43 +00:00
Dale Weiler
9fee84f250 less globals 2013-04-25 12:08:13 +00:00
Dale Weiler
785ab7c072 No more globals for codegen 2013-04-25 09:35:30 +00:00
Wolfgang Bumiller
73070395eb these can be const now 2013-04-25 09:55:58 +02:00
Dale Weiler
c6f2c8fc3d That is also not needed anymore 2013-04-25 03:37:40 +00:00
Dale Weiler
2a3376cb52 not needed for arm anymore 2013-04-25 03:36:57 +00:00
Dale Weiler
10dd7aacfe Apply some static where it belongs 2013-04-25 03:34:42 +00:00
Dale Weiler
1b5504fb9e Fix alignment issues (can remove a clang warning, and also makes our code more portable!) 2013-04-25 03:17:52 +00:00
Dale Weiler
bfbb60bbed Use the LIBS properly 2013-04-25 03:11:50 +00:00
Wolfgang Bumiller
3a4aba0b31 Grrrr 2013-04-24 17:47:42 +02:00
Wolfgang Bumiller
1a915c7bf7 manpage: document and explain __FUNC__ and __NULL__ 2013-04-24 17:42:48 +02:00
Wolfgang Bumiller
66305c676a Allow string concatenation in the parser as well, for now only for immediate strings and __FUNC__, maybe later -fpermissive or somethign could allow it on const-delcared string variables 2013-04-24 17:27:04 +02:00
Dale Weiler
8ffdfbfd97 A nicer way of doing this 2013-04-24 14:08:58 +00:00
Dale Weiler
5d88216f38 remove irrelevant comment 2013-04-24 14:06:43 +00:00
Dale Weiler
19c57c03cc free the memory for asprintf 2013-04-24 14:05:09 +00:00
Dale Weiler
a0f6b00a15 Shitty testsuite support for windows the hacky way because there exists no sane simple way of redirecting pipes without a heafty chunk of code. 2013-04-24 14:04:00 +00:00
Wolfgang Bumiller
1e9d3e43cb test for the simple __FUNC__ case 2013-04-24 11:22:29 +02:00
Wolfgang Bumiller
dcd65f18f8 recognize the simple case of __FUNC__ in the parser 2013-04-24 11:21:10 +02:00
Dale Weiler
8bee9a6819 fix the intrinsic fail 2013-04-24 09:18:24 +00:00
Dale Weiler
6284cc673d typo 2013-04-24 04:50:07 +00:00
Dale Weiler
b3fc77efd6 Implemented __TIME_STAMP__ predef, expands to a timestamp of when the __FILE__ was last modified, returned in the format: "Www Mmm dd hh:mm:ss yyyy", where Www is the weekday, Mmm the month (in letter), dd the day of the month, hh:mm:ss the time, and yyyy the year. 2013-04-24 04:48:05 +00:00
Dale Weiler
35988b6191 Make ftepps __NULL__ translate to gmqccs untyped nil keyword (this isn't correct behaviour of the __NULL__ constant, but it works) 2013-04-24 04:17:17 +00:00
Dale Weiler
dc8523c650 Merge branch 'master' into cooking 2013-04-24 01:46:53 +00:00
Dale Weiler
489ad486bc Get it compiling in visual studio again. 2013-04-24 01:43:53 +00:00
Dale Weiler
10738da2fb Make it compile as C++ code too 2013-04-23 22:50:47 +00:00
Wolfgang Bumiller
17996dee50 fix noreturn testcase descriptions... those were mixed up 2013-04-23 17:07:19 +02:00
Wolfgang Bumiller
f6d554874b initialize the vector member array so that 'cleanup' won't delete uninitialized pointers 2013-04-23 16:54:05 +02:00
Wolfgang Bumiller
3d9a06591a Makefile: be more conformant: at link-time use LDFLAGS, not CFLAGS, also use CPPFLAGS prepended to CFLAGS at compile-commands, append optional LIBS at link-time after everything else 2013-04-23 16:49:43 +02:00
Wolfgang Bumiller
d6f6241872 misc/check-doc.sh 2013-04-22 12:22:24 +02:00
Dale Weiler
c86e778c76 Website target to distro makefile for updating gh-pages 2013-04-22 06:14:26 +00:00
Dale Weiler
217833dff7 Add download.c (used for generating the download.html for the website (for releases)) based on magic. use gcc download.c -o gen; gen ../../; git checkout gh-pages; git add download.html; git push origin gh-pages; to apply website changes. 2013-04-22 05:43:38 +00:00
Dale Weiler
1759388e3f Merge branch 'master' into cooking 2013-04-22 00:11:31 +00:00
Dale Weiler
9a1894f587 Proper install names (preserve the .exe for win32 builds) 2013-04-22 00:05:44 +00:00
Dale Weiler
a879fc28a3 Merge pull request #105 from matthiaskrgr/icon
Icon
2013-04-21 07:22:11 -07:00
Matthias Krüger
cc3b8dcfd6 make: gource: display gmqcc icon in video. 2013-04-21 14:08:23 +02:00
Matthias Krüger
53aac525d9 add gmqcc icon found on ohloh. 2013-04-21 14:07:06 +02:00
Dale Weiler
f8fc40c306 Merge branch 'master' of github.com:graphitemaster/gmqcc 2013-04-21 11:46:05 +00:00
Dale Weiler
0f7634876f Some stuff for building win32 packages via mingw32 2013-04-21 11:45:41 +00:00
Dale Weiler
ef565adaa5 Merge pull request #104 from matthiaskrgr/PKGBUILD_master
PKGBUILD: archlinux: git: install syntax files to respective dirs.
2013-04-21 04:14:06 -07:00
Matthias Krüger
f9ed308aa8 PKGBUILD: archlinux: git: install syntax files to respective dirs. 2013-04-21 13:05:45 +02:00
Wolfgang Bumiller
685fa54daf Merge branch 'master' into cooking 2013-04-21 12:37:06 +02:00
Dale Weiler
160e7cf7ee Remove trailing whitespace 2013-04-21 10:24:55 +00:00
Wolfgang Bumiller
934ff4a5eb Merge branch 'master' into cooking 2013-04-21 12:24:12 +02:00
Wolfgang Bumiller
2343e13c45 updating the manpage 2013-04-21 12:23:54 +02:00
Dale Weiler
8c08897749 Fixes 2013-04-21 10:13:51 +00:00
Dale Weiler
462c06d56b Merge branch 'cooking' 2013-04-21 10:09:08 +00:00
Dale Weiler
317559e5a5 Update CHANGES 2013-04-21 10:08:04 +00:00
Dale Weiler
4a1eb7f948 update README to reflect syntax highlighting stuff. 2013-04-21 09:44:08 +00:00
Dale Weiler
f3c04d0f37 Add jedit syntax highlighting support, thanks to LordHavoc (made some changes to reflect gmqcc syntax more) 2013-04-21 08:13:39 +00:00
Dale Weiler
3cecd5d066 This is suppoted now 2013-04-21 07:30:32 +00:00
Dale Weiler
7def17eed5 Add syntax configuration file for gtksourceview (this allows QC code syntax highlighting for GNOMEs default text view in nautilus, gedit, and sandy + other gtksouceview based editors). 2013-04-21 07:27:59 +00:00
Dale Weiler
c362826dc6 typo 2013-04-21 07:07:07 +00:00
Dale Weiler
0661002257 update README for syntax highlighting stuff 2013-04-21 07:06:37 +00:00
Dale Weiler
96c0fa983d A more realistic preprocessor concatenation test. 2013-04-21 06:52:22 +00:00
Dale Weiler
6009e2b3ea Undo that fail 2013-04-21 06:46:54 +00:00
Dale Weiler
07e335fdb8 Better output on failure 2013-04-21 06:46:39 +00:00
Dale Weiler
e27eebe0f9 More preprocessor testsuite support and our first preprocessor test! 2013-04-21 06:36:52 +00:00
Dale Weiler
c53fa31a0a More preprocessor testing support for the testsuite. 2013-04-21 06:23:40 +00:00
Dale Weiler
79282bfee0 Initial preprocessor procedure option for testsuite implemented. 2013-04-21 06:20:17 +00:00
Dale Weiler
ea0e2c47d5 We don't need to specify "-should fail" because we print the type now (this also makes the description colum shorter) 2013-04-21 06:13:25 +00:00
Dale Weiler
57d2876021 I did it, I did it, I did it, horray!, Thanks Dora .. I mean Hirato. 2013-04-21 06:09:20 +00:00
Dale Weiler
485866552d Some work in progress preprocessing test work 2013-04-21 05:50:21 +00:00
Dale Weiler
b47e3ebccf Remove hashset 2013-04-21 04:56:41 +00:00
Wolfgang Bumiller
46752af74b parser_const_string now uses hashtables; hashtables may want to dup an empty string without it becoming NULL - also replacing ir_strdup with the new util_ one 2013-04-17 18:23:30 +02:00
Wolfgang Bumiller
8f2a22b8c3 fix warnings to allow compiling with -O3 2013-04-17 17:58:08 +02:00
Dale Weiler
dc7e18ec73 Some inline never hurt anyone .. actually, C made a bad decision in it's design, everything should've always been implicitly inline, since most code back in the day was small, if you had large bodies, there should've been an 'outline' keyword for that instead :P 2013-04-17 11:02:42 +00:00
Dale Weiler
0b0b6423ba Use hashtable for macro definitions in the preprocessor, this speeds up the search for them, and the removal of them making it O(1) instead of O(n). This also makes my 30 second xonotic compiles take only 13 seconds 2013-04-17 10:51:33 +00:00
Wolfgang Bumiller
4d394494b6 don't call ftepp_finish on a freed ftepp struct 2013-04-17 11:36:45 +02:00
Dale Weiler
d7be99c9dd More perliminary reworking for threading 2013-04-17 06:30:09 +00:00
Dale Weiler
21c6079b7a Fix compile for windows. 2013-04-17 04:27:00 +00:00
Dale Weiler
1f0a1b8140 Perliminary parser reworking, required for the proposed multithreading. 2013-04-17 00:52:52 +00:00
Dale Weiler
b82efcf0ce Fix typo in kate syntax highlighting installation documentation. 2013-04-16 20:27:01 +00:00
Dale Weiler
a61c9c6d89 Added syntax highlighting configuration files (with documentation on how to install them) for nano, kate and geany. 2013-04-16 20:24:33 +00:00
Wolfgang Bumiller
992c6fbfb8 lex_try_pragma: free the buffers 2013-04-16 14:14:15 +02:00
Dale Weiler
1c51fb80eb Fix memdump printing 2013-04-16 09:13:22 +00:00
Dale Weiler
f2b21158d8 Rewrote memory tracking, now prints highest water mark (most used memory at a given time during compile). Changes all byte representation to MB representation. Added ability to print the contents of the leaked memory to the console when -debug is on (infact the lost messages only print during -debug), -memchk simply reports the memory info at the end (it is also printed when -debug). You can set the memory dump columns with -memdumpcols=# where # is the number of columns you want (default is 16) 2013-04-15 20:54:53 +00:00
Wolfgang Bumiller
1a9c82483c fix macro parameters 2013-04-15 21:07:44 +02:00
Wolfgang Bumiller
1f667c4b35 ast_expression_delete: delete varparam if it is set - fixes another leak 2013-04-15 21:05:59 +02:00
Wolfgang Bumiller
d5e90a17f9 fix memleak in ast_local_codegen 2013-04-15 20:56:48 +02:00
Wolfgang Bumiller
1caf1b3ebe util_strdup: don't use util_memory_a with -DNOTRACK 2013-04-15 20:53:53 +02:00
Dale Weiler
c2b5a95961 GCC specific stuff compile flags. 2013-04-15 06:23:13 +00:00
Dale Weiler
ef528d6710 Added tracing to strdup for allocations, fixed some memleaks, this isn't pretty (trying to track down some weird memory leak issues) 2013-04-14 23:51:16 +00:00
Dale Weiler
18fad16a7d cleanups 2013-04-14 01:41:13 +00:00
Dale Weiler
7ba7fd5968 Fet rid of explicit file stream flushes, streams are flushed on exit, which we can always gurantee. 2013-04-14 01:32:29 +00:00
Dale Weiler
752409417f Remove one more external function 2013-04-14 01:29:50 +00:00
Dale Weiler
4591b3a4fa More flattening. I don't know why I turned off buffering, that makes output to console even slower due to all the flushes, which actually slows down compilation. 2013-04-14 01:26:40 +00:00
Dale Weiler
eb2a74f7e7 Flatten more external functions 2013-04-14 01:25:11 +00:00
Dale Weiler
a25bd052d7 More function flatening 2013-04-14 01:16:35 +00:00
Dale Weiler
ccc2eb3298 More function flatening 2013-04-14 01:14:14 +00:00
Dale Weiler
3e7340c52c More external function flatening (less external symbols) 2013-04-14 01:07:39 +00:00
Dale Weiler
3f546df677 Revert that trans stuff 2013-04-14 01:03:22 +00:00
Dale Weiler
48d6375817 flatten the use of strcpy, 90% of the cases we already knew the length of the string either at compile-time, or already within the scope we where, thus letting us use strncpy, which can be further optimized (unrolled if static) 2013-04-14 01:00:25 +00:00
Dale Weiler
3f40fcb965 Fix possible buffer overflows. 2013-04-13 18:17:15 +00:00
Dale Weiler
95172861f5 Fix possible bug 2013-04-13 18:04:07 +00:00
Dale Weiler
c62d88cb57 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-04-13 18:01:41 +00:00
Dale Weiler
c74889f648 Fix some memory leaks. 2013-04-13 18:01:26 +00:00
Wolfgang Bumiller
cb0169a784 Merge pull request #103 from matthiaskrgr/cooking
fix arch pkgbuilds
2013-04-13 03:50:57 -07:00
Matthias Krüger
7b3bbf05b9 gitignore: ignore pkg.tar.xz packages in distro/arch{linux/bsd} 2013-04-13 11:23:10 +02:00
Matthias Krüger
f5ba2e825f PKGBUILD: release: fix sha1sum, minor cleanup 2013-04-13 11:19:48 +02:00
Matthias Krüger
5bb10260b3 PKGBUILD: git: fix for pacman 4.1.0 2013-04-12 22:08:10 +02:00
Matthias Krüger
47ebf7c84c .gitignore: add /pak 2013-04-12 21:51:55 +02:00
Dale Weiler
c6bd5e6a2b Update specification.tex 2013-04-08 00:05:55 -03:00
Wolfgang Bumiller
a6ac90215b we changed the prefix... there too 2013-04-02 23:40:26 +02:00
Wolfgang Bumiller
c01ad2bfcf we changed the prefix... 2013-04-02 23:39:42 +02:00
Dale Weiler
50e8618b64 Merge pull request #102 from matthiaskrgr/cooking
gource stuff
2013-03-27 13:15:00 -07:00
matthiaskrgr
54c89e485a make: gource flags: add
--key
    --camera-mode overview
    --highlight-all-users
    --file-idle-time 0
    --hide progress,mouse
    --stop-at-end
    --max-files 99999999999
    --max-file-lag 0.000001
    --bloom-multiplier 1.3
2013-03-27 20:05:43 +01:00
matthiaskrgr
8e122d78be Makefile: split up 'make gource' into 'make gource' (render only) and 'make gource-record' (record using ffmpeg) 2013-03-27 19:50:39 +01:00
Dale Weiler
58a04a04e5 Make variable for flexibility 2013-03-21 06:17:50 +00:00
Dale Weiler
6900e50289 Uploadability from package building using dropbox API (all inside a makefile with magics) 2013-03-21 06:01:34 +00:00
Dale Weiler
c42a853e0b Some protection for cross arch package building 2013-03-21 04:47:46 +00:00
Dale Weiler
1b02a5204a Cross architecture stuff for distro build scripts. If you have an x86_64 capable system with a compiler and make (the OS doesn't even matter), simply changing to "distro" directory and typing "make" is sufficent to make archlinux i686/x86_64, and debian i686/x86_64 packages. 2013-03-21 02:02:41 +00:00
Dale Weiler
66b5cf29ba While we're at it, fix that one too. 2013-03-15 22:56:45 +00:00
Dale Weiler
6a0f9d3cb2 *sigh* 2013-03-15 22:56:09 +00:00
Dale Weiler
11255058cf SPACES PEOPLE 2013-03-15 22:53:00 +00:00
Dale Weiler
dfca3743f9 Added gource rule to makefile 2013-03-15 22:51:40 +00:00
Dale Weiler
a798859a7a Added isnan compiler builtin, documented what each compiler builtin does as well. 2013-03-09 09:20:54 +00:00
Dale Weiler
d4785ad6e3 fix comment 2013-03-09 08:59:12 +00:00
Dale Weiler
965f8b9041 Uh wrong file. 2013-03-09 08:57:37 +00:00
Dale Weiler
cbeac3e5f2 Implemented smart intrinsic / builtin system. When you use trivial math functions like "pow", if they don't exist as a builtin, the compiler will implement its own versions, likewise, if a compiler builtin depends on a function that exists, it will use it, likewise if it doesn't it will implement it. If you explicitally use __builtin_ (prefixed) versions, the compiler again will select the best option it can, be it a combination of both builtins and compiler builtins, all compiler builtins, OR, all builtins (most performant). 2013-03-09 08:53:39 +00:00
Dale Weiler
9bb586fb5a Add floor to tests defs.qh 2013-03-09 05:46:08 +00:00
Dale Weiler
d8d78f61a7 Implemented "reverse" enum attribute, e.g enum : reverse { A, B, C, D } -> A,B,C,D = 3,2,1,0 2013-03-09 05:07:14 +00:00
Dale Weiler
73c085a461 Fix operator precedence, closes #101 2013-03-09 04:25:02 +00:00
Dale Weiler
662612d66f Better diagnostic when "floor" cannot be found. 2013-03-08 09:23:35 +00:00
Dale Weiler
f19adcd1b3 Implemented __builtin_mod, and % operator. Added floor builtin to the standalone executor. Mod works so long as the compiler can find a suitable definition of "float floor(float)", otherwise it prints a diagnostic and gives up (original id1 Quake had floor so we can depend on it). 2013-03-08 09:17:54 +00:00
Dale Weiler
b971ddec3a Implemented concept of enumeration attributes (can be further extended, but currently only "flag" is implemented as an attribute). An enumeration with a flag attribute will act as a "flagged enumeration", one that automatically handles exponentiation of the constants defined inside it, i.e enum : flag { A, B, C }, A,B,C will equal 2, 4, 8. 2013-03-08 08:01:45 +00:00
Dale Weiler
479f3b9343 Implemented __builtin_exp 2013-03-08 03:46:25 +00:00
Dale Weiler
12340a6bd0 Actually generate an ast_call for __builtin_pow for the ** operator, otherwise the operator yeilds a ast_function, making "a ** b" not work, but since it's a function, allows **(a, b). Also added tests for exponentiation operator. 2013-03-07 23:05:40 +00:00
Dale Weiler
0367a6175d Add some ice 2013-03-07 22:52:03 +00:00
Dale Weiler
db229b6f94 Make ** RIGHT associative 2013-03-07 22:14:04 +00:00
Dale Weiler
bd54fe03b9 Get rid of the bullshit log stuff 2013-03-07 22:09:14 +00:00
Dale Weiler
f2380a2faa They see me roll 'n, casting, so far they just think I'm implicit casting dirty, implicity casting dirty .. 2013-03-07 21:38:46 +00:00
Dale Weiler
d3c7b6fb39 Implement exponentiation operator ** as well as __builtin_pow (used for exponentiation operator). Use of exponentiation operator with constants results in const folded (precomputed at compile time exponentiation), otherwise runtime exponentiation with some clever loops (slow!). 2013-03-07 21:31:19 +00:00
Dale Weiler
f59d557dce Update specification.tex 2013-03-07 10:21:29 -05:00
Dale Weiler
bedfee1fae Update specification.tex 2013-03-07 10:19:00 -05:00
Dale Weiler
bdbfc85243 Update specification.tex 2013-03-07 09:39:41 -05:00
Dale Weiler
2146e018f1 Update specification.tex 2013-03-07 00:39:26 -05:00
Wolfgang Bumiller
a32f59b256 hopefully fix an off-by-1 vararg copy issue 2013-02-26 16:39:28 +01:00
Dale Weiler
9f06e0e017 Print the number for the test itself in the test-suite. The log10 can be improved. 2013-02-25 10:01:36 +00:00
Dale Weiler
b1d1aabbdd Remove debug printf 2013-02-25 08:52:56 +00:00
Dale Weiler
aebab8b68a Push definitions when -O0 2013-02-25 08:52:17 +00:00
Wolfgang Bumiller
d27c06ea7f Merge branch 'master' into cooking 2013-02-20 23:08:58 +01:00
Wolfgang Bumiller
80184b0d80 fix: don't mess up multiline macros in files ending with \r\n 2013-02-20 23:08:50 +01:00
Wolfgang Bumiller
aa27249b88 update to .gitignore 2013-02-13 10:55:32 +01:00
Wolfgang Bumiller
3593a1b6b8 Merge branch 'master' into cooking 2013-02-12 14:31:27 +01:00
Dale Weiler
3b923a0183 fix 2013-02-11 18:02:42 +00:00
Dale Weiler
3b630ec5dc Less duplication 2013-02-11 17:51:23 +00:00
Dale Weiler
c7e3e3e306 Fix fucking mingw32 shit. 2013-02-11 17:49:17 +00:00
Wolfgang Bumiller
1dfd375738 include: guard the actual inclusion with ftepp->output_on so that include inside #if 0 doesn't happen 2013-02-11 12:13:27 +01:00
Wolfgang Bumiller
3e3b8993aa Lifetime analysis: Don't go through the blocks as a graph, instead, go through only the list.
The difference in code is rather small, but it's much faster.
2013-02-11 11:39:44 +01:00
Dale Weiler
0b154d69e7 BOOM 2013-02-10 13:59:24 +00:00
Dale Weiler
c8959a2452 BOOM 2013-02-10 13:57:22 +00:00
Dale Weiler
b5ead871ef Consider cppchecks (performance) warnings. 2013-02-10 13:47:50 +00:00
Dale Weiler
5acde18ef1 Sigh 2013-02-10 02:09:12 +00:00
Dale Weiler
b0c6dc5ab2 Fix mem leak. 2013-02-10 02:08:17 +00:00
Dale Weiler
e4554892b0 Oops 2013-02-08 19:07:12 +00:00
Dale Weiler
e4075916f0 depend rule for $(OBJ_P) PAK utility. 2013-02-08 16:45:05 +00:00
Dale Weiler
fb8fb9f0f7 These includes are not required 2013-02-08 16:43:31 +00:00
Dale Weiler
ac8f510dac Added $(PAK) to Makefile for clean rule. 2013-02-08 16:42:43 +00:00
Dale Weiler
02230ca992 endian swap on FOURCC for "PACK" on BE systems. 2013-02-08 16:40:47 +00:00
Dale Weiler
533b2144c5 Fix some memleaks. 2013-02-08 16:39:14 +00:00
Dale Weiler
eabb92f7b4 A command line interface for the PAK utility, made it a seperate build target too. 2013-02-08 16:32:15 +00:00
Dale Weiler
a568d43487 Implemented __VA_COUNT__ 2013-02-08 12:30:17 +00:00
Dale Weiler
945aba6e10 Make it compile as C++ code AGAIN 2013-02-08 12:20:48 +00:00
Dale Weiler
09a1a37554 Actually add fs.c 2013-02-08 12:08:24 +00:00
Dale Weiler
8d59d7029d Cleanup cargocult directory and file specific things, to fs.c (renamed file.c which also contains directory handling stuff). Also cleaned up some stuff, and added proper end comments to conditional inclusion stuff. 2013-02-08 12:06:59 +00:00
Dale Weiler
ece64dc779 fix build issue 2013-02-07 20:10:01 +00:00
Dale Weiler
aef60b7ec1 Add directory support for extract_all 2013-02-07 20:08:50 +00:00
Dale Weiler
8ecfc51799 Cleanups and fixes to the PAK utility, can now extract/insert, tested and functional for the most part. 2013-02-07 17:21:15 +00:00
Dale Weiler
1fa9fbb94b Fixes to the PAK utility. 2013-02-07 17:07:29 +00:00
Dale Weiler
86df8c8a78 Work in progress PAK extractor/insterter. 2013-02-07 16:22:47 +00:00
Dale Weiler
d1f4b108a0 Update makefile 2013-02-06 10:54:14 +00:00
Dale Weiler
ecd9e3be97 Make the testsuite C++ compatible. 2013-02-06 10:52:09 +00:00
Dale Weiler
eb0e3c2898 Make it compile as C++ code again. 2013-02-06 10:36:27 +00:00
Wolfgang Bumiller
9bc774dcd3 find aliases in parser_find_global instead of parser_sya_operand 2013-02-06 10:55:06 +01:00
Dale Weiler
cb1a6a6a6b Store the ast nodes for aliases 2013-02-06 09:44:23 +00:00
Dale Weiler
1e60bafcdc Aliases to aliases is a bad idea, revert. Added better tests to show unused aliases 2013-02-06 09:28:42 +00:00
Dale Weiler
21e890602d Fix alias bug. Implemented support for aliases of vectors (x, y, z components). Also made aliases corrector resident (e.g alias to vector foo, named bop, indexing bol_x [instead of bop_x] will result in a correction suggestion of bop_x now). 2013-02-06 09:09:47 +00:00
Dale Weiler
6fc141733f Support for aliases to aliases too. 2013-02-06 08:43:11 +00:00
Dale Weiler
060bc0be10 Some sanity checks for aliases (undeclared variable checks, and incompatible types in alias checks.) 2013-02-06 05:51:05 +00:00
Dale Weiler
3dc8e9bb9c add todo 2013-02-06 05:38:34 +00:00
Dale Weiler
e464cc1ea6 Implemented generalized attribute aliases. You can now alias functions, locals, or globals with [[alias("old_name")]] type new_name; 2013-02-06 05:30:09 +00:00
Dale Weiler
52ffc6db10 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-02-05 17:16:09 +00:00
Dale Weiler
9cff2f7b8a perl ops -> pops 2013-02-05 17:15:28 +00:00
Dale Weiler
b3e87c3280 ast referencing 2013-02-05 17:14:56 +00:00
Wolfgang Bumiller
4b5afe3456 ast_array_index_codegen: never regenerate code 2013-02-05 17:54:14 +01:00
Dale Weiler
e2c424d607 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-02-05 16:35:12 +00:00
Dale Weiler
8e87082e1d Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking
Conflicts:
	parser.c
2013-02-05 16:34:55 +00:00
Wolfgang Bumiller
72106b0982 removing some left-over alloc checks 2013-02-05 17:34:40 +01:00
Dale Weiler
fed0f8b6b4 Work in progress <=> operator. 2013-02-05 16:34:03 +00:00
Wolfgang Bumiller
f860759758 fixing that comment 2013-02-05 17:24:02 +01:00
Wolfgang Bumiller
15141897ae insert an error when an operator doesn't get found - note the comment... 2013-02-05 17:17:38 +01:00
Dale Weiler
31ce4c2afa Better handling of multiple body functions. 2013-02-05 03:28:20 +00:00
Dale Weiler
8e1cd4b1df Update doc/specification.tex 2013-02-04 11:13:11 -05:00
Dale Weiler
442adee298 Update doc/specification.tex 2013-02-04 06:22:28 -05:00
Dale Weiler
e11a17b408 Update doc/specification.tex 2013-02-04 02:48:36 -05:00
Dale Weiler
e7aa24bd28 Work in progress specification LaTeX document for "The GMQCC QuakeC Programming Language" 2013-02-04 07:18:39 +00:00
Wolfgang Bumiller
06ff6eb054 get that message back in 2013-02-04 00:28:35 +01:00
Wolfgang Bumiller
ce8b595ff2 Yes, that's what you are SUPPOSED to do in this case: ERROR, not default to crap 2013-02-04 00:20:41 +01:00
Wolfgang Bumiller
46892daa3a Reverting this awful unmaintainable mess of option description system 2013-02-04 00:19:56 +01:00
Wolfgang Bumiller
e662efae61 fix: rotate_entfield_array_index_nodes deleting the old array caused expressions to be deleted recursively 2013-02-03 23:38:06 +01:00
Wolfgang Bumiller
530dbd85b2 properly mask #message, #warning, #error by ftepp->output_on 2013-02-03 23:23:50 +01:00
Wolfgang Bumiller
0d1b40c9c1 Adding a WIP style sheet for mandoc html output 2013-02-03 19:38:42 +01:00
Wolfgang Bumiller
c41ef65cc9 Merge branch 'master' into cooking 2013-02-03 19:01:30 +01:00
Wolfgang Bumiller
95dd0fcd9f Add -fdarkplaces-string-table-bug to the default flags 2013-02-03 19:01:27 +01:00
Dale Weiler
2b51b35634 Fix this target for archlinux 2013-02-02 09:02:03 +00:00
Dale Weiler
ddb0be6c0a Merge pull request #96 from matthiaskrgr/cooking_PKGBUILD
PKGBUILDs: rename "arch" to "archlinux", move archbsd PKGBUILDs into own...
2013-02-02 00:58:57 -08:00
matthiaskrgr
2e07a7b2c1 PKGBUILDs: rename "arch" to "archlinux", move archbsd PKGBUILDs into own "archbsd" parent directory. 2013-02-02 09:54:31 +01:00
Dale Weiler
7b96b0bd6d s/%d/%s/ 2013-02-02 01:04:26 +00:00
Dale Weiler
319783e873 Better printing of token errors. 2013-02-02 01:03:39 +00:00
Dale Weiler
4c0a836ca6 typo 2013-02-02 00:59:19 +00:00
Dale Weiler
d45853f5fe Update authors file 2013-02-02 00:58:15 +00:00
Dale Weiler
9bf8f9c505 Add bitnot test for testsuite. 2013-02-02 00:12:46 +00:00
Dale Weiler
ccdfd4c65a oops 2013-02-01 23:12:48 +00:00
Dale Weiler
394f1deade Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-02-01 23:11:26 +00:00
Dale Weiler
a3559548a8 Fix ~ unary operator (can now const-fold). Also things like b &= ~1 work now. We also cache ast_value of float (-1) for -1-x (which is how ~ is implemented). 2013-02-01 23:10:23 +00:00
Wolfgang Bumiller
c34f5d20ed Merge branch 'cooking' of git://github.com/graphitemaster/gmqcc into cooking 2013-02-01 19:12:45 +01:00
Dale Weiler
03b933bc7a Work in progress ~ operator implemented as -1-x. 2013-02-01 12:56:01 +00:00
Dale Weiler
bf6eb9432e Fix memleak and assignment for cached lengths in corrector 2013-02-01 06:22:29 +00:00
Wolfgang Bumiller
ea15abada5 manpage: removed -Wpreprocessor 2013-01-31 22:23:29 +01:00
Wolfgang Bumiller
622c55f254 converted qcvm.1 to mdoc 2013-01-31 22:15:01 +01:00
Dale Weiler
d7a47eb5f9 Ignore most memory comparisions by validating the lengths are the same first. Becomes O(log(n)) from O(n) for correct_exists. 2013-01-30 23:32:15 +00:00
Dale Weiler
a6ecc3cbc4 Cache lengths in corrector. This speeds up the corrector a little. 2013-01-30 23:22:03 +00:00
Dale Weiler
a1fac66587 Added definition file for test-suite, used by default by the test system. To override the defs globally, use -defs=file from the command line for the test-suite. To override the defs per-file, use F: -no-defs flag in the test template file. 2013-01-30 08:04:56 +00:00
Dale Weiler
9fffb3441c Older clang had -Wmissing-variable-declarations, which causes a heap of warnings, we disable it, because it's a stupid warning. However, because it's unsupported in newer clang, disabling it causes a warning, so we need to -Wno-unknown-warning-option. *sigh* 2013-01-30 06:52:36 +00:00
Dale Weiler
5f9f6c11b8 Get it compiling with C++ compilers again. 2013-01-30 06:49:50 +00:00
Dale Weiler
1916a6e339 Slightly larger code, but strategic inline for corrector stuff. Makes it a little faster on my RPi (unnoticable on my desktop though). 2013-01-30 06:36:00 +00:00
Dale Weiler
b9f46f4ef7 Not an assembler instruction, but virtual instruction used by the IR. 2013-01-30 06:31:24 +00:00
Dale Weiler
18c317a787 Empty string, not "<null>" 2013-01-30 06:28:02 +00:00
Dale Weiler
8c6f4c3fc3 Cleanups 2013-01-30 06:27:06 +00:00
Dale Weiler
835659ac48 Don't ignore return result from test_perform. 2013-01-30 06:17:57 +00:00
Dale Weiler
44c87bedfc It is used, gcc is a liar. 2013-01-30 06:14:35 +00:00
Dale Weiler
98fd5cd429 Some cleanups and what not. 2013-01-30 06:13:11 +00:00
Dale Weiler
ebd6a1ae95 Document the options in the opts.def file 2013-01-30 06:04:34 +00:00
Dale Weiler
9f5f2b6d74 Fix pragma parsing that I broke. 2013-01-30 05:51:28 +00:00
Dale Weiler
e12d492d67 Removing #error/#warning/#message from parser, and making it part of preprocessor as directives again. 2013-01-30 05:49:08 +00:00
Dale Weiler
36c5722273 Rename 2013-01-30 05:35:07 +00:00
Dale Weiler
d201cfe6b4 Work in progress options cleanup. 2013-01-30 05:24:30 +00:00
Dale Weiler
6c4c373089 Print off the documentation when -[f/W/O]help, also fixed some of the descriptions for flags. 2013-01-30 04:22:13 +00:00
Dale Weiler
480b2fc7b6 Added documentation to all options inside the binary itself. These will be used later for "man/nroff -man"-like documentation on OSs that lack "man" and the concept of system wide documentation. Also it will be nice to add -Wsome_warning help (to get some help about a specific warning/error, etc). 2013-01-30 02:56:58 +00:00
Dale Weiler
f3c5c40104 Fix splint warning 2013-01-30 01:38:37 +00:00
Dale Weiler
76614b311e s/WARN_PREPROCESSOR/WARN_CPP/g (to stay somewhat compatible with gcc/clang warnings for the preprocessor) 2013-01-30 01:32:10 +00:00
Dale Weiler
d61172598e Removed -Wcpp (not needed any more) 2013-01-30 01:26:51 +00:00
Dale Weiler
3d35804a7d Removed #warning and #error from ftepp, and made it part of the parser routine. These are "directives" that should exist regardless if -fftepp is enabled, like #pragma. Implemented #warning, #message and #error as directives in parser instead. 2013-01-30 01:24:58 +00:00
Dale Weiler
7ea1033a43 Handle all possible subscript errors 2013-01-27 21:31:18 +00:00
Dale Weiler
1597f38f45 Better handling of __VA_ARGS__ subscripting. 2013-01-27 21:27:50 +00:00
Dale Weiler
b9fcd64a1f Spiceing up the __VA_ARGS__ test 2013-01-27 13:05:01 +00:00
Dale Weiler
6fc5b32123 Fix warning, and better tests for __VA_ARGS__ 2013-01-27 13:03:02 +00:00
Dale Weiler
001d853f38 Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking 2013-01-27 12:56:43 +00:00
Dale Weiler
b4fbba5708 Implement subscripting for __VA_ARGS__, and added test-case. This only works on INTCONST for now. 2013-01-27 12:55:56 +00:00
Wolfgang Bumiller
370b54251e importing bsd-git/PKGBUILD 2013-01-27 13:12:57 +01:00
Wolfgang Bumiller
95e8140555 fixing an install cmd in bsd-release/PKGBUILD 2013-01-27 13:12:04 +01:00
Wolfgang Bumiller
3518646ad7 unmasking bsd-git/PKGBUILD in .gitignore 2013-01-27 13:10:44 +01:00
Wolfgang Bumiller
03f364a944 importing ArchBSD release PKGBUILD 2013-01-27 13:09:09 +01:00
Wolfgang Bumiller
44e416e790 unmasking bsd-release path in .gitignore 2013-01-27 13:08:31 +01:00
Wolfgang Bumiller
3e1c10628c adding pkgrel to arch/this, and getting rid of du's -b option since it won't work for ArchBSD 2013-01-27 10:31:27 +01:00
Dale Weiler
531fbaf28c Remove user-defined success/failure messages for the testsuite. Instead print an aligned to console string containing the tmpl file name. This closes #90. 2013-01-27 08:39:42 +00:00
Dale Weiler
a94d2fee4e Fixes, updates, and added uninstall target for makefile 2013-01-27 07:45:49 +00:00
Dale Weiler
3cc97984bf Add back the removal of the package directory after building package. 2013-01-27 07:26:50 +00:00
Dale Weiler
74ba208a44 Fix the size calculation 2013-01-27 07:25:46 +00:00
Dale Weiler
b4d3241e27 Add this/Makefile for generating a .tar.xz for arch packages. This is sort of like the debian one, it can be run from any *nix systems to generate a package. Currently only generates an x86_64 package, like the debian one (which only does i686). 2013-01-27 07:08:27 +00:00
Wolfgang Bumiller
4500facb2b manpage: wrong date 2013-01-26 14:44:00 +01:00
Wolfgang Bumiller
edfe340d09 Fix a warning 2013-01-26 14:43:49 +01:00
Wolfgang Bumiller
b39b61e514 store the actual parsing context before parsing into an expression and use that for the effectless-statement warning 2013-01-25 23:37:06 +01:00
Wolfgang Bumiller
9afe41471b error when using a type not usable as boolean in a condition, ie an if statement 2013-01-25 19:19:23 +01:00
Wolfgang Bumiller
7fb3b97e73 -v now prints the initial value of globals in -printdefs 2013-01-25 19:17:31 +01:00
Wolfgang Bumiller
48f8d0e0c3 changing some error prints to print to stderr in exec.c 2013-01-25 18:41:17 +01:00
Wolfgang Bumiller
ad7059156a now moving -Ocall-stores to -O3 2013-01-25 16:25:59 +01:00
Wolfgang Bumiller
9b51e7085b In this situation the values don't need to be in parameter order; fix: call-stores putting values into wrong extparams 2013-01-25 16:25:23 +01:00
Wolfgang Bumiller
31f0c05ebc Merge branch 'master' into cooking 2013-01-25 16:03:38 +01:00
Wolfgang Bumiller
3c8ce7c866 moving -Ocall-stores to -O4 until the vehicle issue is solved 2013-01-25 16:03:16 +01:00
Wolfgang Bumiller
69e29c3ef8 debug extparam naming shouldn't start at 8, it's confusing, param 9 is now named extparam0 2013-01-25 15:37:09 +01:00
Wolfgang Bumiller
ef0de47954 Converting gmqcc.1 from man to mdoc style. It can produce nice html output so we can create an online version of the manpage which doesn't look like crap... still todo: qcvm.1 2013-01-24 22:23:49 +01:00
Wolfgang Bumiller
32f1a5d2c8 manpage: fixing a .TP/.B mixup 2013-01-24 12:56:38 +01:00
Wolfgang Bumiller
62af1659eb adding testcase for various parentheses and ternary combinations which to test the newly refactored code; includes some cases not hit by xonotic 2013-01-18 15:22:53 +01:00
Wolfgang Bumiller
dca9dd56d1 adding missing wantop flag and some related parentheses code 2013-01-18 15:22:03 +01:00
Wolfgang Bumiller
ba207cc04c Major expression parsing code refactoring, getting rid of lots of duplicated code and in the process also fixing a bug. Still thie will require more testing. xonotic code works with it though 2013-01-18 14:50:37 +01:00
Dale Weiler
496aededb1 Fix debian package building, now works. 2013-01-18 00:45:35 +00:00
Wolfgang Bumiller
5d9ad219cf removing unused vars, and following conventions 2013-01-17 23:46:27 +01:00
Dale Weiler
99482a324e -f to supress error if file doesn't exist for rm clean target 2013-01-17 22:34:39 +00:00
Dale Weiler
57102aea4a Use $(PREFIX) 2013-01-17 22:34:06 +00:00
Dale Weiler
1d4c0bb388 Fix the brokenness 2013-01-17 22:33:02 +00:00
Wolfgang Bumiller
de28df33ec Rather than performing copying the install-procedure, the debian Makefile could just use the main Makefile's install target 2013-01-17 23:25:09 +01:00
Wolfgang Bumiller
a8d5504445 fixing manpage permissions 2013-01-17 23:22:38 +01:00
Dale Weiler
94a83ad969 Added makefile script for generating deb packages the portable .. but more manual way. It doesn't support multi-architecture yet. It just grabs what ever is already compiled. Not tested! 2013-01-17 22:10:36 +00:00
Wolfgang Bumiller
06f53b1a28 When not actually executing, don't complain about invalid progs.dat versions for now. 2013-01-17 17:36:06 +01:00
Wolfgang Bumiller
8697fa59f3 Added counter-stability test to the varargs testcase 2013-01-17 10:32:43 +01:00
Wolfgang Bumiller
1410840ef6 Make the varargs counter more stable, it'll now work with a function pointer with a different number of fixed params 2013-01-17 10:30:32 +01:00
Wolfgang Bumiller
4c0a358e2b Update CHANGES file 2013-01-17 10:06:01 +01:00
Wolfgang Bumiller
d5ba5a6e6a linenumbers and macros are stupid 2013-01-16 23:34:54 +01:00
Wolfgang Bumiller
7d2b0e9638 more linenumber madness 2013-01-16 22:58:43 +01:00
Wolfgang Bumiller
b31e9b63eb fix: trigraph check screwing up linenumbering 2013-01-16 22:09:27 +01:00
Wolfgang Bumiller
81f3a6d186 fix an off-by-one bug when copying varargs 2013-01-16 21:04:08 +01:00
Wolfgang Bumiller
00a9d2a9e3 fixing a possible NULL deref 2013-01-16 20:32:37 +01:00
Wolfgang Bumiller
e311dffcb3 fixing a warning 2013-01-16 16:16:52 +01:00
Wolfgang Bumiller
0ba8455f6a initialize max_param_count to 1 so vararg functions don't try to create an accessor for an array of 0 elements... 2013-01-16 09:37:32 +01:00
Wolfgang Bumiller
dfad837f5b this might fix some linenumbering, I hope 2013-01-15 22:29:44 +01:00
Wolfgang Bumiller
11450c11d1 manpage: -E was missing all that time in there 2013-01-15 22:08:15 +01:00
Wolfgang Bumiller
dfa6d0c9ad call ftepp_recursion_header/footer only when there are newlines in the expanded macro 2013-01-15 22:03:16 +01:00
Wolfgang Bumiller
f8f4ad8ee5 a tiny speedup, seems like -O2 doesn't do that by itself 2013-01-15 20:57:30 +01:00
Wolfgang Bumiller
e695a5919d reduce the hashtable size a bit 2013-01-15 20:35:30 +01:00
Wolfgang Bumiller
b311cd6163 that tempbool should have gone long ago... 2013-01-15 20:27:23 +01:00
Wolfgang Bumiller
73afc98699 fix: on error it was possible that leaveblock() is called after the function's already been deleted 2013-01-15 14:28:15 +01:00
Wolfgang Bumiller
150c6e21e7 fix a goto to a wrong error-cleanup part 2013-01-15 14:23:17 +01:00
Wolfgang Bumiller
c7ca5683b9 fix a possible leak 2013-01-15 14:20:08 +01:00
Wolfgang Bumiller
0f190026e8 Error on an empty paren expression 2013-01-15 14:18:03 +01:00
Wolfgang Bumiller
ee7d45f492 add a hint about -fvariadic-args to -Wvariadic-function 2013-01-15 11:35:18 +01:00
Wolfgang Bumiller
b208c1a49f Fix a crash... if (!x) delete(x) yeah right... 2013-01-15 10:50:14 +01:00
Wolfgang Bumiller
73c86127f7 fix the broken vector instructions in our executor as well... how could I forget 2013-01-14 14:22:02 +01:00
Wolfgang Bumiller
bfbbe0c771 gmqcc.ini.example: LEGACY_VECTOR_MATHS 2013-01-14 11:17:25 +01:00
Wolfgang Bumiller
0962dfdd4d manpage: -flegacy-vector-maths 2013-01-14 11:16:49 +01:00
Wolfgang Bumiller
d12e6e15c9 -flegacy-vector-maths, enabled by default 2013-01-14 11:15:06 +01:00
Wolfgang Bumiller
d7f4e981a3 fix: missing-return check: vec_size(entries) is 0 on the entry-block, also check if it's the first block 2013-01-14 10:56:56 +01:00
Wolfgang Bumiller
bec05f1bbb apparently it's possible to segfault DP with a bad INSTR_LOAD_V - so the IR should not allow this 2013-01-13 21:00:13 +01:00
Wolfgang Bumiller
ab8cc64dfd constant-fold the 1/N division from a_vector/N 2013-01-13 20:53:07 +01:00
Wolfgang Bumiller
a5029a510a test for vec/float 2013-01-13 20:49:27 +01:00
Wolfgang Bumiller
3d62cb37f1 allow vec/float 2013-01-13 20:49:16 +01:00
Wolfgang Bumiller
e0504ce482 This undef was missing there... 2013-01-13 17:37:09 +01:00
Wolfgang Bumiller
12ffd83d4f parsewarning->compile_warning 2013-01-13 17:32:54 +01:00
Wolfgang Bumiller
8d4e395092 Replacing lots of parseerror calls with compile_error calls and a more correct context information 2013-01-13 17:31:31 +01:00
Dale Weiler
1d05cd28ee Merge pull request #85 from matthiaskrgr/master
better gitignore for arch linux pkgbuild related files
2013-01-12 17:33:01 -08:00
matthiaskrgr
3ecae267ad gitignore: be more clever 2013-01-13 02:11:08 +01:00
Wolfgang Bumiller
3652a122ed Removed -fenhanced-diagnostics - it's now --correct, which makes sense since it doesn't affect the compilation process itself 2013-01-12 17:10:07 +01:00
Dale Weiler
d1def27dbb Uhh I did it again 2013-01-12 15:47:41 +00:00
Dale Weiler
08200d4f77 serpate line travis-ci build url for notifications 2013-01-12 15:47:08 +00:00
Wolfgang Bumiller
7fc88cfe5b fix a build issue 2013-01-12 16:38:49 +01:00
Wolfgang Bumiller
61b777f575 vararg testcases 2013-01-12 16:37:26 +01:00
Wolfgang Bumiller
f440c3c614 gmqcc.ini.example: VARIADIC_ARGS 2013-01-12 16:32:36 +01:00
Wolfgang Bumiller
127cc5215b manpage: -fvariadic-args 2013-01-12 16:31:51 +01:00
Wolfgang Bumiller
4df6d1e028 guarding vararg code by -fvariadic-args 2013-01-12 16:28:04 +01:00
Wolfgang Bumiller
47db74c699 this is useless and just confused me a lot, removing 2013-01-12 16:20:31 +01:00
Wolfgang Bumiller
7dd31ccf77 entity setter array subscript needs to get a correct field type 2013-01-12 15:49:31 +01:00
Wolfgang Bumiller
5887afae62 copying the output type on ast_array_index_codegen 2013-01-12 15:49:04 +01:00
Wolfgang Bumiller
a01388ea7d Copying arg counter into the local 2013-01-12 15:06:19 +01:00
Wolfgang Bumiller
57c0a09800 Creating the argument counter if requested 2013-01-12 14:59:30 +01:00
Wolfgang Bumiller
175623592b updated CHANGES file 2013-01-12 14:54:11 +01:00
Wolfgang Bumiller
e149551744 Added '...(idx,type)' to access varargs 2013-01-12 14:53:48 +01:00
Wolfgang Bumiller
cd543aad5e added gen_function_varargs_copy 2013-01-12 14:48:56 +01:00
Wolfgang Bumiller
e8b5ad6625 mask -Olocal-temps by IR_FLAG_MASK_NO_LOCAL_TEMPS which now equals IR_FLAG_MASK_NO_OVERLAP - though HAS_ARRAYS usually suffices, but not for code which _depends_ on uninitialized variables 2013-01-12 14:03:54 +01:00
Wolfgang Bumiller
2a4ea74a97 ir_function stores max_varargs now 2013-01-12 14:01:16 +01:00
Wolfgang Bumiller
1861660585 builtins are generally not declared const, so don't expect CV_CONST, otherwise we write out va_count for builtin calls as well... 2013-01-12 13:52:42 +01:00
Wolfgang Bumiller
c10d127fd7 While at it: moving generation of reserved:version to just before the functions so no global/immedate is generated _after_ it - at least from the parser's point of view 2013-01-12 13:49:06 +01:00
Wolfgang Bumiller
d78997599a create store to reserved:va_count; fix: don't build vararg accessor ast tree after generating immediates as they create new ones 2013-01-12 13:47:56 +01:00
Wolfgang Bumiller
973122ed9b ast_call now has a va_count which causes a store to reserved:va_count before the call 2013-01-12 13:29:47 +01:00
Wolfgang Bumiller
6dfdf69a8e vararg accessor generation 2013-01-12 13:01:20 +01:00
Wolfgang Bumiller
c69ba2c734 parsing of vararg-counter 2013-01-12 11:29:03 +01:00
Wolfgang Bumiller
87ff481abf updated CHANGES file 2013-01-12 11:11:31 +01:00
Wolfgang Bumiller
6a248e2498 type restricted varargs 2013-01-12 11:10:29 +01:00
Wolfgang Bumiller
ca947d782c Declaration of type-restricted varargs 2013-01-12 11:03:17 +01:00
Wolfgang Bumiller
2f9db8972e keep track of the highest parameter count of calls for later for varargs 2013-01-12 10:58:01 +01:00
Wolfgang Bumiller
3429e7d0cb 'static' shouldn't be accepted in the global scope for now 2013-01-12 10:52:18 +01:00
Wolfgang Bumiller
30eac57199 filling type_name in exec.c 2013-01-11 23:15:16 +01:00
Wolfgang Bumiller
5bb4e40c72 code cleanup: prog_tempstring used to cast const char * parameter to char * due to the old vector code which is now gone 2013-01-11 23:13:36 +01:00
Wolfgang Bumiller
7bab7fc42e fixing CHANGES: this actually was not part of 0.2 2013-01-11 23:12:00 +01:00
Wolfgang Bumiller
d6ffcbb8fc CHANGES file updated 2013-01-11 23:10:41 +01:00
Wolfgang Bumiller
199ed6c31f Fix a typo - why the hell does clang not complain? Why the hell does it even compile with clang... 2013-01-11 20:04:46 +01:00
Wolfgang Bumiller
5231279113 manpage: --add-info 2013-01-11 19:23:03 +01:00
Wolfgang Bumiller
3436fa7d89 added the --add-info compile switch: it adds a global const string named version to the 'reserved' namespace, ie ends up named 'reserved:version', containing the --version string 2013-01-11 19:18:51 +01:00
Wolfgang Bumiller
6df3c625b0 Added a flag to both ast and ir which enforces the generation of a globaldef for a value 2013-01-11 19:15:59 +01:00
Wolfgang Bumiller
5ea710e317 In order to avoid release version strings in non-git builds, by default --version on non-tagged commits now also prints 'development build' as the 2nd line 2013-01-11 10:40:33 +01:00
Wolfgang Bumiller
88cfa53dc2 replacing an error message in the enum parsing 2013-01-10 22:08:49 +01:00
Dale Weiler
0d9144eeff mention CHANGES in README 2013-01-10 20:52:23 +00:00
Dale Weiler
f6197a965c Better enumeration test 2013-01-10 20:50:42 +00:00
Wolfgang Bumiller
4a063d3518 enum testcase 2013-01-10 21:38:32 +01:00
Dale Weiler
0da4626417 will warn about "check" no such file or directory (since it aliases in the rule for the Makefile) 2013-01-10 20:28:53 +00:00
Wolfgang Bumiller
fa90d2d06e correction fix: don't try to create edits for an empty string 2013-01-10 21:09:44 +01:00
Wolfgang Bumiller
0616bb9468 CHANGES file updated 2013-01-10 21:05:10 +01:00
Wolfgang Bumiller
9c2bc7f381 Allow accessing vector components via the . operator, including components
of expressions, like: (3 * a_vector).y.
2013-01-10 21:03:35 +01:00
Wolfgang Bumiller
a474f20b84 CHANGES file updated 2013-01-10 19:59:01 +01:00
Wolfgang Bumiller
aa8b9eb1ad parse_expression_leave: also end at a closing } - enum: check for } and , after an expression again 2013-01-10 18:52:43 +01:00
Wolfgang Bumiller
a468d0b478 simple 'enum' implementation 2013-01-10 18:38:57 +01:00
Wolfgang Bumiller
1c1ea1d0f7 strictness sweep: (void)-ing all vec_ macros which don't evaluate to a sensible value 2013-01-10 18:26:35 +01:00
Wolfgang Bumiller
101cb09e91 git package is now named gmqcc-git, also added conflicts/provides 2013-01-10 16:31:01 +01:00
Wolfgang Bumiller
f69f2c2ece the -git PKGBUILD needs 'git' as makedepends according to the guidelines on the arch wiki 2013-01-10 16:25:36 +01:00
Wolfgang Bumiller
16ccaffc3f checking if git even is available 2013-01-10 16:13:47 +01:00
Wolfgang Bumiller
7a5a328c54 --version now prints GMQCC_GITINFO, which is not not defined in gmqcc.h to some empty string, it just won't exist in release builds 2013-01-10 16:07:33 +01:00
Wolfgang Bumiller
f06a59e3c7 Fix a warning 2013-01-10 16:04:58 +01:00
Wolfgang Bumiller
ffba3429fb This file seems to live in the past. Let's pull it over 2013-01-10 15:55:58 +01:00
Wolfgang Bumiller
cf676443cb manpage: updating the section about nil vs fteqcc-__NULL__ 2013-01-10 15:41:36 +01:00
Wolfgang Bumiller
81cc4194dc fixed a bug which allowed some statements to end in tokens other than semicolons... (ie closing parens) 2013-01-10 15:23:04 +01:00
Wolfgang Bumiller
428453a132 for compile-time constants << and >> are now available 2013-01-10 15:12:19 +01:00
Wolfgang Bumiller
06101d48e4 manpage: A note about __NULL__ vs nil 2013-01-09 21:54:36 +01:00
Wolfgang Bumiller
d0efaa50d4 Adding a CHANGES file 2013-01-09 21:49:28 +01:00
Wolfgang Bumiller
96126b435a manpage: __DATE__, __TIME__ predefs 2013-01-09 21:32:17 +01:00
Wolfgang Bumiller
10c7f4f838 don't call correct_edit anew for each scope 2013-01-09 21:16:22 +01:00
Wolfgang Bumiller
6b0a522bb9 Factor out the adding of globals in various places into parser_addglobal; Add globals to the correct_variables lists 2013-01-09 20:42:33 +01:00
Wolfgang Bumiller
704ddf94f8 manpage: Document change to -Wall 2013-01-09 20:41:12 +01:00
Wolfgang Bumiller
4f7113116d -Wall now does not set -Wuninitialized-global 2013-01-09 20:39:17 +01:00
Wolfgang Bumiller
be6942d972 fixing a crash caused by the correction: setting correct=NULL after freeing so the later if(correct) check properly fails 2013-01-09 19:12:27 +01:00
Wolfgang Bumiller
9eefe90d78 removing a goto loop 2013-01-09 16:00:16 +01:00
Wolfgang Bumiller
16e789419d testcase for mul_vf/fv 2013-01-08 21:55:34 +01:00
Wolfgang Bumiller
7d4340469e So it wasn't _reall_ the optimization... it just made it easier. -Olocal-temps -> -O3 2013-01-08 21:23:38 +01:00
Wolfgang Bumiller
a76ae11241 more IR dump verbosity; fix: MUL_VF/FV additional liferange must be propagated to the full vector when using a vector-member as float-parameter 2013-01-08 21:21:52 +01:00
Wolfgang Bumiller
6ece523552 sqrt and normalize builtins 2013-01-08 20:46:30 +01:00
Wolfgang Bumiller
d6809ed331 better solution to blockstart pointlife issues 2013-01-08 15:22:24 +01:00
Wolfgang Bumiller
4c05230cb3 Seems like there's still a problem with it - -Olocal-temps back up to -O4 2013-01-07 20:27:50 +01:00
Wolfgang Bumiller
3f3ed9b6f0 added a testcase for -Olocal-temps 2013-01-07 19:09:15 +01:00
Wolfgang Bumiller
57c3d48711 error when trying to break/continue outside of loops/switches instead of segfaulting at codegen 2013-01-07 15:19:53 +01:00
Wolfgang Bumiller
debfe136a5 Moving -Olocal-temps back to -O3 2013-01-07 14:55:42 +01:00
Wolfgang Bumiller
ae97ff7a80 This should fix the -Olocal-temps issue; set v->unique_life for any v with a point-life - this is a bad solution: proper dead code elimination should be done instead 2013-01-07 14:55:05 +01:00
Wolfgang Bumiller
63e5bc91de more info in the IR dump 2013-01-07 14:55:05 +01:00
Dale Weiler
a395a20dba close #76 implemented -Werror-some-warning section [errors] for the ini system. 2013-01-07 12:46:50 +00:00
Dale Weiler
54c8801bec Merge branch 'master' of github.com:graphitemaster/gmqcc 2013-01-07 12:40:03 +00:00
Dale Weiler
d8ae1cb3e9 Move splint.sh into the Makefile 2013-01-07 12:39:33 +00:00
Wolfgang Bumiller
cbb91c2026 moving -Olocal-temps to -O4 until the issues are solved 2013-01-07 12:58:56 +01:00
Wolfgang Bumiller
99249c8fa3 Guard 2 peephole optimizations which should only work on the currently-last instruction by a check if it's actually really at the end... 2013-01-07 00:22:54 +01:00
Wolfgang Bumiller
f4d1ef4740 Fix some possible NULL access in an error case 2013-01-07 00:22:16 +01:00
Wolfgang Bumiller
4d72c85f73 __STD_QCCX__ on -std=qccx - I have no idea about what qccx does/can do but at least now -fftepp includes the macros... 2013-01-06 20:52:12 +01:00
Wolfgang Bumiller
5134673461 manpage: bring the list of included -f and -W flags for each described -std up to date 2013-01-06 20:50:18 +01:00
Wolfgang Bumiller
5d1685b93d Adding -ftranslatable-strings to -std=gmqcc 2013-01-06 20:49:57 +01:00
Wolfgang Bumiller
dcc511f4c3 make the LNOF header compiler friendlier 2013-01-06 16:40:38 +01:00
Wolfgang Bumiller
e59d50ee5d Merge branch 'master' of git://github.com/graphitemaster/gmqcc 2013-01-06 16:37:05 +01:00
Wolfgang Bumiller
2531a3695f fixup qcvm parameter handling, now progs.dat can be specified anywhere not just at the end 2013-01-06 16:37:02 +01:00
Dale Weiler
985a177288 Pipe stderr from makedepend for depend rule in makefile to /dev/null 2013-01-06 15:27:39 +00:00
Dale Weiler
ecb83404ab Add test alias to check for make file 2013-01-06 15:12:46 +00:00
Dale Weiler
8ac6bcdad7 Add splint rule to makefile 2013-01-06 12:43:46 +00:00
Dale Weiler
4f873e1d9d remove never reached return 2013-01-06 12:39:37 +00:00
Dale Weiler
7cc7e912e7 Enable corrector by default 2013-01-06 12:29:25 +00:00
Dale Weiler
72f056a4d7 Merge branch 'screwaround' 2013-01-06 12:29:07 +00:00
Dale Weiler
ac5cc49840 remove a the 2013-01-06 12:28:27 +00:00
Dale Weiler
9a4e215179 Document the awesome hack 2013-01-06 12:24:05 +00:00
Wolfgang Bumiller
9c8ddb3771 An evil optimization to the trie, now has a fixed amount of branches and uses a char-to-index map to index into the branches... 2013-01-06 13:07:28 +01:00
Dale Weiler
1e17b5f696 Cleaner transformation calls (one less size_t for agruments). We can coalesce it in correct_edit. 2013-01-06 11:02:39 +00:00
Dale Weiler
3fa771f51d Leave a space here for makedepend 2013-01-06 10:56:25 +00:00
Dale Weiler
4afe61060d Add a "depend" rule for the makefile. It uses makedepend to generate dependinces that are catted to the current Makefile. 2013-01-06 10:55:22 +00:00
Dale Weiler
0f4090402d No need to +1 for comparision in correct_known_resize 2013-01-06 10:37:09 +00:00
Dale Weiler
cfdeaf4786 Fix comments 2013-01-06 10:35:43 +00:00
Dale Weiler
056779d3b8 Remove trailing shitspace 2013-01-06 10:33:09 +00:00
Dale Weiler
6f5a20e76b Use -O2 by default 2013-01-06 10:29:29 +00:00
Dale Weiler
a4c1e63637 Less pointer dereferences 2013-01-06 05:17:30 +00:00
Dale Weiler
cc7e1a3363 Screw you clang :-) 2013-01-06 05:14:57 +00:00
Dale Weiler
ee33b4e5cc A little faster, plus some more research 2013-01-06 05:13:19 +00:00
Dale Weiler
0c59274c54 This is a work of art, it deserve nice comments :) 2013-01-06 04:09:12 +00:00
Dale Weiler
d98cc564b1 Fixes and more documentation 2013-01-06 04:06:38 +00:00
Dale Weiler
44a7154f58 Add a notice 2013-01-06 03:52:37 +00:00
Dale Weiler
106db76b9d Use memcmp with strlen for correct_exists (it's a hell of a lot faster) 2013-01-06 03:34:56 +00:00
Dale Weiler
cc8558025b No more uninitialized 2013-01-06 03:33:21 +00:00
Dale Weiler
9841240aab Some more nicer loops 2013-01-06 03:29:55 +00:00
Dale Weiler
e2e4907b60 Nicer loops 2013-01-06 03:26:09 +00:00
Dale Weiler
7e87c61d78 Cleanups and documentation 2013-01-06 03:06:56 +00:00
Dale Weiler
294870c5ba Remove override macros 2013-01-06 02:41:15 +00:00
Dale Weiler
efecd160ca Remove an illegal mem_d 2013-01-06 02:40:36 +00:00
Dale Weiler
0fb089fbb7 Cleanup the pool system for correct.c. Use blubs correct_resize stuff. 2013-01-06 02:39:07 +00:00
Dale Weiler
682c43973e Don't use notices 2013-01-05 20:44:53 +00:00
Dale Weiler
726d163631 Better IRC hook 2013-01-05 20:43:47 +00:00
Dale Weiler
7a5bb20778 notifications 2013-01-05 20:39:50 +00:00
Dale Weiler
caa44e82e0 Add irc to travis 2013-01-05 20:39:17 +00:00
Dale Weiler
41a01c08e1 Add travis.yml 2013-01-05 20:31:17 +00:00
Wolfgang Bumiller
8bc9d4b427 Committing an evil allocator and a trie to speed up the correction stuff 2013-01-05 19:09:36 +01:00
Wolfgang Bumiller
b8d238d76b Merge branch 'master' of git://github.com/graphitemaster/gmqcc 2013-01-04 14:52:00 +01:00
Wolfgang Bumiller
0e3bb0e4f4 Get rid of correct_strndup and correct_concat altogether, reduces each generated edit to a single alloc 2013-01-04 14:50:50 +01:00
Dale Weiler
ec4cd0d258 Disable enhanced diagnostics as they're too slow. 2013-01-04 12:26:44 +00:00
Dale Weiler
793547a132 Implemented -f[no]enhanced-diagnostics, to enable/disable the usage of enhanced diagnostics. 2013-01-04 12:07:42 +00:00
Dale Weiler
5377835f1e Remove constant string literal for correction check, use parse_tokval of the current parser state instead. Accidently left it behind from debugging. 2013-01-04 11:58:27 +00:00
Dale Weiler
2d96b2a3ec Merge branch 'correct' 2013-01-04 11:56:07 +00:00
Dale Weiler
36d02d010e Got rid of all the memleaks. We can now merge with master. 2013-01-04 11:53:40 +00:00
Dale Weiler
18b9473cf8 Itegration of corrector. Seems to be some leaks in the score keeping for the probability system. 2013-01-04 11:44:25 +00:00
Dale Weiler
d97e032fcf Cleanups and add the corrector to the makefile. Starting integration with the parser. 2013-01-04 10:05:41 +00:00
Dale Weiler
7ef051f58a Fix all the memleaks in the corrector. Holy shit, the amount of hours I wasted trying to find out where I left out ONE little free. 2013-01-04 09:46:22 +00:00
Dale Weiler
ab64706cc3 Fix another two leaks 2013-01-03 21:38:07 +00:00
Dale Weiler
2189dd4b85 Remove some memory leaks in the corrector. There is still some memory leaks that are proving impossible to fix. 2013-01-03 21:25:35 +00:00
Dale Weiler
861987e13e Work on "did you mean? <ident>" support for errors. Using a three-part Bayes Theorem expression (language model, error model and control mechanisim). 2013-01-03 19:44:13 +00:00
Wolfgang Bumiller
9edae7fa0a Merge remote-tracking branch 'origin/pp-unary-numbers' 2013-01-03 14:58:02 +01:00
Wolfgang Bumiller
cf293bc669 handling the ast-destruction in computed goto 2013-01-03 13:21:11 +01:00
Dale Weiler
7d14fdf530 Merge branch 'master' of github.com:graphitemaster/gmqcc 2013-01-03 12:05:02 +00:00
Dale Weiler
9bda8f61f4 Add specialized diagnostics for when predefined macros are used and ftepp predefined macros are not enabled. 2013-01-03 12:04:32 +00:00
Wolfgang Bumiller
614fcb12f5 check for TYPE_NOEXPR in general when applying an operator 2013-01-03 12:56:26 +01:00
Wolfgang Bumiller
ae09831227 Introducing TYPE_NOEXPR so that these undefined labels cannot be used on the expression side of goto ternary expressions; ast_label now is TYPE_NOEXPR; we may consider setting ast_ifthen to that too unless we want ifthen to return a value... 2013-01-03 12:49:21 +01:00
Wolfgang Bumiller
e146fd121c parse_expression now takes a boolean flag on whether or not it should be creating ast_labels for undefined identifiers; creating the label later will pick it up and set its undefined flag to false 2013-01-03 12:46:33 +01:00
Dale Weiler
0ab15e9f22 Fix argument padding for win_fputs and alike. 2013-01-03 10:33:35 +00:00
Dale Weiler
a168c5efbe More error checking and proper unreferencing of ast nodes if expressions for computed goto fails. 2013-01-02 22:39:24 +00:00
Dale Weiler
c1734d1b27 Some error checking for computed goto. 2013-01-02 22:28:26 +00:00
Dale Weiler
c750828632 Fix the testsuite bug, and implemented QCFLAGS enviroment variable support for setting the compile flags (the .tmpl rules takes precedence). 2013-01-02 22:16:02 +00:00
Dale Weiler
a2f63aae33 Implemented __TIME__ for ftepp 2013-01-02 21:53:46 +00:00
Dale Weiler
908f6ded8a Implemented __DATE__ for ftepp 2013-01-02 21:51:22 +00:00
Dale Weiler
e08e4a9ce0 Remove "got" left behind from debugging. 2013-01-02 21:35:18 +00:00
Dale Weiler
a421d9a33b Implemented computed goto + added goto test for testsuite (tests both normal and computed goto statements). 2013-01-02 21:32:57 +00:00
Wolfgang Bumiller
6c076f99f6 lex->flags.preprocessing causes the lexer to parse the unary number if it is one 2013-01-02 17:38:24 +01:00
Dale Weiler
467a4740da Fix some issues 2013-01-02 16:34:55 +00:00
Wolfgang Bumiller
654eceb33b Allow unary minus in ftepp_if_value 2013-01-02 17:26:35 +01:00
Wolfgang Bumiller
0d839bd138 pragma code: signed correctness 2013-01-02 15:20:07 +01:00
Wolfgang Bumiller
558a091c08 remove ast.h-include from lexer.h to parser.c... 2013-01-02 15:08:02 +01:00
Wolfgang Bumiller
14593ce789 Makefile: ftepp.o: lexer.h 2013-01-02 15:05:52 +01:00
Wolfgang Bumiller
359ba5f728 lex.peek char->int 2013-01-02 15:03:20 +01:00
Wolfgang Bumiller
8331a2982d tests for __VA_ARGS__ 2013-01-02 14:16:42 +01:00
Wolfgang Bumiller
38a664ed72 __VA_ARGS__ support 2013-01-02 14:15:16 +01:00
Wolfgang Bumiller
3c212c8389 fix a leak: delete the output string of macro calls 2013-01-02 10:45:55 +01:00
Wolfgang Bumiller
dce7a0c72b update old_string on failure in ftepp_macro_expand to not segfault on a preprocessor-error inside recursive preprocessor calls 2013-01-02 10:44:39 +01:00
Wolfgang Bumiller
c7280fca52 when recursinve into macros copy the previous line number; fixes macros showing line 1 for each error 2013-01-02 10:35:00 +01:00
Dale Weiler
686394654f Implemented a optimized hash-set that can be used in various parts of the compiler (to get a little more speed). I intend this to replace the hackery that is code_genstring, and code_util_str_htgeth. 2013-01-01 07:59:04 +00:00
Dale Weiler
29db4a44ed Happy new years! 2013-01-01 05:08:55 +00:00
Dale Weiler
2f356f12e6 Fix util_vasprintf. 2012-12-31 18:50:57 +00:00
Dale Weiler
f4c3080824 Add todo about util_vasprintf (too lazy to fix right now) 2012-12-31 18:34:13 +00:00
Dale Weiler
1182ab55c5 Fix #include for <machine/endian.h> s/endiane/endian/ 2012-12-31 14:40:08 +00:00
Wolfgang Bumiller
2b1eaa6df3 Actually allocate a nil-vector for nil 2012-12-31 13:25:18 +01:00
Wolfgang Bumiller
5a5cb74db2 add codegen_output_type to ast_binary_codegen 2012-12-31 13:20:08 +01:00
Wolfgang Bumiller
0c673dfebb fix store op for nil as parameter 2012-12-31 13:19:34 +01:00
Wolfgang Bumiller
12d87fba1b Adding '&~=' to the -std=gmqcc operator list 2012-12-31 12:56:04 +01:00
Wolfgang Bumiller
0920cb6ec4 Another hardcoded -std=gmqcc option removed and added to the implied -std=gmqcc flags 2012-12-31 12:43:15 +01:00
Wolfgang Bumiller
0626bbef8e remove another hardcoded -std=gmqcc case 2012-12-31 12:40:09 +01:00
Wolfgang Bumiller
d8254cede0 -std=gmqcc now implies -Werror-missing-return-values; another hardcoded error removed 2012-12-31 12:37:47 +01:00
Wolfgang Bumiller
17951ac92c Just allow variable declarations in for-loop initializers in any standard... 2012-12-31 12:35:26 +01:00
Wolfgang Bumiller
d47da25b82 Changing -Wtoo-few-parameters to -Winvalid-parameter-count; removing hardcoded COMPILER_GMQCC code which makes invalid parameter counts an error and instead make -std=gmqcc imply -Werror-invalid-parameter-count 2012-12-31 12:29:25 +01:00
Wolfgang Bumiller
26d43e650f Adding some more internal-error messages where they were missing; fixed ast_ternary_codegen to use the ast_node's type instead of the ir generated ones to avoid erroring on TYPE_NIL 2012-12-31 12:08:47 +01:00
Wolfgang Bumiller
a170154927 nil in ternary, and fix ternary to honor -fcorrect-logic/-ftrue/false-empty-strings 2012-12-31 11:45:00 +01:00
Wolfgang Bumiller
2cf4b4e56d Explicitly allow 'return nil' 2012-12-31 11:39:00 +01:00
Wolfgang Bumiller
4d5153854b This should actually cover all nil cases 2012-12-31 11:34:29 +01:00
Wolfgang Bumiller
819ed10f29 nil check in paramter type checking 2012-12-31 11:30:02 +01:00
Wolfgang Bumiller
5bb9351a3f Allow assigning nil to a field 2012-12-31 11:23:49 +01:00
Wolfgang Bumiller
2637f6f824 gmqcc.ini.example: -Wparenthesis 2012-12-31 11:14:43 +01:00
Wolfgang Bumiller
f698e796d2 manpage: -Wparenthesis 2012-12-31 11:14:34 +01:00
Wolfgang Bumiller
3538b505da Activate -Wparenthesis by default 2012-12-31 11:14:24 +01:00
Wolfgang Bumiller
0c4806b4a0 Adding -Wparenthesis, fixing constant folding of && and || 2012-12-31 11:11:46 +01:00
Dale Weiler
d750d17be5 Fix evaluation order bug 2012-12-30 11:01:45 +00:00
Wolfgang Bumiller
5a013c5b89 Do we REALLY need to listen to splint? 2012-12-30 11:59:29 +01:00
Wolfgang Bumiller
d9282ed988 Clean up trailing whitespaces 2012-12-30 11:03:59 +01:00
Dale Weiler
af3ba03a5b Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-12-30 09:59:32 +00:00
Dale Weiler
46374e94ca Add support for user defined messages for [[deprecated]] generalized attribute 2012-12-30 09:58:52 +00:00
Wolfgang Bumiller
048ef3e796 fix: ftepp_delete needs to ftepp_flush to not cause a leak on errors 2012-12-30 10:37:15 +01:00
Dale Weiler
921877e8a4 Implement [[deprecated]] general attribute, will mark functions as deprecated. Making calls to functions marked as such will trigger a compiler warning. Enabled by default. 2012-12-30 06:43:07 +00:00
Wolfgang Bumiller
755ee5462f Properly support globals initialized to nil 2012-12-29 21:15:59 +01:00
Wolfgang Bumiller
432a29e4d9 improvie/fix \{x...} char parsing 2012-12-29 19:11:06 +01:00
Wolfgang Bumiller
d961cfb855 gmqcc.ini.example: DIFFERENT_QUALIFIERS, DIFFERENT_ATTRIBUTES 2012-12-29 17:41:20 +01:00
Wolfgang Bumiller
64ccc88a9e manpage: -Wdifferent-qualifiers -Wdifferent-attributes 2012-12-29 17:41:20 +01:00
Wolfgang Bumiller
8bdd060112 -Wdifferent-qualifiers, -Wdifferent-attributes 2012-12-29 17:41:20 +01:00
Dale Weiler
d700bb66b2 Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-12-29 14:42:17 +00:00
Dale Weiler
842b0a1271 Fix uninitialized-global 2012-12-29 14:41:47 +00:00
Wolfgang Bumiller
33be9d4559 Don't allow code like: v * '0 1 0' = 3; to actually work... 2012-12-29 15:13:54 +01:00
Wolfgang Bumiller
fda4f4d027 gmqcc.ini.example: VECTOR_COMPONENTS 2012-12-29 15:13:28 +01:00
Wolfgang Bumiller
3d67b29a7b manpage: -Ovector-components 2012-12-29 15:10:04 +01:00
Wolfgang Bumiller
73bc4cc3e4 -Ovector-components 2012-12-29 15:05:04 +01:00
Dale Weiler
c0eca32b92 Merge pull request #80 from matthiaskrgr/master
add .gitignore file
2012-12-28 19:10:06 -08:00
matthiaskrgr
3567abbd64 Merge remote-tracking branch 'upstream/master' 2012-12-28 23:33:43 +01:00
matthiaskrgr
82f37c87fc add .gitignore file 2012-12-28 23:32:33 +01:00
Wolfgang Bumiller
ded1ab3da1 Typo... 2012-12-28 21:05:04 +01:00
Wolfgang Bumiller
2ac2827256 Updating gmqcc.ini.example 2012-12-28 21:04:14 +01:00
Wolfgang Bumiller
e37adb8c47 GMQCC_GITINFO 2012-12-28 20:39:30 +01:00
Wolfgang Bumiller
14e954284e more general qualifier/attribute parsing, added not-yet-used AST_FLAG_INLINE and [[inline]] 2012-12-28 19:46:28 +01:00
Wolfgang Bumiller
898e00f5b4 manpage: -Wuninitialized-constant -Wuninitialized-global 2012-12-28 19:11:29 +01:00
Wolfgang Bumiller
9315577be6 noref testcase must use -Wno-uninitialized-global 2012-12-28 19:09:06 +01:00
Wolfgang Bumiller
47baca22d9 -Wuninitialized-const, -Wuninitialized-global 2012-12-28 19:07:43 +01:00
Wolfgang Bumiller
dae1291b37 manpage: -Wreserved-names, -funtyped-nil, -fpermissive 2012-12-28 18:27:34 +01:00
Wolfgang Bumiller
77d454725a -Wreserved-names, -fpermissive allows local variables named 'nil' to be created even with -funtyped-nil, they supersede the global untyped 'nil' 2012-12-28 18:22:09 +01:00
Wolfgang Bumiller
2e0216b7c6 'nil' global with -funtyped-nil 2012-12-28 18:16:19 +01:00
Wolfgang Bumiller
40b2a26e89 TYPE_NIL, builder->nil, ast_value_codegen for TYPE_NIL 2012-12-28 18:05:28 +01:00
Dale Weiler
3f88b5fa14 Fix teh paren! 2012-12-28 15:19:19 +00:00
Dale Weiler
8f34e9fa37 added util_vasprintf/util_asprintf .. so we can stop assuming a certian static array size for formatting strings ... I expect to see full migration to this before the next release for protection of over/under flows. As well as identifers >= 1024 bytes :) 2012-12-28 15:02:53 +00:00
Dale Weiler
2ddb49f546 memleak 2012-12-28 14:47:27 +00:00
Dale Weiler
d6e7d8ca75 s/\t/ /g - utf8.c 2012-12-28 12:57:41 +00:00
Dale Weiler
cb12460b95 Fix another Blub bug .. learn to use comments properly :P 2012-12-28 12:54:20 +00:00
Dale Weiler
3688dab048 Fix a very possible bug 2012-12-28 12:50:37 +00:00
Dale Weiler
a6f51264fd Fixed another possible implementation specific bug thanks to this progressive splint idea :) 2012-12-28 12:43:08 +00:00
Dale Weiler
e2f9aa5027 Fix another warning 2012-12-28 12:40:00 +00:00
Dale Weiler
e4b8df2dc6 Fix another warning 2012-12-28 12:36:15 +00:00
Dale Weiler
6935561b41 Fix one warning 2012-12-28 12:33:10 +00:00
Dale Weiler
f58b4a6cd9 Added splint.sh (a progressive way to fix some possible bugs) 2012-12-28 12:29:46 +00:00
Wolfgang Bumiller
f1fa8f6055 So why doesn't any popular compiler complain about this 2012-12-28 11:50:03 +01:00
Wolfgang Bumiller
126b0fe324 ... This... I'll have to git rewrite-history at some point 2012-12-28 11:43:17 +01:00
Dale Weiler
566dda6ad7 Working on getting gmqcc to work when compiled with tcc 2012-12-28 09:30:01 +00:00
Dale Weiler
a7724bffaa Reorder operands 2012-12-28 09:06:04 +00:00
Dale Weiler
dbb7a87fd8 Quoting of strings is forbid in some "make" implementations 2012-12-28 09:05:14 +00:00
Dale Weiler
cfa7119fdb Got it working on arm :) 2012-12-28 08:59:41 +00:00
Dale Weiler
ba25970f27 Always use -fsigned-char .. The compiler I was using had -funsigned-char by default on ARM (which was breaking everything ...) try it .. add -funsigned-char and run the test-suite (only 2 out of all the tests actually pass, and it's by fluke) 2012-12-28 08:52:13 +00:00
Wolfgang Bumiller
fb30f11bc1 manpage: -floop-labels 2012-12-28 00:21:59 +01:00
Wolfgang Bumiller
03c079cb8c Some default options for -std=gmqcc including -floop-labels 2012-12-28 00:21:53 +01:00
Wolfgang Bumiller
a60d0182db finish parsing of labeled loops; ast support added 2012-12-28 00:04:09 +01:00
Wolfgang Bumiller
c702970a0e distinguish between break/continue levels in the parser 2012-12-27 23:52:57 +01:00
Wolfgang Bumiller
ebb7cb2ae3 parsing of loop labels 2012-12-27 23:43:20 +01:00
Wolfgang Bumiller
c6e7e80f23 there's no -f flag named overlap-locals... removed the opts.def entry 2012-12-27 22:18:58 +01:00
Wolfgang Bumiller
4187332bb1 Merge pull request #77 from matthiaskrgr/PKGBUILD
PKGBUILDs: note myself as contributor.
2012-12-27 11:10:10 -08:00
matthiaskrgr
b1e0687373 PKGBUILDs: note myself as contributor. 2012-12-27 20:07:58 +01:00
Wolfgang Bumiller
8624af879a bumping arch/release PKGBUILD to 0.2.2 2012-12-27 14:48:52 +01:00
Wolfgang Bumiller
517b6fed81 Another bool->int fix; now clang-compiled gmqcc actually works... 2012-12-27 14:33:58 +01:00
Wolfgang Bumiller
24752b5fd1 manpage: -fbail-on-werror 2012-12-27 12:48:36 +01:00
Wolfgang Bumiller
5cfd97c344 -fbail-on-werror option 2012-12-27 12:46:36 +01:00
Wolfgang Bumiller
24f3098418 fix: when there are no additional temps the first one allocated slot's size was counted twice resulting in some additional unused globals 2012-12-27 11:46:08 +01:00
Wolfgang Bumiller
babdebee79 Merge pull request #75 from matthiaskrgr/master
mention PKGBUILDs in INSTALL file, fix typo in manpage
2012-12-27 02:06:04 -08:00
Wolfgang Bumiller
3f8f2b3f48 manpage: -Oglobal-temps 2012-12-26 23:20:49 +01:00
Wolfgang Bumiller
d4483bfda6 -Oglobal-temps 2012-12-26 23:18:45 +01:00
Wolfgang Bumiller
93dbfa18f1 fix -v option parsing in qcvm 2012-12-26 22:49:50 +01:00
Wolfgang Bumiller
1cca992a8e factoring out temp-slot-assignment and using it for the declared locals too, makes -Olocal-temps more effective 2012-12-26 22:09:54 +01:00
matthiaskrgr
3d9760473b manpage: gmqcc: fix typo 2012-12-26 22:03:08 +01:00
matthiaskrgr
00fc3a5686 INSTALL: mention ArchLinux PKGBUILDs. 2012-12-26 21:57:26 +01:00
Wolfgang Bumiller
b42328dbc6 Switch over to LONGBIT 2012-12-26 21:39:00 +01:00
Wolfgang Bumiller
24161543d9 Merge pull request #74 from matthiaskrgr/PKGBUILD
add arch PKGBUILDs for git and release build.
2012-12-26 12:31:25 -08:00
matthiaskrgr
1f867e3920 PKGBUILD: formatting 2012-12-26 20:21:41 +01:00
matthiaskrgr
1ac110d426 add PKGBUILD for release build. 2012-12-26 20:17:29 +01:00
matthiaskrgr
56568d24ff PKGBUILD: license is MIT 2012-12-26 20:13:07 +01:00
Wolfgang Bumiller
de3d8747f7 fix uninitialized warnings in ir.c 2012-12-26 20:07:57 +01:00
matthiaskrgr
9bf6b2e1bd PKGBUILD: install custom license file. 2012-12-26 20:07:51 +01:00
matthiaskrgr
c3a867f0c2 PKGBUILD: license is not GPL actually 2012-12-26 20:03:17 +01:00
Wolfgang Bumiller
f832b86dcd Fixing uninitialized warnings in parser.c 2012-12-26 20:00:17 +01:00
Wolfgang Bumiller
33c7707f56 adding -fno-strict-aliasing 2012-12-26 19:58:53 +01:00
matthiaskrgr
728a8e975a add PKGBUILD for git build. 2012-12-26 19:58:40 +01:00
Wolfgang Bumiller
365fe400b0 manpage: -dump, -dumpfin 2012-12-26 19:37:55 +01:00
Wolfgang Bumiller
b32bd22af3 Merge pull request #73 from matthiaskrgr/master
fix some typos in todo file
2012-12-26 10:21:31 -08:00
matthiaskrgr
a2504f6455 TODO: fix typos 2012-12-26 19:15:40 +01:00
Wolfgang Bumiller
700628b2cb counters for -Ocall-stores because we all love numbers 2012-12-26 19:11:26 +01:00
Wolfgang Bumiller
14889897da Don't copy return values away from OFS_RETURN if they don't get locked. 2012-12-26 18:33:16 +01:00
Wolfgang Bumiller
456e80a7d5 manpage: -Ovoid-return 2012-12-26 10:28:01 +01:00
Wolfgang Bumiller
5779fea9b4 manpage: added -v to the qcvm manpage 2012-12-26 10:26:04 +01:00
Wolfgang Bumiller
af5b552a7f -Ovoid-return - the last INSTR_RETURN of a void functions is replaced by INSTR_DONE to reduce the instruction count 2012-12-26 10:24:33 +01:00
Wolfgang Bumiller
47f7611ec9 verbose switches for the qcvm; makes -printfuns find the instruction-count of a function and print that too 2012-12-26 10:23:45 +01:00
Wolfgang Bumiller
aee7bf0de0 Actually generate the vector member ir_values in ir_function_finalize, since ir_builder_gen_global is too late / happens after life ranges; this should fix -Ooverlap-locals 2012-12-25 23:51:29 +01:00
Wolfgang Bumiller
1172e2b8cc manpage: -Ocall-stores 2012-12-25 23:28:09 +01:00
Wolfgang Bumiller
a7c3ef3e22 -Ocall-stores as part of -O1: instead of having CALL instructions issue STOREs for every parameter, use the newly introduced 'lock' flag to make the operations generating the call's parameters generate them right into the OFS_PARM if there's no interfering CALL in between 2012-12-25 23:25:59 +01:00
Wolfgang Bumiller
d7de5cb5ff do the locking before processing the call-reads otherwise all the call's parameters get locked as well 2012-12-25 23:24:31 +01:00
Wolfgang Bumiller
710f580e15 liferange calc now sets the 'locked' flag on values when reaching a CALL 2012-12-25 21:03:26 +01:00
Wolfgang Bumiller
35ba2dcaf9 The very aggressive -Ooverlap-strings 2012-12-25 20:38:05 +01:00
Wolfgang Bumiller
307746dc35 Ensure that the members[] array is filled for vector types so the liferange function can use all of them 2012-12-24 12:52:15 +01:00
Wolfgang Bumiller
fcdff3180a Tests for the previous vector-liferange change 2012-12-24 12:43:16 +01:00
Wolfgang Bumiller
dc691c8a6e Now this should deal with vector life ranges more correctly. 2012-12-24 12:43:05 +01:00
Wolfgang Bumiller
da927b5d41 print an error when static is used in global scope - this is currently not being handled as expected 2012-12-24 11:38:33 +01:00
Wolfgang Bumiller
2b468cb0ee Added the 'static' keyword.
Implements #71
2012-12-24 11:30:58 +01:00
Wolfgang Bumiller
c3dfe2c61c manpage: -q, --quiet 2012-12-24 11:03:34 +01:00
Wolfgang Bumiller
55dc45ec3e manpage: -fftepp-predefs 2012-12-24 11:01:24 +01:00
Wolfgang Bumiller
2d66431af4 -q, --quiet option 2012-12-24 10:53:51 +01:00
Dale Weiler
f811a4e876 one too many zeros 2012-12-24 08:19:57 +00:00
Dale Weiler
fa155f8a42 Added my awesome MT1997 PRNG, and use it instead of stdio's rand()/srand() .. which are implementation specific .. and simply unsafe (for example one of the compilers at work simply has it's standard library implementation of rand() return 0 always (which is perfectly conformant)). 2012-12-24 01:43:27 +00:00
Dale Weiler
0a57c408c0 Added ftepp predefs flag (ability to turn on/off predefs) disabled by default (even with -ftepp), enabled with -E, to enable use -fftepp-predefs. 2012-12-24 00:21:55 +00:00
Dale Weiler
bd12429cd0 Implemented __FILE__, __LINE__, __RANDOM__, __RANDOM_LAST__, __COUNTER__ and __COUNTER_LAST__ as predefined macros. __FUNCTION__ is not implemented yet due to the overall complexity in making it constant. 2012-12-24 00:12:24 +00:00
Wolfgang Bumiller
6a93b72ea5 -Ostrip-constant-names 2012-12-23 22:58:46 +01:00
Wolfgang Bumiller
d3568627e9 code_genstring now caches strings, no need for code_cachestring 2012-12-23 21:42:00 +01:00
Wolfgang Bumiller
6a60368a1b -Olocaltemps -> -Olocal-temps for consistency; added manpage entry; removed leftover manpage entry for -foverlap-locals; -Olocal-temps moved from -O1 to -O3 due to stability concerns 2012-12-23 21:39:23 +01:00
Wolfgang Bumiller
1ac913877e revert 3ef30e850d 2012-12-23 21:34:04 +01:00
Wolfgang Bumiller
63928e231c Remove ir_block_create_{add,sub,mul,div}, they're not used; STOREP instructions don't themselves to their target pointer's 'writes' list, but 'reads' list instead 2012-12-23 21:29:15 +01:00
Wolfgang Bumiller
435dee935b Start instruction numbering at 1 and make parameters live at 0 2012-12-23 21:20:16 +01:00
Wolfgang Bumiller
3ef30e850d Don't store off CALL results if they're never read 2012-12-23 21:11:56 +01:00
Wolfgang Bumiller
cff74493a7 Even safer vector macros 2012-12-23 20:55:15 +01:00
Wolfgang Bumiller
fb5a65c51a Life Ranges: First deal with all writes, then with all reads, since writes will remove values from the Living set 2012-12-23 20:50:21 +01:00
Wolfgang Bumiller
46c2fe2443 Fixing vector macros 2012-12-23 20:49:50 +01:00
Wolfgang Bumiller
890ca3c782 added -disasm-func to the qcvm 2012-12-23 20:45:43 +01:00
Wolfgang Bumiller
ee7051c5a4 strcmp and strncmp builtins 2012-12-23 19:22:38 +01:00
Wolfgang Bumiller
275b6f777a Adding strcat builtin to qcvm 2012-12-23 19:06:29 +01:00
Wolfgang Bumiller
3c9283cc41 don't optimize out NOT_S instructions for COND 2012-12-23 17:51:01 +01:00
Wolfgang Bumiller
2967dba7ad manpage: remove the MUL_FV/VF section, it wouldn't be legal code anyway 2012-12-23 17:50:44 +01:00
Wolfgang Bumiller
4f06daf7d0 manpage: optimization section 2012-12-23 17:46:40 +01:00
Wolfgang Bumiller
c91b457054 Mask overlap-locals by -Ooverlap-locals, and count (the amount of overlapped functions) 2012-12-23 17:40:56 +01:00
Wolfgang Bumiller
b8c61f2f88 Try generating the function-locals in a later pass; with the option to overlap them. 2012-12-23 17:32:39 +01:00
Wolfgang Bumiller
67bc99223d Fix a nasty bug in the executor; and make null-strings be shown as (null) in the trace output 2012-12-23 17:32:14 +01:00
Wolfgang Bumiller
eabe23cc24 Add -Ooverlap-locals to -O3 2012-12-23 16:31:21 +01:00
Wolfgang Bumiller
88a6437840 remember the maximum amount of required function-locals 2012-12-23 16:31:01 +01:00
Wolfgang Bumiller
7998a98818 ir_function now has a flags field - flags are: IR_FLAG_HAS_{ARRAYS,UNINITIALIZED,GOTO} 2012-12-23 16:21:38 +01:00
Wolfgang Bumiller
2382fdee50 util_swa_* + GMQCC_INLINE 2012-12-23 13:11:20 +01:00
Wolfgang Bumiller
1731a29c51 Don't generate defs for locals or parameters unless using -g 2012-12-23 12:22:27 +01:00
Wolfgang Bumiller
84fcd95d4e utf8lib.c -> utf8.c - I hope windows 8 allows this filename :P 2012-12-23 10:44:03 +01:00
Wolfgang Bumiller
95965e9ff6 license header 2012-12-23 10:35:21 +01:00
Wolfgang Bumiller
e72d141ec4 Uchar -> uchar_t for consistency 2012-12-23 10:34:29 +01:00
Wolfgang Bumiller
3e6c98d65d manpage: -futf8 2012-12-23 10:23:42 +01:00
Wolfgang Bumiller
041f8a86d7 utf8 tests 2012-12-23 10:23:42 +01:00
Wolfgang Bumiller
2164afb8cf Better error message for -futf8 2012-12-23 10:23:42 +01:00
Wolfgang Bumiller
ac0ca3de81 fix and speed up u8_analyze for our purposes 2012-12-23 10:23:42 +01:00
Wolfgang Bumiller
a707440e52 -futf8 implementation 2012-12-23 10:23:42 +01:00
Wolfgang Bumiller
aec2284f45 u8_analyze: return false on any invalid character, we do not allow invalid/overlong characters in code at all 2012-12-23 10:23:41 +01:00
Wolfgang Bumiller
fe3d8e44e6 Importing utf8lib 2012-12-23 10:23:41 +01:00
Dale Weiler
da49a40b96 Bump 0.2 -> 0.3 2012-12-23 09:18:17 +00:00
Wolfgang Bumiller
55117912ab Don't generate vector defs if the vector's name starts with a # because that's an 'IMMEDIATE' 2012-12-23 10:14:25 +01:00
Dale Weiler
d51a6ab3db Whitespace 2012-12-23 09:10:31 +00:00
Dale Weiler
5bc815c63f Revert "Whitespace fixes"
This reverts commit 4580dcf1ea.
2012-12-23 09:10:07 +00:00
Dale Weiler
4580dcf1ea Whitespace fixes 2012-12-23 08:42:53 +00:00
Dale Weiler
e0ea101838 Lies ... damned lies, all lies I tell you ... copy-pasta lies! 2012-12-23 08:17:05 +00:00
Dale Weiler
f598fbeaea Actually fix the segfault this time 2012-12-23 08:08:05 +00:00
Dale Weiler
3b27107676 con_default_out for opts.pp_only (removes recently added TODO .. and fixes a segfault) 2012-12-23 07:57:06 +00:00
Dale Weiler
c3964cf29d Make compiler and virtual-machine compile as C++ code, also removed gmqcc_voidptr hack. 2012-12-23 07:51:19 +00:00
Dale Weiler
d35d953a91 Remove parser_compile_string_len, and make parser_compiler_string take an additional length argument. 2012-12-23 07:22:15 +00:00
Dale Weiler
6951f3dfcc fix comments 2012-12-23 07:19:49 +00:00
Dale Weiler
4224ac5ca0 fixes, and removed a #pragma warning(disable ...) in MSVC .. thanks to the FILE wrapping interface. 2012-12-23 07:18:00 +00:00
Dale Weiler
d18656c2dc Cleanup flexible array / vector system 2012-12-23 07:14:16 +00:00
Dale Weiler
6bc29a1601 Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-12-23 06:06:57 +00:00
Dale Weiler
13003bf6af Wrapper around FILE to take advantage of MSVC "secure" CRT. We don't actually defend bounds checks (we just hack in the few ones to silent MSVC .. and to pass WinRT "native code" rules) 2012-12-23 06:05:22 +00:00
Wolfgang Bumiller
9d54ea6b0c More stuff for qcvm -info 2012-12-22 23:30:52 +01:00
Wolfgang Bumiller
aef7ff87fc Makefile: lexer.o depends on lexer.h 2012-12-22 20:43:59 +01:00
Wolfgang Bumiller
77639bb21d guard ]] with lex->flags.noops 2012-12-22 20:41:02 +01:00
Wolfgang Bumiller
eb952f1199 fix -fshort-logic to cast to true boolean values 2012-12-22 20:05:15 +01:00
Wolfgang Bumiller
96ddc217da manpage: capital section headings, updated -fcorrect-logic description, added -Wunknown-attribute 2012-12-22 18:19:51 +01:00
Wolfgang Bumiller
e8cd9411b0 -Wunknown-attribute; and don't error on unknown attributes 2012-12-22 18:16:41 +01:00
Wolfgang Bumiller
7cf0ba5aa8 'noreturn' is now an attribute and parsed as [[noreturn]] 2012-12-22 18:09:56 +01:00
Wolfgang Bumiller
b38b3b08bd properly fill the token string for TOKEN_ATTRIBUTE_* 2012-12-22 18:09:17 +01:00
Wolfgang Bumiller
2c2bfab8bc is now no keyword anymore 2012-12-22 18:03:43 +01:00
Wolfgang Bumiller
26a80e0868 Lexer: [[ and ]] are now TOKEN_ATTRIBUTE_{OPEN,CLOSE} 2012-12-22 18:00:51 +01:00
Wolfgang Bumiller
949cd9bb06 Test cases for -fcorrect-logic 2012-12-22 17:55:55 +01:00
Wolfgang Bumiller
d858237010 Adding truth-flags testsuite for strings 2012-12-22 17:36:06 +01:00
Wolfgang Bumiller
1f070b740f -ffalse-empty-strings in && and || 2012-12-22 17:31:31 +01:00
Wolfgang Bumiller
0fe71af4ce -fcorrect-logic now handles only vectors 2012-12-22 17:18:37 +01:00
Wolfgang Bumiller
7efc3a4c21 Error when using both -ffalse-empty-strings and -ftrue-empty-strings 2012-12-22 16:50:09 +01:00
Wolfgang Bumiller
8459895fdd Fix a bug with -fperl-logic and -fcorrect-logic 2012-12-22 16:25:19 +01:00
Wolfgang Bumiller
b4e38a8fed Fix: ast_value.cvq must be an int, not a bool;
Fixes #62
2012-12-22 12:30:20 +01:00
Dale Weiler
fa401b6f56 Cleanups and make compile with clang again with no warnings. 2012-12-22 08:22:50 +00:00
Dale Weiler
7d2a2f2ade cleanups and fixes that cppcheck found 2012-12-22 08:07:54 +00:00
Dale Weiler
322fbaf389 More cleanups 2012-12-22 07:54:14 +00:00
Dale Weiler
9ba655e74c Remove more unused code 2012-12-22 07:46:43 +00:00
Dale Weiler
313e442107 Make gmqcc binary smaller (by removing some useless code) 2012-12-22 07:40:17 +00:00
Dale Weiler
ed11fe130b Stick to one hash function (no platform optimized versions) 2012-12-22 07:33:11 +00:00
Dale Weiler
7753e19ba8 Cleanups 2012-12-22 07:24:25 +00:00
Dale Weiler
88fee02228 Windows stuff for visual studio now offical works with exception to colorized output to cmd (which actually should work). As well as the testsuite which lacks implementations of task_popen/task_pclose. 2012-12-21 06:16:08 -05:00
Wolfgang Bumiller
43cf6e7cba -Opeephole now also reduces CALL stores 2012-12-21 11:42:23 +01:00
Wolfgang Bumiller
48ba6a6189 Rename ir_function_pass_tailcall->tailrecursion; Take -fadjust-vector-fields into account when storing field type return-values from functions 2012-12-21 11:33:44 +01:00
Wolfgang Bumiller
06ea71d5be manpage: -Wcpp; added a FILES section which contains gmqcc.ini.example - we should install this to some DATADIR in the install make target 2012-12-21 11:02:36 +01:00
Dale Weiler
c9e3c29a25 testsuite compiles on windows now (but doesn't work). Still need to implement bidirectional piping on stdout/stderr/stdin.. Which for some reason is incredibly stupidly complicated on windows. You need to setup SECURITY_ATTRIBUTES for each handle, do crazy handle duplication, and forking via CreateThread. Meanwhile the whole "concept" of threading is entierly broken in fundamental design on windows, which means you constantly need to store the current process handles for backup, and "inherit" from child process. It's just stupid, provide unix pipes via close/open and dup. Like normal people (they're simple and sane). 2012-12-21 01:59:34 -05:00
Dale Weiler
3c003bc168 Get gmqcc/qcvm compiling on windows again. Plus work in progress support for the testsuite on windows (does not compile yet). 2012-12-21 01:00:51 -05:00
Dale Weiler
0be55824d4 Implemented preprocessing error directive tests (should fail) 2012-12-21 04:48:01 +00:00
Dale Weiler
0e40ef172a Document ini.example 2012-12-21 04:01:47 +00:00
Dale Weiler
bf53f82d16 Update ini.example (added UNREACHABLE_CODE, and CPP) as warning options 2012-12-21 03:14:31 +00:00
Dale Weiler
f78ab9061b added -Wcpp (for turning off cpp warnings defined with #warning like GCC/clang/pathscale .. no more [-Wunused-variable]) 2012-12-21 03:12:58 +00:00
Dale Weiler
36a90bb866 Implemented #warning and #error preprocessor directives, they're functionally equivalent to CPPs (supporting both string constant and non-string constant versions). Warnings however are printed with a [-Wunused-variable] which isn't correct (TODO: allow systematic changes of -W paramaters in relation to warning fields for preprocessor directives. 2012-12-21 03:08:21 +00:00
Dale Weiler
c7a62970a6 Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-12-20 23:07:33 +00:00
Dale Weiler
e1f0e40341 Implemented roboust compile-time endianess check. 2012-12-20 23:07:06 +00:00
Wolfgang Bumiller
0bbc8a3350 Remove old tempalloc code; disable -Olocaltemps for now 2012-12-20 23:52:54 +01:00
Wolfgang Bumiller
e38bdecd21 Be more correct with sizes; use a better local-alloc strategy 2012-12-20 23:48:41 +01:00
Wolfgang Bumiller
5375400e85 minor: fix ast_function_label 2012-12-20 23:27:23 +01:00
Wolfgang Bumiller
1d3fdea432 Fix util_endianswap; and endianswap the LNO data as well 2012-12-20 22:03:51 +01:00
Wolfgang Bumiller
8d86d7d1c1 Don't check for is_return but for final at the end of a function so that if 'goto' is the last expression we don't try to append a return 2012-12-20 21:05:29 +01:00
Wolfgang Bumiller
93341dd009 *sigh* 2012-12-20 20:57:05 +01:00
Wolfgang Bumiller
a6547a15f3 no need to check the array, the 2nd NOT is a NOT_F 2012-12-20 20:56:49 +01:00
Wolfgang Bumiller
8dc6696957 manpage: -fcorrect-logic, -ftrue-empty-strings, -ffalse-empty-strings 2012-12-20 20:56:08 +01:00
Wolfgang Bumiller
ccbccad994 fix -fcorrect-logic to use double-not instead of a single one - wow that was a bad one 2012-12-20 20:55:56 +01:00
Wolfgang Bumiller
712be84bba Testcases for -ftrue-empty-strings and -ffalse-empty-strings 2012-12-20 20:43:58 +01:00
Wolfgang Bumiller
68c4070f62 Fix the -fcorrect-logic condition 2012-12-20 20:40:59 +01:00
Wolfgang Bumiller
0988b731b7 Fix -fcorrect-logic 2012-12-20 20:33:05 +01:00
Wolfgang Bumiller
b595ec03f8 fix a leak in the local-allocator 2012-12-20 20:26:54 +01:00
Wolfgang Bumiller
98b6772db9 Fix a leak: free code_linenums 2012-12-20 20:26:14 +01:00
Wolfgang Bumiller
4f9c7861ec For loops may have an empty condition - don't try processing a NULL 2012-12-20 20:23:35 +01:00
Wolfgang Bumiller
a985a5cab1 while/for/do now all use process_condition, ast_loop got 2 new parameters for more efficient translation 2012-12-20 20:22:31 +01:00
Wolfgang Bumiller
d72cb42b08 process_condition function used by parse_if - need to still add it to loops 2012-12-20 19:51:30 +01:00
Wolfgang Bumiller
db577fdf17 -ftrue-empty-strings now changes type_not_instr[TYPE_STRING] to INSTR_NOT_F 2012-12-20 19:32:57 +01:00
Wolfgang Bumiller
34063108a6 since unary not doesn't fold these, remove them from immediate_is_true 2012-12-20 19:19:12 +01:00
Wolfgang Bumiller
4319922b3c introducing an immediate_is_true which follows the new -f flags on strings and vector truthfulness, used in logic-op constant folding; const folding now disabled for functions-constants on NOT because it's stupid 2012-12-20 19:18:22 +01:00
Wolfgang Bumiller
6b9eff19f1 unary not now uses NOT_F with -ftrue-empty-strings 2012-12-20 19:04:56 +01:00
Wolfgang Bumiller
b85441d6af Making logical 'and' and 'or' use NOT_ in -fcorrect-logic for both operands normally, but only for the first with -fperl-logic 2012-12-20 19:00:23 +01:00
Wolfgang Bumiller
d5cfe74d5d Adding -fcorrect-logic, -ftrue-empty-strings, -ffalse-empty-strings flags; not used yet 2012-12-20 18:59:05 +01:00
Wolfgang Bumiller
8f858a8f3e manpage: typo 2012-12-20 16:56:22 +01:00
Wolfgang Bumiller
5b98011f5f Fix condition on whether or not to print 'error' or 'warning' 2012-12-20 16:55:00 +01:00
Wolfgang Bumiller
6cd821d459 -Werror-<warning> should actually use opts_setwerror 2012-12-20 16:53:09 +01:00
Wolfgang Bumiller
b360245b45 -Werror-<warning>, -Wno-error-<warning>, manpage updated 2012-12-20 16:49:10 +01:00
Wolfgang Bumiller
78b1105c10 manpage: -Wunreachable-code 2012-12-20 16:41:40 +01:00
Wolfgang Bumiller
fffa78c7a6 Reorder the warnings in opts.c to match their oder in opts.def, added WARN_LOCAL_SHADOWS to the list with its default false parameter 2012-12-20 16:32:36 +01:00
Wolfgang Bumiller
eb8dc60981 Turn -fallow-unreachable-code into a -Wunreachable-code 2012-12-20 16:29:32 +01:00
Wolfgang Bumiller
145c011247 Fix object dependency: OBJ -> OBJ_D so they all depend on gmqcc.h again properly 2012-12-20 16:28:35 +01:00
Wolfgang Bumiller
915c002be4 Temporarily fix noreturn bug by creating an actual dummy return instruction after the call for now 2012-12-20 16:20:08 +01:00
Wolfgang Bumiller
4ef0e8c66e -g sets opts.g and -debug causes blocks to be labeled 2012-12-20 16:04:10 +01:00
Wolfgang Bumiller
b02c4e4d10 sscanf_s only for _MSC_VER not WIN32 in exec.c 2012-12-20 15:46:31 +01:00
Wolfgang Bumiller
5d51930adf Oh god I hate this so much 2012-12-20 15:45:15 +01:00
Wolfgang Bumiller
bb356bffa5 that should have gone into the second to last commit 2012-12-20 15:27:15 +01:00
Wolfgang Bumiller
0f0a458cc4 WINDOWS 8 USERS ARE IDIOTS, YES YOU SHOULD TAKE THIS PERSONALLY 2012-12-20 15:26:45 +01:00
Wolfgang Bumiller
d76e6b103d ast_return needs the correct context... 2012-12-20 15:01:19 +01:00
Wolfgang Bumiller
3119a95a89 -fallow-unreachable-code 2012-12-20 14:41:16 +01:00
Wolfgang Bumiller
79f3f980e9 vector initialization tests 2012-12-20 14:12:22 +01:00
Wolfgang Bumiller
a274f8ec07 making the uninitialized-var on vector warning now check all members; ir_value_vector_member now also appends _x,_y,_z since they're used in the used-unintialized message 2012-12-20 14:06:25 +01:00
Wolfgang Bumiller
8adbb2f5ac Remove the suffix entirely 2012-12-20 13:44:53 +01:00
Wolfgang Bumiller
7833efd6e1 UL->ULL 2012-12-20 12:55:21 +01:00
Wolfgang Bumiller
a301796186 Added tests for 'noreturn' 2012-12-20 12:00:39 +01:00
Dale Weiler
f1a662a422 ugh todo: seed per ht, not per hash 2012-12-20 10:21:31 +00:00
Dale Weiler
2e57a952a7 No more hacks 2012-12-20 10:20:16 +00:00
Dale Weiler
42fc620466 fixes 2012-12-20 09:44:47 +00:00
Dale Weiler
475b3152ca One last fix for mankind 2012-12-20 09:01:01 +00:00
Dale Weiler
148f7babcd *sigh* 2012-12-20 08:51:29 +00:00
Dale Weiler
199540e6ca Allow uname override 2012-12-20 08:49:14 +00:00
Dale Weiler
8fda2233cb Fix murmur hash seeding 2012-12-20 08:46:39 +00:00
Dale Weiler
3e8435783c More fixes 2012-12-20 08:45:54 +00:00
Dale Weiler
9f742271b1 Another fix 2012-12-20 08:19:43 +00:00
Dale Weiler
d7585a810a FTBFS fixes 2012-12-20 08:17:04 +00:00
Dale Weiler
0648835061 handle cygwin/mingw for makefile 2012-12-20 00:22:22 +00:00
Dale Weiler
2bf2991ecb Typos 2012-12-19 21:37:37 +00:00
Dale Weiler
757617f89f Implemened -fail procedure type for testsuite. Essentially performs compilation on the idea that the compilation should fail, for the test to succeed, otherwise the test actually fails. 2012-12-19 21:35:47 +00:00
Wolfgang (Blub) Bumiller
afaa162aa1 Applying the actual 'Fix FTFBS stuff' part 2012-12-19 22:17:22 +01:00
Wolfgang (Blub) Bumiller
57aaf57dfc Revert "Fix FTFBS stuff"
This reverts commit 2cc51b8eb0.
2012-12-19 22:15:38 +01:00
Dale Weiler
2cc51b8eb0 Fix FTFBS stuff 2012-12-19 21:05:40 +00:00
Wolfgang (Blub) Bumiller
664b6d6604 'noreturn' is - for now - a keyword, and used just like noref/var/const, to mark a function as not-returning 2012-12-19 20:56:22 +01:00
Wolfgang (Blub) Bumiller
c8e163b0df ast_call now passes AST_FLAG_NORETURN on to the IR 2012-12-19 20:47:01 +01:00
Wolfgang (Blub) Bumiller
ba434c8e22 removing ast_expression_common.variadic, adding ast_expression_common.flags, added AST_FLAG_VARIADIC and AST_FLAG_NORETURN 2012-12-19 20:45:48 +01:00
Wolfgang (Blub) Bumiller
7c5fc26081 NRCALL now sets block->final and block->is_return 2012-12-19 20:40:45 +01:00
Wolfgang (Blub) Bumiller
bf267d0238 ir_block_create_{phi,call} now check self->final 2012-12-19 20:39:44 +01:00
Wolfgang (Blub) Bumiller
384446316a VINSTR_NRCALL, translated like any other call for now; to be used to mark a call which never returns, ie the error builtin 2012-12-19 20:38:32 +01:00
Wolfgang Bumiller
2a2c208884 Merge pull request #48 from mhofstra/patch-1
Small typo fix to make it compile on x86
2012-12-18 13:01:43 -08:00
mhofstra
5fc1cc2414 Small typo fix to make it compile on x86 2012-12-18 21:57:16 +01:00
Rudolf Polzer
acf4da9385 Fixes for some minor bugs clang-analyzer and cppcheck found
Signed-off-by: Dale Weiler <killfieldengine@gmail.com>
2012-12-18 16:54:51 +00:00
Wolfgang (Blub) Bumiller
8cd94192d8 default make target now is 'all' 2012-12-18 16:58:21 +01:00
Wolfgang (Blub) Bumiller
dd6f415a04 Tests for perl-logic _types_ 2012-12-18 16:57:38 +01:00
Wolfgang (Blub) Bumiller
2a61a65ce0 -fperl-logic now doesn't allow logic ops with operands of different types, but therefore uses the correct output type 2012-12-18 16:56:22 +01:00
Wolfgang (Blub) Bumiller
9b9fbb6e3b Added intrinsic: __builtin_debug_typestring(expr) to get the type of an expression as string 2012-12-18 16:52:30 +01:00
Wolfgang (Blub) Bumiller
b337f630c8 Remove a TODO message 2012-12-18 16:36:06 +01:00
Wolfgang (Blub) Bumiller
259aaad324 make install-doc now also installs qcvm.q 2012-12-18 16:03:48 +01:00
Wolfgang (Blub) Bumiller
9cb46789f0 Adding qcvm.1 2012-12-18 16:03:29 +01:00
Wolfgang (Blub) Bumiller
e1c3e35422 Improved parameter handling of qcvm a little, added --version and --help 2012-12-18 15:46:26 +01:00
Wolfgang (Blub) Bumiller
6601e89029 fix wrong --version string 2012-12-18 15:44:26 +01:00
Wolfgang (Blub) Bumiller
70f676784d Better usage message for qcvm, don't exit after any of the information prints - but don't execute if any of them are used 2012-12-18 15:39:20 +01:00
Wolfgang (Blub) Bumiller
49c4da9670 BUGS, SEE ALSO and AUTHOR sections in the manpage 2012-12-18 15:30:59 +01:00
Wolfgang (Blub) Bumiller
201b3f9218 It's -config=file, not -config file 2012-12-18 15:27:12 +01:00
Wolfgang (Blub) Bumiller
52b4c9f0c1 Added -config to usage and manpage, added a CONFIG section in the manpage describing the ini file format, and added a short example to it 2012-12-18 15:26:41 +01:00
Wolfgang (Blub) Bumiller
82e0073433 Add included -fs and -Ws to for each -std in the manpage 2012-12-18 14:21:01 +01:00
Wolfgang (Blub) Bumiller
dccafd65ac More jump removal 2012-12-18 14:03:20 +01:00
Wolfgang (Blub) Bumiller
19deac0707 *sigh* 2012-12-18 13:13:54 +01:00
Wolfgang (Blub) Bumiller
66e6e6329f vector components are floats, not vectors 2012-12-18 12:58:15 +01:00
Wolfgang (Blub) Bumiller
d9cca87aff Don't generate IF/IFNOT with +1 offsets 2012-12-18 12:57:09 +01:00
Wolfgang (Blub) Bumiller
d09ab90f24 -fsingle-vector-defs to disable _x,_y,_z generation 2012-12-18 12:47:48 +01:00
Wolfgang (Blub) Bumiller
116d744823 Generate _x,_y,_z defs/fields 2012-12-18 12:41:38 +01:00
Wolfgang (Blub) Bumiller
2a94fe9731 qcvm -pringdefs now prints [SAVE] next to globals with DEF_SAVEFLAG set 2012-12-18 12:41:29 +01:00
Wolfgang (Blub) Bumiller
db5484bdef DEF_SAVEGLOBAL flag is now applied on initialized non-constant globals, and is not applied on 'consts' 2012-12-18 12:02:33 +01:00
Wolfgang (Blub) Bumiller
6b4c89700b Don't generate 'jump +1' instructions 2012-12-18 11:57:30 +01:00
Wolfgang (Blub) Bumiller
26f3370ea6 Renaming gmqcc.init since it's used by default if it exists and it makes the testsuite fail 2012-12-18 11:48:03 +01:00
Wolfgang (Blub) Bumiller
83a41d13c0 Don't generate AINSTR_END anymore, use INSTR_DONE 2012-12-18 11:46:26 +01:00
Wolfgang (Blub) Bumiller
a5e0542f95 cmd_options -> opts_cmd_t to make testsuite and executor compile again 2012-12-18 11:46:15 +01:00
Dale Weiler
2587aed697 Allow setting configuration file via commandline 2012-12-18 05:22:23 +00:00
Dale Weiler
ed4213d403 Add a template ini file for documentation 2012-12-18 05:12:57 +00:00
Dale Weiler
4b3e2571af Cleanups of compiler option configuration. Added ini/cfg parser system as well. 2012-12-18 04:57:17 +00:00
Wolfgang (Blub) Bumiller
0befe5da1c messages caused by -Warnings now show the -W flag 2012-12-17 18:36:27 +01:00
Wolfgang (Blub) Bumiller
b7117e08ce parsewarning and genwarning to use vcompile_warning 2012-12-17 18:26:26 +01:00
Wolfgang (Blub) Bumiller
2534076963 irwarning to use vcompile_warning 2012-12-17 18:25:06 +01:00
Wolfgang (Blub) Bumiller
0f99ae3459 ftepp_warn to use vcompile_warning 2012-12-17 18:24:16 +01:00
Wolfgang (Blub) Bumiller
fe344cb5b2 vcompile_error, vcompile_warning; fixed: removed opts_ globals from con.c; made the lexer use vcompile_warning 2012-12-17 18:22:33 +01:00
Wolfgang (Blub) Bumiller
6fa30fdaf4 Adding -Wunknown-pragmas to the manpage 2012-12-17 17:18:19 +01:00
Dale Weiler
8e0515de44 Added -Wunknown-pragmas 2012-12-17 16:14:43 +00:00
Wolfgang (Blub) Bumiller
68e4fb87d8 Fixed a bug in the generation of default switch cases: they can now fall through correctly 2012-12-17 17:01:07 +01:00
Dale Weiler
c1a4c8102e Finally fix the bug in -D 2012-12-17 15:46:07 +00:00
Wolfgang (Blub) Bumiller
f7bc1dca08 Revert "Not defining GMQCC_VERSION_ in gmqcc.h but checking if they're defiend and #error if not - they're set in the Makefile - please fix windows builds"
This reverts commit a473979cf5.

-- because visual studio sucks
2012-12-17 16:46:03 +01:00
Dale Weiler
e72d656eb8 Fixes, but still crashes because ... I have no clue, there is no reason for this to crash. 2012-12-17 15:39:22 +00:00
Wolfgang (Blub) Bumiller
a473979cf5 Not defining GMQCC_VERSION_ in gmqcc.h but checking if they're defiend and #error if not - they're set in the Makefile - please fix windows builds 2012-12-17 16:30:07 +01:00
Wolfgang (Blub) Bumiller
340de8379a --version 2012-12-17 16:14:39 +01:00
Dale Weiler
08302ff32b Just make it -v 2012-12-17 15:11:34 +00:00
Dale Weiler
ae960efff4 Added -which/-version 2012-12-17 15:08:17 +00:00
Wolfgang (Blub) Bumiller
ac18d58ffc Copy over the array-count in ast_type_adopt/ast_type_copy 2012-12-17 16:00:08 +01:00
Wolfgang (Blub) Bumiller
f0687adbaa Error when the assignop for an assignment is invalid, eg. when trying to assign arrays 2012-12-17 16:00:08 +01:00
Wolfgang (Blub) Bumiller
c2857a22e3 Let's still initialize the 'count' member... 2012-12-17 16:00:08 +01:00
Dale Weiler
c1c7a93884 Implemented -D for preprocessor 2012-12-17 14:58:55 +00:00
Wolfgang (Blub) Bumiller
eab1050ba4 Fix: check error before calling codegen_output_type 2012-12-17 15:43:14 +01:00
Dale Weiler
05ccb73e08 Update some info 2012-12-16 23:00:17 +00:00
Dale Weiler
58f90d9f51 Fix some typos 2012-12-16 22:52:17 +00:00
Dale Weiler
49e7f6d31d Add TODO 2012-12-16 22:48:46 +00:00
Dale Weiler
60807b677c Fix testsuite. Also added an additional test to the ternary stuff 2012-12-16 22:07:33 +00:00
Wolfgang (Blub) Bumiller
c198c23df1 Another peephole optimization 2012-12-06 22:10:31 +01:00
Wolfgang (Blub) Bumiller
8858f265dd s/ir_function_pass_minor/ir_function_pass_peephole/ 2012-12-06 21:39:34 +01:00
Wolfgang (Blub) Bumiller
362d822e18 Adding an 'install-doc' target to the Makefile, which is included by the 'install' target and uses MANDIR, which defaults to DATADIR/man, and DATADIR defaults to PREFIX/share 2012-12-06 18:57:56 +01:00
Wolfgang (Blub) Bumiller
583c58f65b Adding -f flags to the manpage 2012-12-06 18:51:46 +01:00
Wolfgang (Blub) Bumiller
abfda3271b Adding all the warnings to the manpage 2012-12-06 18:41:22 +01:00
Wolfgang (Blub) Bumiller
5e186bb434 Updating usage message a bit 2012-12-06 18:16:59 +01:00
Wolfgang (Blub) Bumiller
9c5b95bbe3 Temporarily disable the new tempalloc strat 2012-12-06 17:41:00 +01:00
Wolfgang (Blub) Bumiller
f9b1d057b5 Moving all the global opts_ variables into a struct, now there's one global 'opts' struct 2012-12-06 13:23:53 +01:00
Wolfgang (Blub) Bumiller
94560d1873 -Ominor -> -Opeephole; added -Olocaltemps flag; using a less space-wasting temp-allocation in general 2012-12-06 13:08:46 +01:00
Wolfgang (Blub) Bumiller
04a57d871e unexpected typename error when there are typenames in an expression 2012-12-05 17:14:44 +01:00
Wolfgang (Blub) Bumiller
2eea7b03c0 get rid of some code duplication, and fix some wrong type adoptions in the ast 2012-12-05 16:22:32 +01:00
Wolfgang (Blub) Bumiller
37fbe7176f Tiny codegen optimization: silently ignore the creation of STORE with input and output being the same address 2012-12-05 15:17:11 +01:00
Wolfgang (Blub) Bumiller
8acfd87039 remember this for later 2012-12-05 15:14:21 +01:00
Wolfgang (Blub) Bumiller
5f0f5bedbc More stuff in qcvm -printfuns 2012-12-05 14:22:24 +01:00
Wolfgang (Blub) Bumiller
fe150aee72 ir_function_pass_minor: some minor optimizations 2012-12-05 14:14:35 +01:00
Wolfgang (Blub) Bumiller
8777624fe2 ast_block_add_expr now lets the block fully adopt the type of the added expression 2012-12-05 12:57:00 +01:00
Wolfgang (Blub) Bumiller
f140251e85 s/parser_sy_pop/parser_sy_apply_operator/ 2012-12-04 21:04:14 +01:00
Wolfgang (Blub) Bumiller
0c8bacd134 ast_ternary_codegen: use codegen_outpu_type 2012-12-04 14:11:49 +01:00
Dale Weiler
0dfd3136e5 Fix testsuite for -compile cases 2012-12-04 11:56:20 +00:00
Wolfgang (Blub) Bumiller
8e077f378e -Werror now changes the word 'warning' into 'error' 2012-12-04 12:54:53 +01:00
Wolfgang (Blub) Bumiller
36fe4e2729 noref -compile testcase 2012-12-04 12:50:38 +01:00
Wolfgang (Blub) Bumiller
0e4e81d94f Parsing the 'noref' keyword; this also gets rid of some code duplication 2012-12-04 12:17:43 +01:00
Wolfgang (Blub) Bumiller
88a4721de7 Parsing noref-pragma 2012-12-03 20:37:02 +01:00
Wolfgang (Blub) Bumiller
ea08d16c06 ftepp_preprocess_string uses strlen - push nul-byte to verminor and vermajor 2012-12-03 20:23:40 +01:00
Dale Weiler
d43a6c50d4 Hide execution call to testsuite with @ in Makefile 2012-12-02 23:58:13 +00:00
Dale Weiler
16ae493a9a -g now turns on -flno 2012-12-02 23:52:38 +00:00
Dale Weiler
1ca3e72417 Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-12-02 23:17:07 +00:00
Dale Weiler
4d1514257e Added preprocessor test 2012-12-02 23:16:44 +00:00
Wolfgang (Blub) Bumiller
6b575372cc Don't warn about uninitialized stuff in accessors - remove the liferanges calculated when finalizing accessors, this would add invalid liferanges to function-local arrays and thus suppress warnings randomly 2012-12-02 18:09:59 +01:00
Wolfgang (Blub) Bumiller
c926c4cb59 Sanity check in ast_generate_accessors 2012-12-02 18:02:44 +01:00
Wolfgang (Blub) Bumiller
02ec45363e Get rid of some code duplication 2012-12-02 17:57:08 +01:00
Dale Weiler
77ef7f516d Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-12-02 12:03:40 +00:00
Wolfgang (Blub) Bumiller
668735e0f4 Copy the real test output to ternary-fte.tmpl 2012-12-02 13:03:20 +01:00
Dale Weiler
41881823b7 Add whitespace to ternary-fte template so it matches (expected behaviour) 2012-12-02 12:03:02 +00:00
Dale Weiler
8aff0f76c0 Fixes 2012-12-02 12:01:36 +00:00
Dale Weiler
b5a0fd7e42 Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-12-02 11:21:31 +00:00
Dale Weiler
628ed253b3 Improved testsuite diagnostics 2012-12-02 11:21:01 +00:00
Wolfgang (Blub) Bumiller
e8a1b7e71c Remove an unused variable qc_stof 2012-12-02 11:58:15 +01:00
Dale Weiler
79b8435877 Fix testsuite 2012-12-02 10:57:04 +00:00
Wolfgang (Blub) Bumiller
95865035eb Fix ternary operator entry for -std=gmqcc 2012-12-02 11:56:20 +01:00
Wolfgang (Blub) Bumiller
d39df54f8a Updating ternary testcase to use -fcorrect-ternary - added fte-style test as well for it 2012-12-02 11:52:25 +01:00
Dale Weiler
37ccf19769 added __STD_VERSION_[MINOR/MAJOR]__, and vec_upload 2012-12-02 04:30:46 +00:00
Wolfgang (Blub) Bumiller
c371efb882 Fix a type size bug: non-var locals overlapped with var locals, that was bad 2012-12-01 23:23:00 +01:00
Wolfgang (Blub) Bumiller
836935fba2 Remove unused omit-nullbytes code in code.c 2012-12-01 23:14:52 +01:00
Wolfgang (Blub) Bumiller
efe35ed02b Removed -fomit-null-bytes 2012-12-01 21:19:33 +01:00
Wolfgang (Blub) Bumiller
07f4e6309d Some of the output types were superfluous; others are now put into a function to take care of it 2012-12-01 16:39:29 +01:00
Wolfgang (Blub) Bumiller
de837f2380 Add some more output and field types so you can now properly call 'get_a_function_which_gives_a_function()()()' without return values getting lost 2012-12-01 16:11:04 +01:00
Wolfgang (Blub) Bumiller
b7ce7370e8 stof builtin #9 2012-12-01 15:54:13 +01:00
Wolfgang (Blub) Bumiller
dfd8f14116 function pointer's output types need to be set for the IR to know 2012-12-01 15:23:40 +01:00
Wolfgang (Blub) Bumiller
79e0c5c4fa More info in qcvm -printfuns 2012-12-01 15:23:04 +01:00
Wolfgang (Blub) Bumiller
53fd019780 -fcorrect-ternary; by default -std=fteqcc now uses fteqcc's wrong ternary precedence parsing 2012-12-01 13:42:16 +01:00
Wolfgang (Blub) Bumiller
8188d0b9f7 Sanity check for -Wternary-precedence 2012-12-01 12:36:54 +01:00
Wolfgang (Blub) Bumiller
ed4c513b1e -Wternary-precedence; *sight* this is tough 2012-12-01 12:35:46 +01:00
Wolfgang (Blub) Bumiller
624e95ee03 Generate extparams on calls too since the to-be-called function needs not be generated first after all 2012-12-01 11:43:54 +01:00
Wolfgang (Blub) Bumiller
b966cd4f4d More ternary fixes 2012-12-01 00:50:04 +01:00
Wolfgang (Blub) Bumiller
43c0343755 Offsetting builtins so we can use 'if builtin!=0' as condition but also allow a '#0' builtin 2012-12-01 00:36:24 +01:00
Wolfgang (Blub) Bumiller
e102c1632b Upping the default max-array-limit *sigh* 2012-12-01 00:34:18 +01:00
Wolfgang (Blub) Bumiller
75ab0e6663 and 'const' is a keyword, not an ident 2012-12-01 00:33:07 +01:00
Wolfgang (Blub) Bumiller
ac9d68387c var const / const var - both need to be allowed 2012-12-01 00:32:18 +01:00
Wolfgang (Blub) Bumiller
d52879315d some SYA fix; adding optional variable parsing to the head of a switch block 2012-12-01 00:31:00 +01:00
Wolfgang (Blub) Bumiller
46942df6c0 skipwhite bugfix 2012-11-30 21:51:18 +01:00
Wolfgang (Blub) Bumiller
d148cfdcd5 bodyless loops still have to loop 2012-11-30 21:34:49 +01:00
Wolfgang (Blub) Bumiller
8d014cc6eb changing parse_statement_or_block to return a bool and put the output block into a pointer, so that NULL can still be possible 2012-11-30 21:31:19 +01:00
Wolfgang (Blub) Bumiller
cda62cef20 apparently #0 is a valid builtin number, used for some NULL funcs 2012-11-30 21:25:18 +01:00
Wolfgang (Blub) Bumiller
2a2465c884 prepare fields before generating globals so we avoid the need for relocating initialized fieldpointers 2012-11-30 21:22:48 +01:00
Wolfgang (Blub) Bumiller
2a3e7c1cff field constants - revert globals generated after fields 2012-11-30 21:11:25 +01:00
Wolfgang (Blub) Bumiller
316298650e remember if an ast_value is a field-declaration, build fields before globals 2012-11-30 21:03:57 +01:00
Wolfgang (Blub) Bumiller
1a264e5576 additional info in an internal error 2012-11-30 20:40:48 +01:00
Wolfgang (Blub) Bumiller
b3a9c4e8d9 Use the field parameter type on the raw paramter type list for their sizes. 2012-11-30 20:33:40 +01:00
Wolfgang (Blub) Bumiller
e0a7f8a484 qcvm -printfuns; prog_section_function.nargs is now signed as fteqcc sets builtins with varargs to have -1 params 2012-11-30 20:20:13 +01:00
Wolfgang (Blub) Bumiller
a9a41a786e Adding opts.def as dep to everything which has gmqcc.h as dep 2012-11-30 18:21:14 +01:00
Wolfgang (Blub) Bumiller
6fc00e523d All ir_instrs now get their lex-context, so that we can create an LNO file with -flno 2012-11-30 18:20:02 +01:00
Wolfgang (Blub) Bumiller
2f3612d905 increase the ridiculously low size limit on lex-pragma parameters 2012-11-30 17:28:46 +01:00
Wolfgang (Blub) Bumiller
bda5ff4213 update other value/const check for array indexing 2012-11-30 16:28:09 +01:00
Wolfgang (Blub) Bumiller
696a8629b3 Don't treat initialized non-consts as static array indices 2012-11-30 16:25:18 +01:00
Wolfgang (Blub) Bumiller
6acd159c9c Keeping track of numbers for debugging 2012-11-30 16:23:42 +01:00
Wolfgang (Blub) Bumiller
9f1aa1490a out-of-bounds indexing check on static array indexing 2012-11-30 16:23:34 +01:00
Wolfgang (Blub) Bumiller
44cbf40553 We can now reintroduce the 'preprocessor-directives only after newlines' rule correctly 2012-11-30 15:53:53 +01:00
Wolfgang (Blub) Bumiller
f1a36ca647 Ignore modelgen commands with lex->flags.preprocessing 2012-11-30 15:44:45 +01:00
Wolfgang (Blub) Bumiller
41cb923c0c Wrong condition *sigh* 2012-11-30 15:43:18 +01:00
Wolfgang (Blub) Bumiller
0627e9e06e Still have to parse ahead though 2012-11-30 15:41:01 +01:00
Wolfgang (Blub) Bumiller
b78dab9d71 Don't expand macros inside #if 0 at _all_ 2012-11-30 15:40:19 +01:00
Wolfgang (Blub) Bumiller
5ca4390a1f Don't produce 'unknown token' errors in preprocessing mode 2012-11-30 15:38:03 +01:00
Wolfgang (Blub) Bumiller
7f915c0f2a Don't try to add a slash to actual filenames, only paths... 2012-11-30 15:26:14 +01:00
Wolfgang (Blub) Bumiller
645bd212d7 Don't try to compile an empty output from the preprocessor 2012-11-30 15:20:23 +01:00
Wolfgang (Blub) Bumiller
f587e9cfb3 remove array-field without parens warning since it seems to not be broken in fteqcc anymore 2012-11-30 14:47:55 +01:00
Wolfgang (Blub) Bumiller
0252c0a47a Fix indentation of compile_warning 2012-11-30 14:46:56 +01:00
Wolfgang (Blub) Bumiller
535fd5744b lex_ctx of a return will be at the return keyword now 2012-11-30 14:42:18 +01:00
Wolfgang (Blub) Bumiller
207293bf74 revert 1 of the error messages 2012-11-30 14:37:54 +01:00
Wolfgang (Blub) Bumiller
321a1fe0d6 Keep track of the beginning of a block 2012-11-30 14:37:23 +01:00
Wolfgang (Blub) Bumiller
eec61af381 mark vectors as used when their members are used 2012-11-30 14:30:25 +01:00
Wolfgang (Blub) Bumiller
b476a3deca fteqcc's \{number\} string control sequences 2012-11-30 14:22:00 +01:00
Wolfgang (Blub) Bumiller
fefb51c592 fteqcc like \[ and \] in strings 2012-11-30 14:18:45 +01:00
Wolfgang (Blub) Bumiller
70bda85629 lexer: hex sequences with \x and fteqcc-specific handling if one-digit sequences and <, -, and > sequences 2012-11-30 14:18:15 +01:00
Wolfgang (Blub) Bumiller
600ecda860 Set the full const/var qualifier; only generate warnings about unimplemented functions if they have no qualifier at all 2012-11-30 14:05:25 +01:00
Wolfgang (Blub) Bumiller
5e23e8296d don't just store a 'bool constant' in the ast/ir, store the complete qualifier: 'int cvq', moved CV_ defines into gmqcc.h 2012-11-30 13:47:28 +01:00
Wolfgang (Blub) Bumiller
8e043c8447 Remove the 'warnreturn' parameter in some parser functions 2012-11-30 12:37:46 +01:00
Wolfgang (Blub) Bumiller
39b8d8431c Actually generate the missing return instruction 2012-11-30 12:35:33 +01:00
Wolfgang (Blub) Bumiller
9841bc2f0d ast_loop with no condition and no incrementor are 'for(;;)' and need to loop endlessly instead of once... 2012-11-30 12:28:51 +01:00
Wolfgang (Blub) Bumiller
42376513e7 Still need to generate the jump... 2012-11-30 12:23:27 +01:00
Wolfgang (Blub) Bumiller
a19849099c ast_ifthen will not create dead blocks anymore 2012-11-30 12:21:10 +01:00
Wolfgang (Blub) Bumiller
a58061464e actually removing -Wmissing-return-values from parser.c and enabling the ast code for it 2012-11-30 12:11:36 +01:00
Wolfgang (Blub) Bumiller
2ec0a96a21 Fix a wrong vec_remove in the tailcall pass 2012-11-30 11:59:03 +01:00
Wolfgang (Blub) Bumiller
03cb670096 don't use vec_size but _vec_end in _vec_remove, since using it on an empty vector is an error anyway; this causes a warning about vec_pop doing an effect-less memmove so vec_pop now doesn't use vec_remove anymore actually 2012-11-30 11:55:32 +01:00
Wolfgang (Blub) Bumiller
0983125d2d print the number of performed optimizations after compiling 2012-11-30 11:47:35 +01:00
Wolfgang (Blub) Bumiller
17029ba695 Also print the numeric -O flag which would enable an optimization when listing optimizations via -Ohelp 2012-11-30 11:15:57 +01:00
Wolfgang (Blub) Bumiller
e1fe6cff54 Importing tail-recursion optimization 2012-11-30 11:12:53 +01:00
Wolfgang (Blub) Bumiller
a890589031 -O now, additionally to taking a number, can work like -W and -f to take an actual optimization name 2012-11-30 11:05:58 +01:00
Wolfgang (Blub) Bumiller
fef9303381 moving opts_warn and opts_werror to con.c 2012-11-28 19:18:11 +01:00
Wolfgang (Blub) Bumiller
3c1992fc38 qcvm didn't compile since moving the compile messages to con.c due to undefined references - fixed now 2012-11-28 19:16:35 +01:00
Wolfgang (Blub) Bumiller
8e1ce2ab5e generic compile_error/compile_warning functions in con.c, issuing end-of-non-void warning from within the ast now 2012-11-26 16:12:40 +01:00
Wolfgang (Blub) Bumiller
e6928c6b78 Checking in test for nested ternaries; this is more a test of the ast than the parser 2012-11-26 14:12:56 +01:00
Wolfgang (Blub) Bumiller
08551eefba Fix a small typo 2012-11-26 14:05:31 +01:00
Dale Weiler
ca52ecc20a Remove trailing whitespace for Blub. 2012-11-26 11:12:06 +00:00
Dale Weiler
77272da718 opval is asserted .. need (void) to hide warning when NDEBUG 2012-11-26 02:12:50 +00:00
Dale Weiler
a336fb62ff fast optimized murmur hash with crc seeding, literally zero collision, and roughly only 52 instructions 2012-11-26 00:21:16 +00:00
Wolfgang (Blub) Bumiller
ec2ff09eff operator &~= must not cause the generated binstore to free the destination twice 2012-11-26 00:15:07 +01:00
Wolfgang (Blub) Bumiller
1c9de6763f Same as earlier: remember the outgoing block of a condition in a ternary since it could be different due to shortened logic 2012-11-25 23:54:15 +01:00
Wolfgang (Blub) Bumiller
bf244fc960 ast_breakcont_codegen: error when a target is missing instead of segfaulting trying to access it anyway 2012-11-25 23:51:39 +01:00
Wolfgang (Blub) Bumiller
0564e701c0 endlessloops don't have any other block which could be a continue-target-block, so use the body itself to not continue to NULL 2012-11-25 23:50:42 +01:00
Wolfgang (Blub) Bumiller
23e0637e85 ir_function_create_block now takes a lex_ctx instead of copying from the function; ast_ternary: need to remember the _end_ block of the 2 expressions because that's where the jump is actually supposed to be 2012-11-25 23:48:29 +01:00
Wolfgang (Blub) Bumiller
d70fcdec42 don't set the request-Lvalue flag for an array index 2012-11-25 23:35:49 +01:00
Wolfgang (Blub) Bumiller
0af62801f4 Don't add redeclared globals a second time 2012-11-25 23:35:31 +01:00
Wolfgang (Blub) Bumiller
7c241da548 more verbose errors in the ast when an ir-create fails 2012-11-25 23:32:10 +01:00
Wolfgang (Blub) Bumiller
38df8b5e40 Another case for -fassign-function-types 2012-11-25 23:28:47 +01:00
Wolfgang (Blub) Bumiller
0d3896ca54 introducing -fassign-function-types, previously guarded by std==qcc this is now the flag to cause a warning (-Wassign-function-types) instead of an error when assigning functions of wrong types 2012-11-25 23:27:48 +01:00
Wolfgang (Blub) Bumiller
b4a5517851 fix a lexer error which parsed !! as one operator 2012-11-25 23:24:39 +01:00
Wolfgang (Blub) Bumiller
2f5a26a4de __builtin_debug_printtype directive... helped me down tracking a bug: parsing typedeffed types in parameter lists properly now 2012-11-25 22:57:11 +01:00
Wolfgang (Blub) Bumiller
08ef8bd045 Only check the ast-type of a switch case, not if it's an ACTUAL constant, fteqcc doesn't either... grrr 2012-11-25 22:40:35 +01:00
Wolfgang (Blub) Bumiller
10f49a38ca actually handle unary plus... 2012-11-25 22:38:52 +01:00
Wolfgang (Blub) Bumiller
089e490c69 Allow float constants which start with a dot 2012-11-25 22:35:41 +01:00
Wolfgang (Blub) Bumiller
42bd37a2e8 Ah right, 'var' is not an actual keyword, support TOKEN_IDENT-var inside functions 2012-11-25 22:26:28 +01:00
Wolfgang (Blub) Bumiller
f1bbdb7d45 Use the correct default cv-qualifier on locals 2012-11-25 22:16:08 +01:00
Wolfgang (Blub) Bumiller
c62e0a93eb Allow 'var' in functions... even there initialized locals seem to be constant by default... laaaaaaaame 2012-11-25 22:15:08 +01:00
Dale Weiler
967254f7f2 Fix the testsuite to properly error on failed loads 2012-11-25 21:12:26 +00:00
Wolfgang (Blub) Bumiller
797ceb9e04 handling TOKEN_CHARCONST - -Wmultibyte-character 2012-11-25 22:11:21 +01:00
Wolfgang (Blub) Bumiller
2234090398 Actually use TOKEN_CHARCONST in the lexer... 2012-11-25 22:04:27 +01:00
Wolfgang (Blub) Bumiller
0301ea7818 Don't error about creating an unreachable statement if the node we're about to generate is an ast_label 2012-11-25 21:59:57 +01:00
Wolfgang (Blub) Bumiller
e2602e6b87 Filling up remaining gotos at the end of a function for when the label is defined after the goto; erroring for missing labels 2012-11-25 21:56:38 +01:00
Wolfgang (Blub) Bumiller
2ec8ef4406 making goto a keyword 2012-11-25 21:56:21 +01:00
Wolfgang (Blub) Bumiller
24f9b63475 parsing goto 2012-11-25 21:53:14 +01:00
Wolfgang (Blub) Bumiller
4b71b74c6a Add the array tests, seem to have forgotten to add those... 2012-11-25 21:41:30 +01:00
Wolfgang (Blub) Bumiller
f431b7a693 Support codegen of ast_label and ast_goto in any order 2012-11-25 21:40:26 +01:00
Wolfgang (Blub) Bumiller
474d8bd6f0 ast_label, and labels later used for goto 2012-11-25 21:27:14 +01:00
Wolfgang (Blub) Bumiller
336d91494f temporarily disable the 'constant' flag when parsing the initializer to avoid the 'assigning to constant' error in a block-local constant 2012-11-25 21:10:43 +01:00
Wolfgang (Blub) Bumiller
22173df7bd Allow 'const' within function bodies 2012-11-25 21:08:30 +01:00
Wolfgang (Blub) Bumiller
36cdffe1b3 Fix linecounting mistake in try_digraph 2012-11-25 21:07:03 +01:00
Wolfgang (Blub) Bumiller
3424b7227b Set the output to NULL always before parsing stuff 2012-11-25 20:48:06 +01:00
Wolfgang (Blub) Bumiller
4513fc4d0b fix wrong parameter order in parse_variable calls, dammit I hate how 'bool' and 'int' are implicitly convertible here 2012-11-25 20:29:12 +01:00
Wolfgang (Blub) Bumiller
1b72cb264a more on CV_CONST/CV_VAR, initializers to check 'constant' not just 'hasvalue' 2012-11-25 20:25:39 +01:00
Wolfgang (Blub) Bumiller
6cd432a909 const/variable qualifier flag for parse_variable 2012-11-25 20:22:47 +01:00
Wolfgang (Blub) Bumiller
779c974511 Allow dangling semicolons for now 2012-11-25 20:18:40 +01:00
Wolfgang (Blub) Bumiller
f2887f1208 a '(void)' parameter list does not mean 1 parameter of type void, but empty... xonotic needs this 2012-11-25 19:44:21 +01:00
Wolfgang (Blub) Bumiller
b59401db1b fixed: -frelaxed-switch check was in the wrong position 2012-11-25 19:42:16 +01:00
Wolfgang (Blub) Bumiller
353b1f945f assignment to constant error 2012-11-25 19:37:31 +01:00
Wolfgang (Blub) Bumiller
39f572fe99 constant flag, -finitialized-nonconstants to turn initialized globals into mutable variables 2012-11-25 19:35:00 +01:00
Wolfgang (Blub) Bumiller
6e400ca81f ast: isconst->hasvalue, const keyword will set the const flag 2012-11-25 19:30:10 +01:00
Wolfgang (Blub) Bumiller
55aa53beca Parse the 'not' keyword in if as TOKEN_IDENT 2012-11-25 19:20:00 +01:00
Wolfgang (Blub) Bumiller
ca033e5acd Some side-effect propagation for better warnings, so that comma-operators with assignments in them don't cause the -Weffectless-statement warning, and fixing ternary precedence for fte operator list 2012-11-25 19:19:36 +01:00
Wolfgang (Blub) Bumiller
63d89f9f5a Allow regular AND used on non-float types 2012-11-25 18:56:22 +01:00
Wolfgang (Blub) Bumiller
bf23ed948d Allow strings to contain a backslash and a newline at the end 2012-11-25 18:38:04 +01:00
Wolfgang (Blub) Bumiller
2c0a9d78df Guard translatable strings by -ftranslatable-strings, defaults to ON with -std=fteqcc 2012-11-25 18:25:01 +01:00
Wolfgang (Blub) Bumiller
66317aaef9 update noops flag while parsing a translatable string 2012-11-25 18:23:48 +01:00
Wolfgang (Blub) Bumiller
7838e772de Translatable string constants 2012-11-25 18:22:00 +01:00
Wolfgang (Blub) Bumiller
0df394dcbc parser_const_string can now create a translatable string 2012-11-25 18:17:08 +01:00
Wolfgang (Blub) Bumiller
f65dbda659 linecounting fix for push/pop(line) pragmas 2012-11-25 18:13:46 +01:00
Wolfgang (Blub) Bumiller
e3acdcf0a9 Let's not have + and - as sole token, always allow ++ and -- to become operators independent of the noops flag 2012-11-25 18:07:19 +01:00
Wolfgang (Blub) Bumiller
b457bfec2a linecounting... 2012-11-25 18:02:54 +01:00
Wolfgang (Blub) Bumiller
04347508e6 linecounting issue in the lexer 2012-11-25 17:50:31 +01:00
Wolfgang (Blub) Bumiller
9a9ecd574e Fix a bug in the lexer causing double-dots to double the character after the 2nd dot 2012-11-25 17:43:24 +01:00
Wolfgang (Blub) Bumiller
e22af32805 Fix parsing of multi-dot field types 2012-11-25 17:43:13 +01:00
Wolfgang (Blub) Bumiller
2884556fe3 multiple dots to start a field type, ie ..float for a fieldpointer field 2012-11-25 17:37:54 +01:00
Wolfgang (Blub) Bumiller
b5d6f454a4 moving cleanvar=false out of a condition 2012-11-25 16:20:22 +01:00
Wolfgang (Blub) Bumiller
07fa97b8e7 linecounting issues in the ftepp 2012-11-25 16:08:41 +01:00
Wolfgang (Blub) Bumiller
2da37129d7 a more verbose error 2012-11-25 15:58:10 +01:00
Wolfgang (Blub) Bumiller
4b619ce1cd -Wconst-var 2012-11-25 15:56:13 +01:00
Wolfgang (Blub) Bumiller
93ae1a65fb Fixing propogate->propAgate typo in test.c 2012-11-25 15:39:49 +01:00
Wolfgang (Blub) Bumiller
de2e2bd6d3 s/succeed/succeeded/ 2012-11-25 15:36:20 +01:00
Wolfgang (Blub) Bumiller
f132166f46 Simplify some condition in the tester 2012-11-25 15:35:04 +01:00
Wolfgang (Blub) Bumiller
7cd6a477f8 Typedef testcases 2012-11-25 15:33:03 +01:00
Wolfgang (Blub) Bumiller
f6a374c1d5 free the _locals vector 2012-11-25 15:31:26 +01:00
Wolfgang (Blub) Bumiller
3c0c002e2f Fix a missing uninitialized value which caused typedefs within functions to cause a segfault 2012-11-25 15:30:31 +01:00
Wolfgang (Blub) Bumiller
63d9e44f56 Allow typedefs to shadow defs of previous scopes 2012-11-25 15:27:22 +01:00
Wolfgang (Blub) Bumiller
b851f542ac Implementing typedef 2012-11-25 15:21:52 +01:00
Wolfgang (Blub) Bumiller
a1b50603e5 fixing a leak in the hashtables, htdel didn't delete the hash_node_t entries 2012-11-25 15:12:16 +01:00
Wolfgang (Blub) Bumiller
23d16b303d typedef is now a keyword 2012-11-25 14:29:59 +01:00
Wolfgang (Blub) Bumiller
e7bf73455d always define GMQCC, never define FTEQCC or QCC, but have __STD_FTEQCC__ and the likes for -std=qcc/gmqcc/fteqcc 2012-11-25 14:29:06 +01:00
Wolfgang (Blub) Bumiller
7b56ad9405 Revert "Fix type punning warnings"
it's a gcc version issue...

This reverts commit 3e6d173e31.
2012-11-25 14:05:10 +01:00
Dale Weiler
3e6d173e31 Fix type punning warnings 2012-11-25 12:57:28 +00:00
Wolfgang (Blub) Bumiller
d69b576d6b Fix some uninitialized values 2012-11-25 13:55:29 +01:00
Wolfgang (Blub) Bumiller
18b27d5cf6 use the hashtables in the IR 2012-11-25 13:37:54 +01:00
Wolfgang (Blub) Bumiller
060f995ca4 removing ir_function_get_local - it's unused 2012-11-25 13:33:00 +01:00
Wolfgang (Blub) Bumiller
613e1e7247 Change the parser to use the hashtable functions 2012-11-25 13:23:37 +01:00
Dale Weiler
9c0231a58e Some hashtable changes 2012-11-24 21:46:28 +00:00
Dale Weiler
32c928ab6d You made substantial changes to this file, you get a name :P 2012-11-24 21:23:21 +00:00
Dale Weiler
5c0a62be96 Add respective license headers + some cleanups 2012-11-24 21:22:35 +00:00
Dale Weiler
f454a9f9cd Whitespace 2012-11-24 20:33:03 +00:00
Dale Weiler
8bce855f0b Set correct macro for PP based on the selected standard 2012-11-24 00:37:36 +00:00
Dale Weiler
3dbe54f0cd Implemented -W? and -f? as aliases to -Whelp and -fhelp 2012-11-24 00:29:30 +00:00
Dale Weiler
4f00824104 Implemented -show-defaults 2012-11-24 00:26:51 +00:00
Wolfgang (Blub) Bumiller
d09ccba5d6 -Wdouble-declaration on by default 2012-11-23 23:44:35 +01:00
Wolfgang (Blub) Bumiller
86f3ef2194 turn the message about global variable double-declaration into a warning instead of an error on std != gmqcc 2012-11-23 22:30:35 +01:00
Wolfgang (Blub) Bumiller
39b8b6a660 warn about double function declarations... 2012-11-23 22:22:22 +01:00
Wolfgang (Blub) Bumiller
5897f0439c A nice internal error 2012-11-23 22:15:17 +01:00
Wolfgang (Blub) Bumiller
2bc99076cf 'var' is now no keyword anymore, :\ 2012-11-23 22:07:35 +01:00
Wolfgang (Blub) Bumiller
1c7e9c5fde handling 'const' - still need correct separation of constant and just initialized later when we distinguish between them 2012-11-23 21:52:16 +01:00
Wolfgang (Blub) Bumiller
e3c1244687 preserve newlines in preprocessed multiline comments 2012-11-23 21:47:00 +01:00
Wolfgang (Blub) Bumiller
6df6906ed2 Adding an unrecognized keywords error 2012-11-23 21:41:50 +01:00
Wolfgang (Blub) Bumiller
ab55673c35 Fix a very nasty bug in the lexer's handling of comments 2012-11-23 21:35:14 +01:00
Dale Weiler
9bb80788d8 Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-11-23 20:06:11 +00:00
Dale Weiler
9d677bab7c Added comment about hashtable 2012-11-23 20:05:53 +00:00
Wolfgang (Blub) Bumiller
74fce32233 relation operation in #if just as wrong as in fteqcc 2012-11-23 21:05:07 +01:00
Dale Weiler
6e047ec65b No copy, just store pointer for hash table 2012-11-23 20:01:58 +00:00
Wolfgang (Blub) Bumiller
58c87ac328 Enforce a trailing nul-byte after preprocessing 2012-11-23 19:34:24 +01:00
Wolfgang (Blub) Bumiller
85e98e9f53 Don't ftepp_warn after destroying the lexer... 2012-11-23 19:30:02 +01:00
Wolfgang (Blub) Bumiller
37eaaa76f9 Look for include files in the currently #included file's directory first 2012-11-23 19:29:45 +01:00
Wolfgang (Blub) Bumiller
4a3921fcb9 Let's #define GMQCC by default 2012-11-23 19:13:09 +01:00
Wolfgang (Blub) Bumiller
f6b7ddf72b Don't delete the ftepp prematurely 2012-11-23 15:03:10 +01:00
Wolfgang (Blub) Bumiller
498cbf6fa5 ftepp_out can return a nullptr 2012-11-23 14:59:56 +01:00
Wolfgang (Blub) Bumiller
0d33939b1b operator &~= 2012-11-23 14:39:05 +01:00
Wolfgang (Blub) Bumiller
122e80cc4d operators &= and |= 2012-11-23 14:28:11 +01:00
Wolfgang (Blub) Bumiller
553f3df5df *= and /= operators 2012-11-23 14:24:58 +01:00
Wolfgang (Blub) Bumiller
5867167a70 Fixing operator precedence of suffices 2012-11-23 12:32:07 +01:00
Wolfgang (Blub) Bumiller
448d4ebd75 operator tests 2012-11-23 12:29:52 +01:00
Wolfgang (Blub) Bumiller
1223e04e05 correcting an error message 2012-11-23 12:28:51 +01:00
Wolfgang (Blub) Bumiller
f22f1af891 Suffix operators, and remembering the const-float-1 in parser_t 2012-11-23 12:25:13 +01:00
Wolfgang (Blub) Bumiller
4079835c7e Parsing of suffix operators, NOTE: applied like prefix operators just to get it committed in a compilable state 2012-11-23 11:57:08 +01:00
Wolfgang (Blub) Bumiller
38f5090778 Prefix ++,-- 2012-11-23 11:52:03 +01:00
Wolfgang (Blub) Bumiller
9a43eb6370 a type_name -> ast_type_to_string conversion 2012-11-23 11:45:22 +01:00
Wolfgang (Blub) Bumiller
3f805fdde9 -std=fteqcc gets its own operator list 2012-11-23 11:45:07 +01:00
Dale Weiler
e25e83b14c Visual studio __forceinline can be used for GMQCC_INLINE 2012-11-23 06:48:54 +00:00
Dale Weiler
c748293ccb Use memcmp for comparing doubles 2012-11-23 06:41:06 +00:00
Dale Weiler
46fff99fad ast_binstore_codegen initialize left ir value to null for output left side used for lvalue to prevent clang from warning. Also fixed uninitialized bug in hashtable implementation 2012-11-23 06:26:19 +00:00
Dale Weiler
81bb87c49b Sign conversion fixes in exec.c 2012-11-23 06:23:20 +00:00
Dale Weiler
f4edbe2165 Cleanups 2012-11-23 06:17:21 +00:00
Dale Weiler
9e3399df19 Implemented hashtable as-per Blubs request 2012-11-23 06:12:01 +00:00
Dale Weiler
02a933b808 Wall was already there, changed pedantic, into pedantic-errors 2012-11-23 02:31:02 +00:00
Dale Weiler
20d65da321 change choice of diagnostics for ftepp to use lex_ctx instance. Cleaned up C++ style comments, and some other things ... 2012-11-23 02:29:01 +00:00
Dale Weiler
b5507b3127 Make it compile with -Wall and -pedantic 2012-11-23 02:23:22 +00:00
Dale Weiler
af2324e922 Fix getline 2012-11-22 22:11:53 +00:00
Wolfgang (Blub) Bumiller
a4198fc27e Fixing the makefile - stop adding pointless defaults 2012-11-22 23:11:29 +01:00
Wolfgang (Blub) Bumiller
fafc755274 Fixing up ast_binstore_codegen to handle array updates 2012-11-22 22:42:47 +01:00
Dale Weiler
fcc57a1185 Fix memory leaks 2012-11-22 21:38:14 +00:00
Dale Weiler
59e81eeb7f Remove some disabled warnings from the makefile 2012-11-22 20:46:38 +00:00
Wolfgang (Blub) Bumiller
905ca8819b unused params in parser.c 2012-11-22 21:44:09 +01:00
Wolfgang (Blub) Bumiller
facd89b188 unsed params in ftepp.c 2012-11-22 21:42:14 +01:00
Wolfgang (Blub) Bumiller
e6443496e7 Fix unused params in ir.c 2012-11-22 21:41:22 +01:00
Wolfgang (Blub) Bumiller
ed53040907 Fix unused parameters in ast.c 2012-11-22 21:39:30 +01:00
Dale Weiler
baf69f3725 Fix more warnings 2012-11-22 20:32:08 +00:00
Wolfgang (Blub) Bumiller
04665a9c94 conversion warnings and sanity check 2012-11-22 21:25:02 +01:00
Dale Weiler
6ea37089fa Fix some casting stuff 2012-11-22 20:16:34 +00:00
Wolfgang (Blub) Bumiller
a8b31be328 Fixing a shadowing in ir.c 2012-11-22 21:12:15 +01:00
Wolfgang (Blub) Bumiller
dfde3a583c Remove unused macro 2012-11-22 21:10:37 +01:00
Wolfgang (Blub) Bumiller
55915b5217 initialize some values 2012-11-22 21:10:34 +01:00
Wolfgang (Blub) Bumiller
07d5686a47 Fixing shadows in parser.c - moving generate_checksum over the static parser global 2012-11-22 20:47:46 +01:00
Wolfgang (Blub) Bumiller
b771695e0d Fixing shadows in lexer.c 2012-11-22 20:46:13 +01:00
Wolfgang (Blub) Bumiller
a87bc6a575 Removing unused _tokennames from lexer.h 2012-11-22 20:42:55 +01:00
Wolfgang (Blub) Bumiller
f6129ea4e4 Fixing main.c shadows 2012-11-22 20:42:44 +01:00
Wolfgang (Blub) Bumiller
968397da61 Fixing clang-warnings about vectors 2012-11-22 20:42:32 +01:00
Wolfgang (Blub) Bumiller
2f672cce1d Adding short-logic testcase 2012-11-22 20:32:40 +01:00
Wolfgang (Blub) Bumiller
f719a81e2a Fixing short-logic for 'if': it wanted to add the jump to the wrong block 2012-11-22 20:29:55 +01:00
Wolfgang (Blub) Bumiller
014ae1425e Test for extended parameters 2012-11-22 19:36:45 +01:00
Wolfgang (Blub) Bumiller
c5f8fbb871 Collapsing the switch tests into 1 2012-11-22 19:28:45 +01:00
Wolfgang (Blub) Bumiller
c0d46ba893 drop the E line from break.tmpl 2012-11-22 19:28:38 +01:00
Wolfgang (Blub) Bumiller
0500181327 Collapse the break tests into 1 2012-11-22 19:25:45 +01:00
Dale Weiler
fed86b73fd oops 2012-11-22 18:14:03 +00:00
Dale Weiler
6a8494f21b Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-11-22 18:13:12 +00:00
Dale Weiler
79bac33a40 Remove requirement for E 2012-11-22 18:12:47 +00:00
Wolfgang (Blub) Bumiller
ba9217e576 make ast_function_label also work when -dumpfin is used instead of -dump 2012-11-21 21:59:25 +01:00
Wolfgang (Blub) Bumiller
6983142c4d -dump vs -dumpfin; to see the IR before and after finalizing functions 2012-11-21 21:53:38 +01:00
Wolfgang (Blub) Bumiller
42135f1322 Escape strings in ir-dump output 2012-11-21 21:49:21 +01:00
Dale Weiler
2e3d572b53 Bump version 2012-11-21 20:33:52 +00:00
Dale Weiler
ec50d8508e Make blub happy 2012-11-21 20:31:41 +00:00
Dale Weiler
e7917d3225 Make makefile runtest rule depend on all to be built 2012-11-21 20:27:41 +00:00
Dale Weiler
1a5447ae8f less verbosity from test suite, just the way blub wants it 2012-11-21 20:26:18 +00:00
Wolfgang (Blub) Bumiller
e20184ae59 ast_ternary needs to adopt the output type 2012-11-21 20:57:00 +01:00
Wolfgang (Blub) Bumiller
9c8dc43775 error if the ternary operands aren't of the same type - except for the first one of course 2012-11-21 20:56:51 +01:00
Wolfgang (Blub) Bumiller
be52ca3879 More verbose error for invalid parameter types 2012-11-21 20:53:00 +01:00
Wolfgang (Blub) Bumiller
0787038934 check 'ternaries' count 2012-11-21 20:50:27 +01:00
Wolfgang (Blub) Bumiller
90bd91e294 Utilizing vec_last more 2012-11-21 20:44:43 +01:00
Wolfgang (Blub) Bumiller
5ec75a228e question mark must result in TOKEN_OPERATOR 2012-11-21 20:42:48 +01:00
Wolfgang (Blub) Bumiller
55c2148016 operator handling for ternary 2012-11-21 20:41:26 +01:00
Wolfgang (Blub) Bumiller
11f1af78d5 Removing some obsolete messages 2012-11-21 20:40:10 +01:00
Wolfgang (Blub) Bumiller
e0ddf32d2e parsing the ternary 2012-11-21 20:36:42 +01:00
Wolfgang (Blub) Bumiller
8517221b1b Inserting ternary in the qcc-operator-list at the place fteqcc would have it 2012-11-21 20:16:28 +01:00
Wolfgang (Blub) Bumiller
a7fb45f102 removed phi_out from ast_ternary since we have a place in ast_expression_common for this kind of value 2012-11-21 20:13:31 +01:00
Wolfgang (Blub) Bumiller
268ad7db53 Fix wrong merge_id 2012-11-21 19:55:12 +01:00
Wolfgang (Blub) Bumiller
de5592dfc5 -fperl-logic, off by default, so casting to boolean now 2012-11-21 19:40:11 +01:00
Wolfgang (Blub) Bumiller
ebc6954bf5 casting explicitly to boolean values in early out logic 2012-11-21 19:36:28 +01:00
Wolfgang (Blub) Bumiller
21c2fcb929 A note about how early-out in if-expressions can be translated more efficiently 2012-11-21 19:22:28 +01:00
Wolfgang (Blub) Bumiller
bd1bc0dc59 Actually it's likely... 2012-11-21 17:42:44 +01:00
Wolfgang (Blub) Bumiller
5a6b2bceb2 Little optimization to not produce an unreachable goto instruction 2012-11-21 17:40:35 +01:00
Wolfgang (Blub) Bumiller
b1425dfcf1 'likely' hint for IFs 2012-11-21 17:37:45 +01:00
Wolfgang (Blub) Bumiller
ca2b414c7c experimental -fshort-logic, currently perl-like - might have to use NOT(NOT(x)) to fix this 2012-11-21 16:08:08 +01:00
Wolfgang (Blub) Bumiller
1dfb14fef0 Fixing warnings 2012-11-21 16:07:36 +01:00
Wolfgang (Blub) Bumiller
390ac0d871 A hopefully working naive PHI solution 2012-11-21 16:05:54 +01:00
Dale Weiler
be8981a5c3 Implemented multi-line comparitive tests, fixed output of stdout/stderr pair logs. Some other cleanups, and stuff 2012-11-20 06:06:46 +00:00
Wolfgang (Blub) Bumiller
57e7303cf4 Adding break/continue testcases 2012-11-20 00:21:03 +01:00
Wolfgang (Blub) Bumiller
6bc72a0262 *sigh* 2012-11-20 00:20:42 +01:00
Wolfgang (Blub) Bumiller
62ff522013 Fixing switch testcase 7 2012-11-20 00:16:49 +01:00
Wolfgang (Blub) Bumiller
5778b6ffb6 switch testcases 2012-11-19 23:50:47 +01:00
Wolfgang (Blub) Bumiller
f4043faf0b -frelaxed-switch to enable switch on non-constant cases 2012-11-19 22:27:58 +01:00
Wolfgang (Blub) Bumiller
5c52e817ea Add the missing jump from after the actual last case 2012-11-19 22:17:24 +01:00
Wolfgang (Blub) Bumiller
986d58877f Enter the outgoing block after a switch 2012-11-19 22:08:38 +01:00
Wolfgang (Blub) Bumiller
4649c12fa9 Parsing of switches 2012-11-19 22:06:29 +01:00
Wolfgang (Blub) Bumiller
2a55dd7234 fix bnot_id 2012-11-19 22:06:23 +01:00
Wolfgang (Blub) Bumiller
63969180cf 'case' and 'default' are now keywords too, not just switch 2012-11-19 21:40:38 +01:00
Wolfgang (Blub) Bumiller
06ba28f2a0 ast_switch 2012-11-19 21:17:44 +01:00
Wolfgang (Blub) Bumiller
b72900214b fix a warning and remove unused variables 2012-11-19 19:44:26 +01:00
Wolfgang (Blub) Bumiller
8ac689c03a Error in the ast already about unreachable statements and don't upset the IR 2012-11-19 19:42:25 +01:00
Wolfgang (Blub) Bumiller
ea75003cf4 break and continue support 2012-11-19 19:39:52 +01:00
Wolfgang (Blub) Bumiller
2d8bf20d43 moving 'return' parsing into a function 2012-11-19 19:22:00 +01:00
Wolfgang (Blub) Bumiller
6e888396b5 moving keywords into an array 2012-11-19 19:20:26 +01:00
Wolfgang (Blub) Bumiller
3391874ebf Fix con_vprintmsg madness 2012-11-19 19:19:30 +01:00
Wolfgang (Blub) Bumiller
276346e63c This is probably what was intended actually 2012-11-19 19:06:38 +01:00
Dale Weiler
61fa54318c Merge branch 'master' into test-suite
Conflicts:
	Makefile
	ir.c
2012-11-19 02:13:46 +00:00
Dale Weiler
091173341e Added test for variadic arguments 2012-11-19 02:11:24 +00:00
Dale Weiler
245908f491 Added command line parsing to test-suite 2012-11-19 02:05:18 +00:00
Dale Weiler
b1c27e3bf2 stdout/stderr logging functional now. 2012-11-19 00:22:57 +00:00
Dale Weiler
4e85dfa71e Test suite now logs stdout/stderr to respective files 2012-11-18 22:59:23 +00:00
Wolfgang (Blub) Bumiller
19e82883ea Fixing some indentation 2012-11-18 20:56:11 +01:00
Wolfgang (Blub) Bumiller
f1735d91b8 remove a redundant ir_function member 2012-11-18 20:36:02 +01:00
Wolfgang (Blub) Bumiller
12fca5ef8f Make the disasm a bit more verbose as to where globals are 2012-11-18 20:32:22 +01:00
Wolfgang (Blub) Bumiller
ed6189e655 do not set a function-defs nargs to > 8 2012-11-18 20:32:06 +01:00
Wolfgang (Blub) Bumiller
149481b80c CALL to handle extparams, renamed extparams again 2012-11-18 20:17:59 +01:00
Wolfgang (Blub) Bumiller
45cd90c777 Add a # prefix to EXTPARM%i 2012-11-18 20:11:14 +01:00
Wolfgang (Blub) Bumiller
f023004a67 Make functions copy their extparams 2012-11-18 20:06:28 +01:00
Wolfgang (Blub) Bumiller
e8d1e5dbc0 Make the >8 parameter message a warning 2012-11-18 19:19:38 +01:00
Wolfgang (Blub) Bumiller
41235108c4 Importing a tiny README file 2012-11-18 19:15:20 +01:00
Wolfgang (Blub) Bumiller
ccb9cf5347 Importing LICENSE file 2012-11-18 19:14:06 +01:00
Wolfgang (Blub) Bumiller
2652353f50 Checking in an INSTALL file 2012-11-18 18:54:10 +01:00
Wolfgang (Blub) Bumiller
2ab7d8d5c3 Adding myself to main.c's copyright notice 2012-11-18 17:06:26 +01:00
Wolfgang (Blub) Bumiller
e4998e0798 Added #include 2012-11-18 16:22:07 +01:00
Wolfgang (Blub) Bumiller
43a72b2a63 Don't skip the \n after parsing a pragma in the lexer otherwise 2 pragmas in the row wouldn't work 2012-11-18 16:17:19 +01:00
Wolfgang (Blub) Bumiller
a5dbfacf2f pragma line(lineno) - sets the linenumber for the line after the pragma 2012-11-18 15:32:03 +01:00
Wolfgang (Blub) Bumiller
e66f2bcb33 Better linecounting for pragmas; support for prgama file(filename) 2012-11-18 15:30:49 +01:00
Wolfgang (Blub) Bumiller
d3861cea9f Make pragmas pass through the preprocessor so the user can write them manually 2012-11-18 15:30:24 +01:00
Wolfgang (Blub) Bumiller
9898ab5316 fixup line counting in #pragmas 2012-11-18 15:23:00 +01:00
Wolfgang (Blub) Bumiller
79619fbf50 Experimental support for push/pop(line) pragmas 2012-11-18 15:14:42 +01:00
Wolfgang (Blub) Bumiller
4c2e5d7ebf update old_string after a recursive preprocess call so we don't reset to a free'd vector; add recursion header/footer pragmas 2012-11-18 14:39:24 +01:00
Wolfgang (Blub) Bumiller
441a224435 Comment about why stringify is so short 2012-11-18 14:29:15 +01:00
Wolfgang (Blub) Bumiller
edbe8f54cb don't call parser_cleanup with -E 2012-11-18 14:27:47 +01:00
Wolfgang (Blub) Bumiller
a014480987 Add quotes to the known control sequences... darn. Add stringification via # 2012-11-18 14:26:40 +01:00
Wolfgang (Blub) Bumiller
0330b082a2 The ftepp now always outputs into a string buffer, with -E the buffer will be dumped to stdout or the via -o specified file, without -E it'll be passed to the parser to be compiled 2012-11-18 13:33:53 +01:00
Wolfgang (Blub) Bumiller
f0d56d07fe Merge branch 'master' into ftepp 2012-11-18 13:06:29 +01:00
Wolfgang (Blub) Bumiller
cec58b53e4 Collect accessor functions in the parser so they can later be deleted, fixed that leak 2012-11-18 13:06:16 +01:00
Wolfgang (Blub) Bumiller
f47a20aa53 Removing some code duplication 2012-11-18 13:00:18 +01:00
Wolfgang (Blub) Bumiller
d1373af7fc Make -E print to stdout by default and honor -o, changed handling of source list a bit 2012-11-18 12:51:38 +01:00
Wolfgang (Blub) Bumiller
366557bbab Since like with parsing, the preprocessor state has to be preserved across files for macros, we do that now, and with that introduce a new warning: -Wmultifile-if in case an #if spans over several command-line-provided source files (or progs.src file provided for that matter) 2012-11-18 11:54:11 +01:00
Wolfgang (Blub) Bumiller
2b65ea599f Some printf/con_out/con_err conversions, guarded some outputs with not-opts_pp_only so the -E switch can print to stdout normally 2012-11-18 11:43:46 +01:00
Wolfgang (Blub) Bumiller
79abe3fb6d Merge branch 'master' into ftepp 2012-11-17 11:34:00 +01:00
Dale Weiler
d1fd7d044b Merge branch 'master' into test-suite
Conflicts:
	Makefile
2012-11-17 10:02:21 +00:00
Dale Weiler
227c85ba4e More makefile changes 2012-11-17 10:00:55 +00:00
Wolfgang (Blub) Bumiller
852b2b91d2 install targets 2012-11-17 11:00:32 +01:00
Dale Weiler
990dcb106a Merge branch 'master' into test-suite
Conflicts:
	Makefile
2012-11-17 09:56:48 +00:00
Dale Weiler
55491bbc23 Added more tests, fixed existing ones, and some more test system changes. 2012-11-17 09:51:55 +00:00
Wolfgang (Blub) Bumiller
6333130537 Temporary list of dependencies for objects 2012-11-17 10:46:23 +01:00
Wolfgang (Blub) Bumiller
33be9edec7 quick and dirty fix to lexerror for when fopen fails 2012-11-17 10:36:35 +01:00
Wolfgang (Blub) Bumiller
7b74a2bb94 removing mem.c from this branch in preparation for 0.1 2012-11-17 10:35:52 +01:00
Dale Weiler
d0c6e0a481 sigh 2012-11-17 08:54:24 +00:00
Dale Weiler
e062c847cb Fix test suite 2012-11-17 08:50:09 +00:00
Dale Weiler
49cb2bcda2 Actually add the tests 2012-11-17 08:31:23 +00:00
Dale Weiler
56987b41eb Test system works, and added some working tests! 2012-11-17 08:10:31 +00:00
Dale Weiler
bf3011a28d Actually commit the new test stuff 2012-11-17 02:55:33 +00:00
Dale Weiler
0dc4febb91 New test-suite initial implementation. Just need to write some tests. 2012-11-17 02:54:30 +00:00
Wolfgang (Blub) Bumiller
515cafe8bd Lexer should keep newlines in merged lines, so will the preprocessor, but therefore the lexer will replace comments with actual spaces so we don't get borken output... also don't error about redifining a macro when inside a non-outputting #if branch 2012-11-16 23:13:53 +01:00
Wolfgang (Blub) Bumiller
990450bfe0 ## concatenation, -Wpreprocessor warning about redefining macros, #undef 2012-11-16 22:54:59 +01:00
Wolfgang (Blub) Bumiller
d237ff1736 don't error on non-EOL EOF at the end of a macro line 2012-11-16 22:41:29 +01:00
Wolfgang (Blub) Bumiller
0ad2b8b2c7 also use recursive-expansion on macros without parameters 2012-11-16 22:38:58 +01:00
Wolfgang (Blub) Bumiller
57ac55ad01 recursively call the preprocessor on expanded macros 2012-11-16 22:31:51 +01:00
Wolfgang (Blub) Bumiller
05a26333fc Expand macros into a string buffer 2012-11-16 22:22:31 +01:00
Wolfgang (Blub) Bumiller
99dd208880 moving ftepp_delete out of ftepp_preprocess so that it can actually be called recursively 2012-11-16 22:07:53 +01:00
Wolfgang (Blub) Bumiller
03f0e39f7f ftepp_out can now output to a string buffer 2012-11-16 22:06:07 +01:00
Wolfgang (Blub) Bumiller
b8a5c87360 Correctly handle nested #ifs 2012-11-16 22:02:38 +01:00
Wolfgang (Blub) Bumiller
5b91c2af5e Relax the preprocessor condition: # in the middle of a line also counts, but take care of builtin numbers since they use # as well 2012-11-16 21:37:34 +01:00
Wolfgang (Blub) Bumiller
7e660951c2 Fix a bug in macro call parameter parsing 2012-11-16 21:27:15 +01:00
Wolfgang (Blub) Bumiller
d688820518 Parsing parameters for a macro call 2012-11-16 21:20:31 +01:00
Wolfgang (Blub) Bumiller
a56c224f9c macro_body parse function shouldn't skip whitespace inside 2012-11-16 20:50:28 +01:00
Wolfgang (Blub) Bumiller
6c0b4a46fe moving ftepp_out further up, using it in ftepp_macro_call, generating output of parameter-less macros 2012-11-16 20:49:37 +01:00
Wolfgang (Blub) Bumiller
5f287fc476 ftepp_macro_call/ftepp_skipallwhite 2012-11-16 20:46:52 +01:00
Wolfgang (Blub) Bumiller
0bd0a430d6 Also allow empty-parameter-list macros 2012-11-16 20:41:20 +01:00
Wolfgang (Blub) Bumiller
c48b9dbf61 Parsing basic macro body, no special tokens yet 2012-11-16 20:38:44 +01:00
Wolfgang (Blub) Bumiller
52d7a5d7be Set the mergelines flag only for preprocessor commands 2012-11-16 20:32:03 +01:00
Wolfgang (Blub) Bumiller
053d8fb0e2 mergelines flag for the lexer to handle a backslash-newline 2012-11-16 20:29:20 +01:00
Wolfgang (Blub) Bumiller
d4fe6ed82d fixing up dtors, parsing parameters of macros 2012-11-16 20:15:04 +01:00
Wolfgang (Blub) Bumiller
34646cfca7 Update #if description comment 2012-11-16 20:04:30 +01:00
Wolfgang (Blub) Bumiller
45a354d664 Unary NOT in #if 2012-11-16 20:02:27 +01:00
Wolfgang (Blub) Bumiller
bdd8b8275e handling the noops flag better now 2012-11-16 19:32:02 +01:00
Wolfgang (Blub) Bumiller
6ab09ef3bf Parsing some basic #ifs with defined() 2012-11-16 19:28:20 +01:00
Wolfgang (Blub) Bumiller
bd5b2a8b58 Fixing indentation 2012-11-16 19:07:23 +01:00
Wolfgang (Blub) Bumiller
0c75182aab Some #if parsing 2012-11-16 19:01:44 +01:00
Wolfgang (Blub) Bumiller
0473fd84d1 using ftepp_out which will honor conditions 2012-11-16 18:29:46 +01:00
Wolfgang (Blub) Bumiller
cc1c197fc6 macro structure, parsing ifdefs and non-macro defines 2012-11-16 18:27:32 +01:00
Wolfgang (Blub) Bumiller
4bee1bdb6e Basic structure of ftepp 2012-11-16 17:46:16 +01:00
Wolfgang (Blub) Bumiller
07ca2e6407 importing initial ftepp.c; -E option now executes the preprocessor 2012-11-16 16:57:59 +01:00
Wolfgang (Blub) Bumiller
9d57cf2774 Removing old make rules for ir/ast tests in deleted test/ dir 2012-11-16 16:42:30 +01:00
Wolfgang (Blub) Bumiller
d1640f177f Free the 3 actual vectors, not the first 3 times 2012-11-15 21:40:32 +01:00
Wolfgang (Blub) Bumiller
4517072af4 Fixing util_memory_r 2012-11-15 21:36:36 +01:00
Wolfgang (Blub) Bumiller
3bd75546ec moving _vec_remove above the 'exposed interface' comment 2012-11-15 21:24:31 +01:00
Wolfgang (Blub) Bumiller
df61f3c182 Fix a typo causing NOTRACK to fail 2012-11-15 21:18:31 +01:00
Dale Weiler
fb30dd9a3f This bug was what caused mem.c to crash, dear lord 2012-11-15 20:04:05 +00:00
Wolfgang (Blub) Bumiller
c583ae24f2 Replacing lexer's vectors and getting rid of the macros 2012-11-15 18:48:38 +01:00
Wolfgang (Blub) Bumiller
906f319673 Replaced it all... 2012-11-15 18:32:09 +01:00
Wolfgang (Blub) Bumiller
b8fc2b7731 cleaned up empty lines 2012-11-15 11:02:16 +01:00
Dale Weiler
29336ef63d Some man page changes 2012-11-15 03:53:31 +00:00
Dale Weiler
0b8da9eeb4 Some more changes: added redirout/redirerr command line options 2012-11-15 03:38:20 +00:00
Dale Weiler
dcacaca2e8 added --nocolor and fixed bug 2012-11-15 00:50:05 +00:00
Dale Weiler
69408fd58d Remove test binary file 2012-11-15 00:29:05 +00:00
Dale Weiler
2e84cc0b41 Use new console system everywhere. 2012-11-15 00:28:46 +00:00
Dale Weiler
ac01e3b5d3 FIX TEH BLOCK 2012-11-14 20:41:15 +00:00
Wolfgang (Blub) Bumiller
84088cb5f0 Merging in new-syntax 2012-11-14 21:39:16 +01:00
Dale Weiler
18deba1a51 Remove the tput shit 2012-11-14 20:18:52 +00:00
Dale Weiler
f0678cfa5a Fix teh bugs, thanks div0 2012-11-14 19:38:05 +00:00
Dale Weiler
db7a1784d4 Clever hack to determine terminal color support for *nix. Uses zero libraries :) 2012-11-14 19:30:07 +00:00
Dale Weiler
f0750209b7 preliminary segregated console subsystem 2012-11-14 19:17:43 +00:00
Wolfgang (Blub) Bumiller
f3ebbf598f if not() support 2012-11-13 18:55:55 +01:00
Wolfgang (Blub) Bumiller
8f1f6160e3 'not' is now a keyword 2012-11-13 18:55:48 +01:00
Wolfgang (Blub) Bumiller
e7d558dbd8 if not() support 2012-11-13 18:54:25 +01:00
Wolfgang (Blub) Bumiller
6204c8c956 'not' is now a keyword 2012-11-13 18:51:45 +01:00
Wolfgang (Blub) Bumiller
51ba2c49d6 improve the warning 2012-11-13 14:46:14 +01:00
Wolfgang (Blub) Bumiller
b1175eabfc Warn (via -Wextensions) when accessing a field-of-array's element without putting the indexed field name in parenthesis 2012-11-13 14:43:20 +01:00
Dale Weiler
e1c8e54863 More buddy allocator changes 2012-11-13 02:29:02 +00:00
Wolfgang (Blub) Bumiller
b0326c66ed when finishing an array-indexing operation the parser now calls rotate_entfield_array_index_nodes to fixup 'ent.foo[n]' to become 'ent.(foo[n])' 2012-11-13 00:39:39 +01:00
Wolfgang (Blub) Bumiller
6044079528 Fix a very stupid bug in the executor which prevented ADDRESS to have the same global as output as one of its inputs 2012-11-13 00:36:00 +01:00
Dale Weiler
28a6d943d9 Some allocator changes (still doesn't work) 2012-11-12 23:24:14 +00:00
Wolfgang (Blub) Bumiller
b61ae53ecd fix wrong const qualifier 2012-11-13 00:11:07 +01:00
Wolfgang (Blub) Bumiller
d60a76abd1 allowing inexing of array-fields 2012-11-12 23:35:47 +01:00
Wolfgang (Blub) Bumiller
dbdcdb059e array-field setter needs to use STOREP* 2012-11-12 23:05:44 +01:00
Wolfgang (Blub) Bumiller
0340a6a6e7 support for ast_entfield nodes with specific output types, fixing array-field instantiating code to print the correct name on error 2012-11-12 22:39:43 +01:00
Wolfgang (Blub) Bumiller
0224de02d5 add an asterror message for ast_entfield_new with a wrong type 2012-11-12 22:33:34 +01:00
Wolfgang (Blub) Bumiller
89d86420ad entity-array-field-setter generation 2012-11-12 22:31:54 +01:00
Wolfgang (Blub) Bumiller
3579e495be code to instantiate field-array accessors 2012-11-12 22:24:11 +01:00
Wolfgang (Blub) Bumiller
0de1ebbc21 Preparing to generate accessors for field arrays 2012-11-12 22:16:18 +01:00
Wolfgang (Blub) Bumiller
f026ca2fc5 more factorizing and shortening of code 2012-11-12 21:12:25 +01:00
Wolfgang (Blub) Bumiller
c18c89cd62 shorten some code 2012-11-12 20:51:12 +01:00
Wolfgang (Blub) Bumiller
d959c71be6 genearting field arrays 2012-11-12 20:33:49 +01:00
Dale Weiler
baaa6407d5 More work on buddy allocator 2012-11-12 15:32:25 +00:00
Dale Weiler
01b619d53d JS stuff 2012-11-12 02:59:10 +00:00
Dale Weiler
66a503a900 working on a buddy allocator for gmqcc (initial code base) 2012-11-12 01:35:01 +00:00
Wolfgang (Blub) Bumiller
9a42dd1c3a qcvm -trace now shows the current function name and nest-depth 2012-11-11 23:57:42 +01:00
Wolfgang (Blub) Bumiller
83438d9833 call ir_function_finalize on array accessors otherwise they'll blow up stuff 2012-11-11 23:46:03 +01:00
Wolfgang (Blub) Bumiller
cdb7d06521 apply the typemask where previously forgotten 2012-11-11 23:39:40 +01:00
Wolfgang (Blub) Bumiller
fc6bd54943 show the function name for CALLs in disasm 2012-11-11 23:36:03 +01:00
Wolfgang (Blub) Bumiller
bde2175779 Generating function-local arrays 2012-11-11 23:31:57 +01:00
Wolfgang (Blub) Bumiller
a0b6008c2e fix an uninitialized value 2012-11-11 21:32:04 +01:00
Wolfgang (Blub) Bumiller
a78cdd5366 calling the array setter when required 2012-11-11 21:27:02 +01:00
Wolfgang (Blub) Bumiller
feec2d74ee Fix array-index codegen conditions 2012-11-11 19:02:50 +01:00
Wolfgang (Blub) Bumiller
22d6ff2309 Fixing lexer to not classify wrong tokens as operators 2012-11-11 18:57:02 +01:00
Wolfgang (Blub) Bumiller
511058c018 handling of op-[ 2012-11-11 18:54:08 +01:00
Wolfgang (Blub) Bumiller
d5b95f0412 Handling [ in the SYA 2012-11-11 18:45:43 +01:00
Wolfgang (Blub) Bumiller
2edc7ce822 index operator actually has 2 operands, not 0 2012-11-11 18:45:20 +01:00
Wolfgang (Blub) Bumiller
caf8946f99 lexer needs to fill the token for the index operator with actual content... 2012-11-11 18:31:37 +01:00
Wolfgang (Blub) Bumiller
2994d308a0 array index opening-paren can now return TOKEN_OPERATOR, partially handled in SYA 2012-11-11 16:43:16 +01:00
Wolfgang (Blub) Bumiller
533f9f2cfc SY_PAREN_ constants to replace magic numbers 2012-11-11 16:36:20 +01:00
Wolfgang (Blub) Bumiller
30d87ee837 get-accessor calling in ast_array_index_codegen 2012-11-11 16:32:59 +01:00
Wolfgang (Blub) Bumiller
1ab303c528 Store accessors in the ast_value for access from within the ast - generate accessors after generating all the globals to not mess up the order of globals in the output 2012-11-11 16:22:09 +01:00
Wolfgang (Blub) Bumiller
7d9568f806 array accessor function genaration 2012-11-11 16:06:27 +01:00
Wolfgang (Blub) Bumiller
9324a96f77 properly in all situations where an array is part of a function's return type 2012-11-11 14:17:48 +01:00
Wolfgang (Blub) Bumiller
86e42ad123 Don't allow arrays and other unsupported parameter types to be used in parameter lists 2012-11-11 14:08:02 +01:00
Wolfgang (Blub) Bumiller
df77e062dc Starting to add error messages for when using array types in expressions 2012-11-11 12:32:47 +01:00
Wolfgang (Blub) Bumiller
25ad091866 ast->ir for TYPE_ARRAY globals 2012-11-11 12:14:44 +01:00
Wolfgang (Blub) Bumiller
fb264b90b9 need to use ast_unref rather than ast_delete on the parsed array-size otherwise we end up deleting constants 2012-11-11 12:13:34 +01:00
Wolfgang (Blub) Bumiller
1fa67577e0 Removed -O3 from Makefile again 2012-11-11 11:52:05 +01:00
Wolfgang (Blub) Bumiller
a7d3a2d6ea adding opts_max_array_size with a default of 1024, adding some TODO errors for arrays in the AST 2012-11-11 11:09:36 +01:00
Wolfgang (Blub) Bumiller
62d062f860 for arrays, ast_value will contain several ir_values, ir_v will point to the [0] element 2012-11-11 10:51:40 +01:00
Wolfgang (Blub) Bumiller
a3c8605e18 Fixing execloop indentation 2012-11-11 10:40:31 +01:00
Wolfgang (Blub) Bumiller
cf1ea01de3 parser_compile_file vs parser_compile_string 2012-11-11 10:33:29 +01:00
Wolfgang (Blub) Bumiller
a84f9483e6 lex_open_string 2012-11-11 10:27:09 +01:00
Wolfgang (Blub) Bumiller
00a28e48ee parse arrays 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
2cb15e8c2d first parsing of [ - pushing temp changes 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
bc43c6de47 -fadjust-vector-fields is now on by default in -std=gmqcc 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
4977f605d4 array-subscript operator entries 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
1869440fd9 Preparing to parse arrays: adding TYPE_ARRAY and union/struct TYPE_ constants to be consistent with fteqcc, filled type-arrays with their data, attempting to parse an array variable and added some error messages to the IR in case of unhandled types 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
c87b056fdc Support non-const initialized locals 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
8687aa9a3e Shouldn't require a 'local' keyword for local fieldpointers 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
42b9848375 Locals of type .vector will now also properly generate all 3 locals 2012-11-11 10:13:01 +01:00
Wolfgang (Blub) Bumiller
a27750966f globals of type .vector will now properly generate 3 globals 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
52daf02444 Support in the AST for TYPE_FIELD globals which are no actual fields 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
fe05d5afd9 added 'var' to the keywords when not in -std=qcc, supporting 'var .float x;' in global-scope to declare a field-pointer variable without creating a field of that name 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
76b21ad192 -std=qcc now errors on C-style function syntax 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
0bb90f284e -std=qcc should error when the '=' is missing in a function declaration before the body 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
0fc3a0c517 Removing old commented-out parsing code 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
016257c44e Making the = in front of function bodies optional 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
b17fe4db0b Testcases for parameter shadowing 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
7f4047381e new-style syntax 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
e87fd30c48 Enable 'local-already-declared' check for locals even when they are functions - this was previously simply in the wrong 'if' 2012-11-11 10:13:00 +01:00
Wolfgang (Blub) Bumiller
8e30d7cb86 fixing a stupid typo - why doesn't any compiler warn about this crap 2012-11-11 10:12:45 +01:00
Dale Weiler
775f8ae005 Trash asm.c 2012-11-10 21:15:53 +00:00
Dale Weiler
6b12f4435c Make warns.def and flags.def into a single opts.def. 2012-11-10 21:13:09 +00:00
Dale Weiler
c155ef1582 Trash proposal, I'm not commited to this relationship anymore. Also I cannot afford a ring on this salary .. well I can, but you're a dumb bitch. 2012-11-10 21:05:46 +00:00
Dale Weiler
df07531298 Trash misinofmred README 2012-11-10 21:02:55 +00:00
Dale Weiler
793ab14b87 Trash data/ (reason: see last commit) 2012-11-10 20:59:58 +00:00
Dale Weiler
01bfdd2ae5 Dump old tests, test suite will take over .. It isn't activly used, just killing space and looking fugly. If required for reference, see older revisions. 2012-11-10 20:57:54 +00:00
Dale Weiler
852fa9d034 Merge branch 'master' of github.com:graphitemaster/gmqcc 2012-11-10 20:54:26 +00:00
Dale Weiler
9ad35a2817 Remove execloop.h, we still use xmacros, but it's done with #include __FILE__ trickery. Please do not kill me, it doesn't look that bad, conditional compilation is even used in eglibc like this :P 2012-11-10 20:53:37 +00:00
Wolfgang (Blub) Bumiller
b5ea787044 util_memory_r with byte=0 will now call util_memory_d and return NULL 2012-11-10 12:17:05 +01:00
Wolfgang (Blub) Bumiller
09e18e1bbf mem_r to realloc 2012-11-10 11:16:19 +01:00
Wolfgang (Blub) Bumiller
04fd3d04d9 the codegen has to use STORE_V for .vector, not STORE_FLD - contrary to the regular global-assignment, even fteqcc gets this right, so gmqcc should too 2012-11-09 20:11:17 +01:00
Wolfgang (Blub) Bumiller
9141217481 Merged parsing of variable and field declarations into 1 function 2012-11-09 19:10:27 +01:00
Wolfgang (Blub) Bumiller
68148dd0e8 Delete an explicit #define 2012-11-06 19:50:16 +01:00
Wolfgang (Blub) Bumiller
e143db0cae gcc lost it's magic analyzer and now complains about uninitialized stuff... <sadface> 2012-11-04 11:41:44 +01:00
Wolfgang (Blub) Bumiller
5ff0013357 error on more than 8 params for now since more need special treatment 2012-11-02 22:51:26 +01:00
Wolfgang (Blub) Bumiller
bf256abd66 Delete the test preprocess.c file and get the use/build part out of main.c/Makefile 2012-11-02 18:59:21 +01:00
Wolfgang (Blub) Bumiller
5bef2f2870 better test loop 2012-11-02 18:49:50 +01:00
Wolfgang (Blub) Bumiller
b5970707c0 Properly handle string and char constants when preprocessing: don't unescape and keep surrounding quotes 2012-11-02 18:48:32 +01:00
Wolfgang (Blub) Bumiller
b219d4b468 Changed the TOKEN_WHITE to contain the actual data - ie the comments 2012-11-02 18:39:32 +01:00
Wolfgang (Blub) Bumiller
caf4771ba1 Changed the preprocess test to reproduce the input file 2012-11-02 18:37:58 +01:00
Wolfgang (Blub) Bumiller
a3791b3f51 Finishing the preprocessing flag for the lexer, added preprocess.c to test it 2012-11-02 18:34:14 +01:00
Wolfgang (Blub) Bumiller
a195e296a9 -E switch to set opt_pp_only 2012-11-02 18:33:51 +01:00
Wolfgang (Blub) Bumiller
ab86b0470c preprocessing flag for the lexer 2012-11-02 18:33:51 +01:00
Wolfgang (Blub) Bumiller
2ef0203d17 Fix a minor bug in the lexer 2012-11-02 18:30:20 +01:00
Wolfgang (Blub) Bumiller
b1b586d398 -disasm should show builtins as builtins rather than trying to print negative statements - skip function 0 since it's not a valid function 2012-11-02 12:32:13 +01:00
Wolfgang (Blub) Bumiller
265e66b98b -disasm switch for qcvm 2012-11-02 12:23:55 +01:00
270 changed files with 32761 additions and 16078 deletions

15
.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
*.o
*.d
*.orig
*.rej
*.patch
*.diff
*.exe
gmqcc
gmqpak
qcvm
testsuite
build/
.idea/

13
AUTHORS
View file

@ -1,3 +1,10 @@
gmqcc brought to you by:
Dale Weiler
Wolfgang Bumiller
Authors:
Dale `graphitemaster` Weiler - Charismatic Visionary / Programmer
Wolfgang `Blub\w` Bumiller - Main Programmer
Thanks to:
Forest `LordHavoc` Hale - Technical support and assistance
Rudolf `divVerent` Polzer - Technical support and assistance
Matthias `matthiaskrgr` Krüger - Miscellaneous assistance
Samual `Samual` Lenks - Preprocessor assistance
Igor `ignatenkobrain` Gnatenko - Fedora packages

35
CMakeLists.txt Normal file
View file

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 2.8)
project(gmqcc)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
set(SOURCE_FILES
algo.h
ast.cpp ast.h
code.cpp
conout.cpp
fold.cpp fold.h
ftepp.cpp
gmqcc.h
intrin.cpp intrin.h
ir.cpp
ir.h
lexer.cpp lexer.h
opts.cpp
parser.cpp parser.h
stat.cpp
utf8.cpp
util.cpp)
add_library(gmqcclib ${SOURCE_FILES})
add_executable(gmqcc main.cpp)
target_link_libraries(gmqcc gmqcclib)
add_executable(testsuite test.cpp)
target_link_libraries(testsuite gmqcclib)
add_executable(qcvm exec.cpp)
target_link_libraries(qcvm gmqcclib)

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
Copyright (C) 2012, 2013, 2014, 2015
Dale Weiler
Wolfgang Bumiller
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

245
Makefile
View file

@ -1,63 +1,204 @@
CC ?= clang
CFLAGS += -Wall -I. -pedantic-errors
# Compilation options:
# * LTO - Link time optimization [default=0]
# * ASAN - Address sanitizer [default=0]
# * UBSAN - Undefined behavior sanitizer [default=0]
# * DEBUG - Debug build [default=0]
# * UNUSED - Remove unused references [default=1]
# * SRCDIR - Out of tree builds [default=./]
LTO ?= 0
ASAN ?= 0
UBSAN ?= 0
DEBUG ?= 0
UNUSED ?= 1
SRCDIR ?= ./
#turn on tons of warnings if clang is present
ifeq ($(CC), clang)
CFLAGS += \
-Weverything \
-Wno-missing-prototypes \
-Wno-unused-parameter \
-Wno-sign-compare \
-Wno-implicit-fallthrough \
-Wno-sign-conversion \
-Wno-conversion \
-Wno-disabled-macro-expansion \
-Wno-padded \
-Wno-format-nonliteral
endif
ifeq ($(track), no)
CFLAGS += -DNOTRACK
# Determine if we're building for Windows or not so we can set the right file
# extensions for the binaries and exclude the testsuite because it doesn't build
# for that platform.
ifeq ($(OS),Windows_NT)
GMQCC := gmqcc.exe
QCVM := qcvm.exe
else
GMQCC := gmqcc
QCVM := qcvm
TESTSUITE := testsuite
endif
OBJ = \
util.o \
code.o \
ast.o \
ir.o \
error.o
OBJ_A = test/ast-test.o
OBJ_I = test/ir-test.o
OBJ_C = main.o lexer.o parser.o
OBJ_X = exec-standalone.o util.o
# C++ compiler
CXX ?= clang++
#default is compiler only
default: gmqcc
%.o: %.c
$(CC) -c $< -o $@ $(CFLAGS)
# Build artifact directories
OBJDIR := .build/objs
DEPDIR := .build/deps
exec-standalone.o: exec.c
$(CC) -c $< -o $@ $(CFLAGS) -DQCVM_EXECUTOR=1
# Collect all the source files for GMQCC.
GSRCS := ast.cpp
GSRCS += code.cpp
GSRCS += conout.cpp
GSRCS += fold.cpp
GSRCS += ftepp.cpp
GSRCS += intrin.cpp
GSRCS += ir.cpp
GSRCS += lexer.cpp
GSRCS += main.cpp
GSRCS += opts.cpp
GSRCS += parser.cpp
GSRCS += stat.cpp
GSRCS += utf8.cpp
GSRCS += util.cpp
# test targets
test_ast: $(OBJ_A) $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
test_ir: $(OBJ_I) $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
qcvm: $(OBJ_X)
$(CC) -o $@ $^ $(CFLAGS) -lm
exec.o: execloop.h
exec-standalone.o: execloop.h
test: test_ast test_ir
# Collect all the source files for QCVM.
QSRCS := exec.cpp
QSRCS += stat.cpp
QSRCS += util.cpp
# compiler target
gmqcc: $(OBJ_C) $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
# Collect all the source files for TESTSUITE.
TSRCS := conout.cpp
TSRCS += opts.cpp
TSRCS += stat.cpp
TSRCS += test.cpp
TSRCS += util.cpp
#all target is test and all
all: test gmqcc
#
# Compilation flags
#
CXXFLAGS := -Wall
CXXFLAGS += -Wextra
CXXFLAGS += -Wno-parentheses
CXXFLAGS += -Wno-class-memaccess
CXXFLAGS += -Wno-implicit-fallthrough
CXXFLAGS += -std=c++11
# Disable some unneeded features.
CXXFLAGS += -fno-exceptions
CXXFLAGS += -fno-rtti
CXXFLAGS += -fno-asynchronous-unwind-tables
# Give each function and data it's own section so the linker can remove unused
# references to each, producing smaller, tighter binaries.
ifeq ($(UNUSED),1)
CXXFLAGS += -ffunction-sections
CXXFLAGS += -fdata-sections
endif
# Enable link-time optimizations if requested.
ifeq ($(LTO),1)
CXXFLAGS += -flto
endif
ifeq ($(DEBUG),1)
# Ensure there is a frame-pointer in debug builds.
CXXFLAGS += -fno-omit-frame-pointer
# Disable all optimizations in debug builds.
CXXFLAGS += -O0
# Enable debug symbols.
CXXFLAGS += -g
else
# Disable all the stack protection features in release builds.
CXXFLAGS += -fno-stack-protector
CXXFLAGS += -fno-stack-check
# Disable frame pointer in release builds when AddressSanitizer isn't present.
ifeq ($(ASAN),1)
CXXFLAGS += -fno-omit-frame-pointer
else
CXXFLAGS += -fomit-frame-pointer
endif
# Highest optimization flag in release builds.
CXXFLAGS += -O3
endif
# Sanitizer selection
ifeq ($(ASAN),1)
CXXFLAGS += -fsanitize=address
endif
ifeq ($(UBSAN),1)
CXXFLAGS += -fsanitize=undefined
endif
#
# Dependency flags
#
DEPFLAGS := -MMD
DEPFLAGS += -MP
#
# Linker flags
#
LDFLAGS :=
# Remove unreferenced sections
ifeq ($(UNUSED),1)
LDFLAGS += -Wl,--gc-sections
endif
# Enable link-time optimizations if request.
ifeq ($(LTO),1)
LDFLAGS += -flto
endif
# Sanitizer selection
ifeq ($(ASAN),1)
LDFLAGS += -fsanitize=address
endif
ifeq ($(UBSAN),1)
LDFLAGS += -fsanitize=undefined
endif
# Strip the binaries when not a debug build
ifneq (,$(findstring -g,$(CXXFLAGS)))
STRIP := true
else
STRIP := strip
endif
all: $(GMQCC) $(QCVM) $(TESTSUITE)
# Build artifact directories.
$(DEPDIR):
@mkdir -p $(DEPDIR)
$(OBJDIR):
@mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d | $(OBJDIR) $(DEPDIR)
$(CXX) -MT $@ $(DEPFLAGS) -MF $(DEPDIR)/$*.Td $(CXXFLAGS) -c -o $@ $<
@mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
$(GMQCC): $(filter %.o,$(GSRCS:%.cpp=$(OBJDIR)/%.o))
$(CXX) $^ $(LDFLAGS) -o $@
$(STRIP) $@
$(QCVM): $(filter %.o,$(QSRCS:%.cpp=$(OBJDIR)/%.o))
$(CXX) $^ $(LDFLAGS) -o $@
$(STRIP) $@
$(TESTSUITE): $(filter %.o,$(TSRCS:%.cpp=$(OBJDIR)/%.o))
$(CXX) $^ $(LDFLAGS) -o $@
$(STRIP) $@
# Determine if the tests should be run.
RUNTESTS := true
ifdef TESTSUITE
RUNTESTS := ./$(TESTSUITE)
endif
test: $(QCVM) $(TESTSUITE)
@$(RUNTESTS)
clean:
rm -f *.o gmqcc qcvm test_ast test_ir test/*.o
rm -rf $(DEPDIR) $(OBJDIR)
.PHONY: test clean $(DEPDIR) $(OBJDIR)
# Dependencies
$(filter %.d,$(GSRCS:%.cpp=$(DEPDIR)/%.d)):
include $(wildcard $@)
$(filter %.d,$(QSRCS:%.cpp=$(DEPDIR)/%.d)):
include $(wildcard $@)
$(filter %.d,$(TSRCS:%.cpp=$(DEPDIR)/%.d)):
include $(wildcard $@)

240
README
View file

@ -1,239 +1 @@
This is a work in progress Quake C compiler. There are very few good QC
compilers out there on the internet that can be used in the opensource
community. There are a lot of mediocre compilers, but no one wants those.
This is the solution for that, for once a proper Quake C compiler that is
capable of doing proper optimization.
The compiler is intended to implement modern day compiler design princibles
and support modifications through extensions that are provided for the
user through a low-level syntax specific-language inside the language itself
to implement language functionality.
The design goals of the compiler are very large, it's intended the compiler
supports a multitude of things, these things along with the status of
completeness is represented below in a table.
+-------------------+-----------------------------+------------------+
| Feature | What's it for? | Complete Factor |
+-------------------+-----------------------------+------------------+
. Lexical analysis . Tokenization . 90% .
.-------------------.-----------------------------.------------------.
. Tokenization . Parsing . 90% .
.-------------------.-----------------------------.------------------.
. Parsing / SYA . AST Generation . 09% .
.-------------------.-----------------------------.------------------.
. AST Generation . IR Generation . ??% .
.-------------------.-----------------------------.------------------.
. IR Generation . Code Generation . ??% .
.-------------------.-----------------------------.------------------.
. Code Generation . Binary Generation . ??% .
.-------------------.-----------------------------.------------------.
. Binary Generation . Binary . 100% .
+-------------------+-----------------------------+------------------+
Design tree:
The compiler is intended to work in the following order:
Lexical analysis ->
Tokenization ->
Parsing:
Operator precedence:
Shynting yard algorithm
Inline assembly:
Usage of the assembler subsystem:
top-down parsing and assemblation no optimization
Other parsing:
recrusive decent
->
Abstract syntax tree generation ->
Immediate representation (SSA):
Optimizations:
Constant propagation
Value range propogation
Sparse conditional constant propagation (possibly?)
Dead code elimination
Constant folding
Global value numbering
Partial redundancy elimination
Strength reduction
Common subexpression elimination
Peephole optimizations
Loop-invariant code motion
Inline expansion
Constant folding
Induction variable recognition and elimination
Dead store elimination
Jump threading
->
Code Generation:
Optimizations:
Rematerialization
Code Factoring
Recrusion Elimination
Loop unrolling
Deforestation
->
Binary Generation
File tree and explination:
gmqcc.h
This is the common header with all definitions, structures, and
constants for everything.
error.c
This is the error subsystem, this handles the output of good detailed
error messages (not currently, but will), with colors and such.
lex.c
This is the lexer, a very small basic step-seek lexer that can be easily
changed to add new tokens, very retargetable.
main.c
This is the core compiler entry, handles switches (will) to toggle on
and off certian compiler features.
parse.c
This is the parser which goes over all tokens and generates a parse tree
and check for syntax correctness.
typedef.c
This is the typedef system, this is a seperate file because it's a lot more
complicated than it sounds. This handles all typedefs, and even recrusive
typedefs.
util.c
These are utilities for the compiler, some things in here include a
allocator used for debugging, and some string functions.
assembler.c
This implements support for assembling Quake assembler (which doesn't
actually exist untill now: documentation of the Quake assembler is below.
This also implements (will) inline assembly for the C compiler.
README
This is the file you're currently reading
Makefile
The makefile, when sources are added you should add them to the SRC=
line otherwise the build will not pick it up. Trivial stuff, small
easy to manage makefile, no need to complicate it.
Some targets:
#make gmqcc
Builds gmqcc, creating a `gmqcc` binary file in the current
directory as the makefile.
#make test
Builds the ir and ast tests, creating a `test_ir` and `test_ast`
binary file in the current directory as the makefile.
#make test_ir
Builds the ir test, creating a `test_ir` binary file in the
current directory as the makefile.
#make test_ast
Builds the asr test, creating a `test_ast` binary file in the
current directory as the makefile.
#make clean
Cleans the build files left behind by a previous build, as
well as all the binary files.
#make all
Builds the tests and the compiler binary all in the current
directory of the makefile.
////////////////////////////////////////////////////////////////////////
///////////////////// Quake Assembler Documentation ////////////////////
////////////////////////////////////////////////////////////////////////
Quake assembler is quite simple: it's just an annotated version of the binary
produced by any existing QuakeC compiler, but made cleaner to use, (so that
the location of various globals or strings are not required to be known).
Constants:
Using one of the following valid constant typenames, you can declare
a constant {FLOAT,VECTOR,FUNCTION,FIELD,ENTITY}, all typenames are
proceeded by a colon, and the name (white space doesn't matter).
Examples:
FLOAT: foo 1
VECTOR: bar 1 2 1
STRING: hello "hello world"
Comments:
Commenting assembly requires the use of either # or ; on the line
that you'd like to be ignored by the assembler. You can only comment
blank lines, and not lines assembly already exists on.
Examples:
; this is allowed
# as is this
FLOAT: foo 1 ; this is not allowed
FLOAT: bar 2 # neither is this
Functions:
Creating functions is the same as declaring a constant, simply use
FUNCTION followed by a colon, and the name (white space doesn't matter)
and start the statements for that function on the line after it
Examples:
FLOAT: foo 1
FLOAT: bar 2
FUNCTION: test1
ADD foo, bar, OFS_RETURN
RETURN
FUNCTION: test2
CALL0 test1
DONE
Internal:
The Quake engine provides some internal functions such as print, to
access these you first must declare them and their names. To do this
you create a FUNCTION as you currently do. Adding a $ followed by the
number of the engine builtin (negated).
Examples:
FUNCTION: print $4
FUNCTION: error $3
Misc:
There are some rules as to what your identifiers can be for functions
and constants. All indentifiers mustn't begin with a numeric digit,
identifiers cannot include spaces, or tabs; they cannot contain symbols,
and they cannot exceed 32768 characters. Identifiers cannot be all
capitalized either, as all capatilized identifiers are reserved by the
assembler.
Numeric constants cannot contain special notation such as `1-e10`, all
numeric constants have to be numeric, they can contain decmial points
and signs (+, -) however.
Constants cannot be assigned values of other constants, their value must
be fully expressed inspot of the declartion.
No two identifiers can be the same name, this applies for variables allocated
inside a function scope (despite it being considered local).
There exists one other keyword that is considered sugar, and that
is AUTHOR, this keyword will allow you to speciy the AUTHOR(S) of
the assembly being assembled. The string represented for each usage
of AUTHOR is wrote to the end of the string table. Simaler to the
usage of constants and functions the AUTHOR keyword must be proceeded
by a colon.
Examples:
AUTHOR: "Dale Weiler"
AUTHOR: "Wolfgang Bumiller"
Colons exist for the sole reason of not having to use spaces after
keyword usage (however spaces are allowed). To understand the
following examples below are equivlent.
Example 1:
FLOAT:foo 1
Example 2:
FLOAT: foo 1
Example 3:
FLOAT: foo 2
variable amounts of whitespace is allowed anywhere (as it should be).
think of `:` as a delimiter (which is what it's used for during assembly).
////////////////////////////////////////////////////////////////////////
/////////////////////// Quake C Documentation //////////////////////////
////////////////////////////////////////////////////////////////////////
TODO ....
An improved QuakeC compiler

18
algo.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef GMQCC_ALGO_HDR
#define GMQCC_ALGO_HDR
namespace algo {
template<typename ITER>
void shiftback(ITER element, ITER end) {
//typename ITER::value_type backup(move(*element)); // hold the element
typename std::remove_reference<decltype(*element)>::type backup(move(*element)); // hold the element
ITER p = element++;
for (; element != end; p = element++)
*p = move(*element);
*p = move(backup);
}
} // ::algo
#endif

620
asm.c
View file

@ -1,620 +0,0 @@
/*
* Copyright (C) 2012
* Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "gmqcc.h"
/*
* Following parse states:
* ASM_FUNCTION -- in a function accepting input statements
* ....
*/
typedef enum {
ASM_NULL,
ASM_FUNCTION
} asm_state;
typedef struct {
char *name;
char type; /* type, float, vector, string, function*/
char elem; /* 0=x, 1=y, or 2=Z? */
int offset; /* location in globals */
bool isconst;
} asm_sym;
VECTOR_MAKE(asm_sym, asm_symbols);
/*
* Assembly text processing: this handles the internal collection
* of text to allow parsing and assemblation.
*/
static char* asm_getline(size_t *byte, FILE *fp) {
char *line = NULL;
size_t read = util_getline(&line, byte, fp);
*byte = read;
if (read == -1) {
mem_d (line);
return NULL;
}
return line;
}
/*
* Entire external interface for main.c - to perform actual assemblation
* of assembly files.
*/
void asm_init(const char *file, FILE **fp) {
*fp = fopen(file, "r");
code_init();
}
void asm_close(FILE *fp) {
fclose(fp);
code_write("program.dat");
}
void asm_clear() {
size_t i = 0;
for (; i < asm_symbols_elements; i++)
mem_d(asm_symbols_data[i].name);
mem_d(asm_symbols_data);
}
/*
* Dumps all values of all constants and assembly related
* information obtained during the assembly procedure.
*/
void asm_dumps() {
size_t i = 0;
for (; i < asm_symbols_elements; i++) {
asm_sym *g = &asm_symbols_data[i];
if (!g->isconst) continue;
switch (g->type) {
case TYPE_VECTOR: {
util_debug("ASM", "vector %s %c[%f]\n", g->name,
(g->elem == 0) ? 'X' :(
(g->elem == 1) ? 'Y' :
(g->elem == 2) ? 'Z' :' '),
INT2FLT(code_globals_data[g->offset])
);
break;
}
case TYPE_FUNCTION: {
util_debug("ASM", "function %s\n", g->name);
}
}
}
}
/*
* Parses a type, could be global or not depending on the
* assembly state: global scope with assignments are constants.
* globals with no assignments are globals. Function body types
* are locals.
*/
static GMQCC_INLINE bool asm_parse_type(const char *skip, size_t line, asm_state *state) {
if ((strstr(skip, "FLOAT:") != &skip[0]) &&
(strstr(skip, "VECTOR:") != &skip[0]) &&
(strstr(skip, "ENTITY:") != &skip[0]) &&
(strstr(skip, "FIELD:") != &skip[0]) &&
(strstr(skip, "STRING:") != &skip[0])) return false;
/* TODO: determine if constant, global, or local */
switch (*skip) {
/* VECTOR */ case 'V': {
float val1;
float val2;
float val3;
asm_sym sym;
char *find = (char*)skip + 7;
char *name = (char*)skip + 7;
while (*find == ' ' || *find == '\t') find++;
/* constant? */
if (strchr(find, ',')) {
/* strip name */
*strchr((name = util_strdup(find)), ',')='\0';
/* find data */
find += strlen(name) + 1;
while (*find == ' ' || *find == '\t') find++;
/* valid name */
if (util_strupper(name) || isdigit(*name)) {
printf("invalid name for vector variable\n");
mem_d(name);
}
/*
* Parse all three elements of the vector. This will only
* pass the first try if we hit a constant, otherwise it's
* a global.
*/
#define PARSE_ELEMENT(X,Y,Z) \
if (isdigit(*X) || *X == '-'||*X == '+') { \
bool negated = (*X == '-'); \
if (negated || *X == '+') { X++; } \
Y = (negated)?-atof(X):atof(X); \
X = strchr(X, ','); \
Z \
}
PARSE_ELEMENT(find, val1, { find ++; while (*find == ' ') { find ++; } });
PARSE_ELEMENT(find, val2, { find ++; while (*find == ' ') { find ++; } });
PARSE_ELEMENT(find, val3, { find ++; /* no need to do anything here */ });
#undef PARSE_ELEMENT
#define BUILD_ELEMENT(X,Y) \
sym.type = TYPE_VECTOR; \
sym.name = util_strdup(name); \
sym.elem = (X); \
sym.offset = code_globals_elements; \
asm_symbols_add(sym); \
code_globals_add(FLT2INT(Y))
BUILD_ELEMENT(0, val1);
BUILD_ELEMENT(1, val2);
BUILD_ELEMENT(2, val3);
#undef BUILD_ELEMENT
mem_d(name);
} else {
/* TODO global not constant */
}
break;
}
/* ENTITY */ case 'E': {
const char *find = skip + 7;
while (*find == ' ' || *find == '\t') find++;
printf("found ENTITY %s\n", find);
break;
}
/* STRING */ case 'S': {
const char *find = skip + 7;
while (*find == ' ' || *find == '\t') find++;
printf("found STRING %s\n", find);
break;
}
}
return false;
}
/*
* Parses a function: trivial case, handles occurances of duplicated
* names among other things. Ensures valid name as well, and even
* internal engine function selection.
*/
static GMQCC_INLINE bool asm_parse_func(const char *skip, size_t line, asm_state *state) {
if (*state == ASM_FUNCTION)
return false;
if (strstr(skip, "FUNCTION:") == &skip[0]) {
asm_sym sym;
char *look = util_strdup(skip+10);
char *copy = look;
char *name = NULL;
while (*copy == ' ' || *copy == '\t') copy++;
memset(&sym, 0, sizeof(asm_sym));
/*
* Chop the function name out of the string, this allocates
* a new string.
*/
name = util_strchp(copy, strchr(copy, '\0'));
/* TODO: failure system, missing name */
if (!name) {
printf("expected name on function\n");
mem_d(copy);
mem_d(name);
return false;
}
/* TODO: failure system, invalid name */
if (!isalpha(*name) || util_strupper(name)) {
printf("invalid identifer for function name\n");
mem_d(copy);
mem_d(name);
return false;
}
/*
* Function could be internal function, look for $
* to determine this.
*/
if (strchr(name, ',')) {
char *find = strchr(name, ',') + 1;
prog_section_function function;
prog_section_def def;
memset(&function, 0, sizeof(prog_section_function));
memset(&def, 0, sizeof(prog_section_def));
/* skip whitespace */
while (*find == ' ' || *find == '\t')
find++;
if (*find != '$') {
printf("expected $ for internal function selection, got %s instead\n", find);
mem_d(copy);
mem_d(name);
return false;
}
find ++;
if (!isdigit(*find)) {
printf("invalid internal identifier, expected valid number\n");
mem_d(copy);
mem_d(name);
return false;
}
*strchr(name, ',')='\0';
/*
* Now add the following items to the code system:
* function
* definition (optional)
* global (optional)
* name
*/
function.entry = -atoi(find);
function.firstlocal = 0;
function.locals = 0;
function.profile = 0;
function.name = code_chars_elements;
function.file = 0;
function.nargs = 0;
def.type = TYPE_FUNCTION;
def.offset = code_globals_elements;
def.name = code_chars_elements;
code_functions_add(function);
code_defs_add (def);
code_chars_put (name, strlen(name));
code_chars_add ('\0');
sym.type = TYPE_FUNCTION;
sym.name = util_strdup(name);
sym.offset = function.entry;
asm_symbols_add(sym);
util_debug("ASM", "added internal function %s to function table\n", name);
/*
* Sanatize the numerical constant used to select the
* internal function. Must ensure it's all numeric, since
* atoi can silently drop characters from a string and still
* produce a valid constant that would lead to runtime problems.
*/
if (util_strdigit(find))
util_debug("ASM", "found internal function %s, -%d\n", name, atoi(find));
else
printf("invalid internal function identifier, must be all numeric\n");
} else {
/*
* The function isn't an internal one. Determine the name and
* amount of arguments the function accepts by searching for
* the `#` (pound sign).
*/
int args = 0;
int size = 0;
char *find = strchr(name, '#');
char *peek = find;
/*
* Code structures for filling after determining the correct
* information to add to the code write system.
*/
prog_section_function function;
prog_section_def def;
memset(&function, 0, sizeof(prog_section_function));
memset(&def, 0, sizeof(prog_section_def));
if (find) {
find ++;
/* skip whitespace */
if (*find == ' ' || *find == '\t')
find++;
/*
* If the input is larger than eight, it's considered
* invalid and shouldn't be allowed. The QuakeC VM only
* allows a maximum of eight arguments.
*/
if (*find == '9') {
printf("invalid number of arguments, must be a valid number from 0-8\n");
mem_d(copy);
mem_d(name);
return false;
}
if (*find != '0') {
/*
* if we made it this far we have a valid number for the
* argument count, so fall through a switch statement and
* do it.
*/
switch (*find) {
case '8': args++; case '7': args++;
case '6': args++; case '5': args++;
case '4': args++; case '3': args++;
case '2': args++; case '1': args++;
}
}
/*
* We need to parse the argument size now by determining
* the argument identifer list used after the amount of
* arguments.
*/
memset(function.argsize, 0, sizeof(function.argsize));
find ++; /* skip the number */
while (*find == ' ' || *find == '\t') find++;
while (size < args) {
switch (*find) {
case 'V': case 'v': function.argsize[size]=3; break;
case 'S': case 's':
case 'F': case 'f':
case 'E': case 'e': function.argsize[size]=1; break;
case '\0':
printf("missing argument identifer, expected %d\n", args);
return false;
default:
printf("error invalid function argument identifier\n");
return false;
}
size++,find++;
}
while (*find == ' ' || *find == '\t') find++;
if (*find != '\0') {
printf("too many function argument identifers expected %d\n", args);
return false;
}
} else {
printf("missing number of argument count in function %s\n", name);
return false;
}
/*
* Now we need to strip the name apart into it's exact size
* by working in the peek buffer till we hit the name again.
*/
if (*peek == '#') {
peek --; /* '#' */
peek --; /* number */
}
while (*peek == ' ' || *peek == '\t') peek--;
/*
* We're guranteed to be exactly where we need to be in the
* peek buffer to null terminate and get our name from name
* without any garbage before or after it.
*/
*++peek='\0';
/*
* We got valid function structure information now. Lets add
* the function to the code writer function table.
*/
function.entry = code_statements_elements;
function.firstlocal = 0;
function.locals = 0;
function.profile = 0;
function.name = code_chars_elements;
function.file = 0;
function.nargs = args;
def.type = TYPE_FUNCTION;
def.offset = code_globals_elements;
def.name = code_chars_elements;
code_functions_add(function);
code_globals_add (code_statements_elements);
code_chars_put (name, strlen(name));
code_chars_add ('\0');
sym.type = TYPE_FUNCTION;
sym.name = util_strdup(name);
sym.offset = function.entry;
asm_symbols_add(sym);
/* update assembly state */
*state = ASM_FUNCTION;
util_debug("ASM", "added context function %s to function table\n", name);
}
mem_d(copy);
mem_d(name);
return true;
}
return false;
}
static GMQCC_INLINE bool asm_parse_stmt(const char *skip, size_t line, asm_state *state) {
/*
* This parses a valid statement in assembly and adds it to the code
* table to be wrote. This needs to handle correct checking of all
* statements to ensure the correct amount of operands are passed to
* the menomic. This must also check for valid function calls (ensure
* the names selected exist in the program scope) and ensure the correct
* CALL* is used (depending on the amount of arguments the function
* is expected to take)
*/
enum {
EXPECT_FUNCTION = 1,
EXPECT_VARIABLE = 2,
EXPECT_VALUE = 3
};
char *c = (char*)skip;
size_t i = 0;
char expect = 0;
prog_section_statement s;
memset(&s, 0, sizeof(prog_section_statement));
/*
* statements are only allowed when inside a function body
* otherwise the assembly is invalid.
*/
if (*state != ASM_FUNCTION)
return false;
/*
* Skip any possible whitespace, it's not wanted we're searching
* for an instruction. TODO: recrusive decent parser skip on line
* entry instead of pre-op.
*/
while (*skip == ' ' || *skip == '\t')
skip++;
for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
/*
* Iterate all possible instructions and check if the selected
* instructure in the input stream `skip` is actually a valid
* instruction.
*/
if (!strncmp(skip, asm_instr[i].m, asm_instr[i].l)) {
/*
* We hit the end of a function scope, retarget the state
* and add a DONE statement to the statment table.
*/
if (i == AINSTR_END) {
s.opcode = i;
code_statements_add(s);
*state = ASM_NULL;
return true;
}
/*
* Check the instruction type to see what sort of data
* it's expected to have.
*/
if (i >= INSTR_CALL0 && i <= INSTR_CALL8)
expect = EXPECT_FUNCTION;
else
expect = EXPECT_VARIABLE;
util_debug(
"ASM",
"found statement %s expecting: `%s` (%ld operand(s))\n",
asm_instr[i].m,
(expect == EXPECT_FUNCTION)?"function name":(
(expect == EXPECT_VARIABLE)?"variable name":(
(expect == EXPECT_VALUE ?"value" : "unknown"))),
asm_instr[i].o
);
/*
* Parse the operands for `i` (the instruction). The order
* of asm_instr is in the order of the menomic encoding so
* `i` == menomic encoding.
*/
s.opcode = i;
switch (asm_instr[i].o) {
/*
* Each instruction can have from 0-3 operands; and can
* be used with less or more operands depending on it's
* selected use.
*
* DONE for example can use either 0 operands, or 1 (to
* emulate the effect of RETURN)
*
* TODO: parse operands correctly figure out what it is
* that the assembly is trying to do, i.e string table
* lookup, function calls etc.
*
* This needs to have a fall state, we start from the
* end of the string and work backwards.
*/
#define OPEATS(X,Y) X##Y
#define OPCCAT(X,Y) OPEATS(X,Y)
#define OPLOAD(X,Y) \
do { \
util_debug("ASM", "loading operand data ...\n"); \
if (expect == EXPECT_VARIABLE) { \
size_t f=0; \
for (; f<asm_symbols_elements; f++) { \
if (!strncmp(asm_symbols_data[f].name, (Y), strlen(Y)) && \
asm_symbols_data[f].type != TYPE_FUNCTION) { \
(X)=asm_symbols_data[f].offset; \
goto OPCCAT(foundv, __LINE__); \
} \
} \
printf("no variable named %s\n", (Y)); \
break; \
OPCCAT(foundv,__LINE__) : \
printf("operand loaded for %s\n", (Y)); \
} else if (expect == EXPECT_FUNCTION) { \
/* \
* It's a function call not a variable association with an instruction \
* these are harder to handle. \
*/ \
size_t f=0; \
if (strchr(Y, ' ')) { \
*strchr(Y, ' ')='\0'; \
} \
for (; f<asm_symbols_elements; f++) { \
if (!strncmp(asm_symbols_data[f].name, (Y), strlen(Y)) && \
asm_symbols_data[f].type == TYPE_FUNCTION) { \
(X)=asm_symbols_data[f].offset; \
goto OPCCAT(foundf, __LINE__); \
} \
} \
printf("no function named [%s]\n", (Y)); \
break; \
OPCCAT(foundf,__LINE__) : \
printf("operand loaded for [%s]\n", (Y)); \
} \
} while (0)
case 3: { OPLOAD(s.o3.s1,c); break; }
case 2: { OPLOAD(s.o2.s1,c); break; }
case 1: {
while (*c == ' ' || *c == '\t') c++;
c += asm_instr[i].l;
while (*c == ' ' || *c == '\t') c++;
OPLOAD(s.o1.s1, c);
break;
}
#undef OPLOAD
#undef OPCCAT
}
/* add the statement now */
code_statements_add(s);
}
}
return true;
}
void asm_parse(FILE *fp) {
char *data = NULL;
long line = 1; /* current line */
size_t size = 0; /* size of line */
asm_state state = ASM_NULL;
#define asm_end(x) \
do { \
mem_d(data); \
line ++; \
util_debug("ASM", x); \
} while (0); continue
while ((data = asm_getline (&size, fp)) != NULL) {
char *copy = data;
char *skip = copy;
while (*copy == ' ' || *copy == '\t') copy++;
while (*skip != '\n') skip++;
*skip='\0';
if (asm_parse_type(copy, line, &state)){ asm_end("asm_parse_type\n"); }
if (asm_parse_func(copy, line, &state)){ asm_end("asm_parse_func\n"); }
if (asm_parse_stmt(copy, line, &state)){ asm_end("asm_parse_stmt\n"); }
asm_end("asm_parse_white\n");
}
#undef asm_end
asm_dumps();
asm_clear();
}

1897
ast.c

File diff suppressed because it is too large Load diff

3125
ast.cpp Normal file

File diff suppressed because it is too large Load diff

868
ast.h

File diff suppressed because it is too large Load diff

291
code.c
View file

@ -1,291 +0,0 @@
/*
* Copyright (C) 2012
* Dale Weiler, Wolfgang Bumiller
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "gmqcc.h"
/*
* The macros below expand to a typesafe vector implementation, which
* can be viewed in gmqcc.h
*
* code_statements_data -- raw prog_section_statement array
* code_statements_elements -- number of elements
* code_statements_allocated -- size of the array allocated
* code_statements_add(T) -- add element (returns -1 on error)
*
* code_vars_data -- raw prog_section_var array
* code_vars_elements -- number of elements
* code_vars_allocated -- size of the array allocated
* code_vars_add(T) -- add element (returns -1 on error)
*
* code_fields_data -- raw prog_section_field array
* code_fields_elements -- number of elements
* code_fields_allocated -- size of the array allocated
* code_fields_add(T) -- add element (returns -1 on error)
*
* code_functions_data -- raw prog_section_function array
* code_functions_elements -- number of elements
* code_functions_allocated -- size of the array allocated
* code_functions_add(T) -- add element (returns -1 on error)
*
* code_globals_data -- raw prog_section_def array
* code_globals_elements -- number of elements
* code_globals_allocated -- size of the array allocated
* code_globals_add(T) -- add element (returns -1 on error)
*
* code_chars_data -- raw char* array
* code_chars_elements -- number of elements
* code_chars_allocated -- size of the array allocated
* code_chars_add(T) -- add element (returns -1 on error)
*/
VECTOR_MAKE(prog_section_statement, code_statements);
VECTOR_MAKE(prog_section_def, code_defs );
VECTOR_MAKE(prog_section_field, code_fields );
VECTOR_MAKE(prog_section_function, code_functions );
VECTOR_MAKE(int, code_globals );
VECTOR_MAKE(char, code_chars );
uint16_t code_crc;
uint32_t code_entfields;
void code_init() {
prog_section_function empty_function = {0,0,0,0,0,0,0,{0}};
prog_section_statement empty_statement = {0,{0},{0},{0}};
prog_section_def empty_def = {0, 0, 0};
int i = 0;
code_entfields = 0;
/* omit creation of null code */
if (OPTS_FLAG(OMIT_NULL_BYTES))
return;
/*
* The way progs.dat is suppose to work is odd, there needs to be
* some null (empty) statements, functions, and 28 globals
*/
for(; i < 28; i++)
code_globals_add(0);
code_chars_add ('\0');
code_functions_add (empty_function);
code_statements_add(empty_statement);
code_defs_add (empty_def);
code_fields_add (empty_def);
}
uint32_t code_genstring(const char *str)
{
uint32_t off = code_chars_elements;
while (*str) {
code_chars_add(*str);
++str;
}
code_chars_add(0);
return off;
}
uint32_t code_cachedstring(const char *str)
{
size_t s = 0;
/* We could implement knuth-morris-pratt or something
* and also take substrings, but I'm uncomfortable with
* pointing to subparts of strings for the sake of clarity...
*/
while (s < code_chars_elements) {
if (!strcmp(str, code_chars_data + s))
return s;
while (code_chars_data[s]) ++s;
++s;
}
return code_genstring(str);
}
void code_test() {
prog_section_def d1 = { TYPE_VOID, 28, 1 };
prog_section_def d2 = { TYPE_FUNCTION, 29, 8 };
prog_section_def d3 = { TYPE_STRING, 30, 14};
prog_section_function f1 = { 1, 0, 0, 0, 1, 0,0, {0}};
prog_section_function f2 = {-4, 0, 0, 0, 8, 0,0, {0}};
prog_section_function f3 = { 0, 0, 0, 0, 14+13, 0,0, {0}};
prog_section_function f4 = { 0, 0, 0, 0, 14+13+10, 0,0, {0}};
prog_section_function f5 = { 0, 0, 0, 0, 14+13+10+7, 0,0, {0}};
prog_section_function f6 = { 0, 0, 0, 0, 14+13+10+7+9, 0,0, {0}};
prog_section_statement s1 = { INSTR_STORE_F, {30}, {OFS_PARM0}, {0}};
prog_section_statement s2 = { INSTR_CALL1, {29}, {0}, {0}};
prog_section_statement s3 = { INSTR_RETURN, {0}, {0}, {0}};
code_chars_put("m_init", 0x6);
code_chars_put("print", 0x5);
code_chars_put("hello world\n", 0xC);
code_chars_put("m_keydown", 0x9);
code_chars_put("m_draw", 0x6);
code_chars_put("m_toggle", 0x8);
code_chars_put("m_shutdown", 0xA);
code_globals_add(1); /* m_init */
code_globals_add(2); /* print */
code_globals_add(14); /* hello world in string table */
/* now the defs */
code_defs_add (d1); /* m_init */
code_defs_add (d2); /* print */
code_defs_add (d3); /*hello_world*/
code_functions_add (f1); /* m_init */
code_functions_add (f2); /* print */
code_functions_add (f3); /* m_keydown */
code_functions_add (f4);
code_functions_add (f5);
code_functions_add (f6);
code_statements_add(s1);
code_statements_add(s2);
code_statements_add(s3);
}
qcint code_alloc_field (size_t qcsize)
{
qcint pos = (qcint)code_entfields;
code_entfields += qcsize;
return pos;
}
bool code_write(const char *filename) {
prog_header code_header;
FILE *fp = NULL;
size_t it = 2;
/* see proposal.txt */
if (OPTS_FLAG(OMIT_NULL_BYTES)) {}
code_header.statements.offset = sizeof(prog_header);
code_header.statements.length = code_statements_elements;
code_header.defs.offset = code_header.statements.offset + (sizeof(prog_section_statement) * code_statements_elements);
code_header.defs.length = code_defs_elements;
code_header.fields.offset = code_header.defs.offset + (sizeof(prog_section_def) * code_defs_elements);
code_header.fields.length = code_fields_elements;
code_header.functions.offset = code_header.fields.offset + (sizeof(prog_section_field) * code_fields_elements);
code_header.functions.length = code_functions_elements;
code_header.globals.offset = code_header.functions.offset + (sizeof(prog_section_function) * code_functions_elements);
code_header.globals.length = code_globals_elements;
code_header.strings.offset = code_header.globals.offset + (sizeof(int32_t) * code_globals_elements);
code_header.strings.length = code_chars_elements;
code_header.version = 6;
if (opts_forcecrc)
code_header.crc16 = opts_forced_crc;
else
code_header.crc16 = code_crc;
code_header.entfield = code_entfields;
if (OPTS_FLAG(DARKPLACES_STRING_TABLE_BUG)) {
util_debug("GEN", "Patching stringtable for -fdarkplaces-stringtablebug\n");
/* >= + P */
code_chars_add('\0'); /* > */
code_chars_add('\0'); /* = */
code_chars_add('\0'); /* P */
}
/* ensure all data is in LE format */
util_endianswap(&code_header, 1, sizeof(prog_header));
util_endianswap(code_statements_data, code_statements_elements, sizeof(prog_section_statement));
util_endianswap(code_defs_data, code_defs_elements, sizeof(prog_section_def));
util_endianswap(code_fields_data, code_fields_elements, sizeof(prog_section_field));
util_endianswap(code_functions_data, code_functions_elements, sizeof(prog_section_function));
util_endianswap(code_globals_data, code_globals_elements, sizeof(int32_t));
fp = util_fopen(filename, "wb");
if (!fp)
return false;
if (1 != fwrite(&code_header, sizeof(prog_header), 1, fp) ||
code_statements_elements != fwrite(code_statements_data, sizeof(prog_section_statement), code_statements_elements, fp) ||
code_defs_elements != fwrite(code_defs_data, sizeof(prog_section_def) , code_defs_elements , fp) ||
code_fields_elements != fwrite(code_fields_data, sizeof(prog_section_field) , code_fields_elements , fp) ||
code_functions_elements != fwrite(code_functions_data, sizeof(prog_section_function) , code_functions_elements , fp) ||
code_globals_elements != fwrite(code_globals_data, sizeof(int32_t) , code_globals_elements , fp) ||
code_chars_elements != fwrite(code_chars_data, 1 , code_chars_elements , fp))
{
fclose(fp);
return false;
}
util_debug("GEN","HEADER:\n");
util_debug("GEN"," version: = %d\n", code_header.version );
util_debug("GEN"," crc16: = %d\n", code_header.crc16 );
util_debug("GEN"," entfield: = %d\n", code_header.entfield);
util_debug("GEN"," statements = {.offset = % 8d, .length = % 8d}\n", code_header.statements.offset, code_header.statements.length);
util_debug("GEN"," defs = {.offset = % 8d, .length = % 8d}\n", code_header.defs .offset, code_header.defs .length);
util_debug("GEN"," fields = {.offset = % 8d, .length = % 8d}\n", code_header.fields .offset, code_header.fields .length);
util_debug("GEN"," functions = {.offset = % 8d, .length = % 8d}\n", code_header.functions .offset, code_header.functions .length);
util_debug("GEN"," globals = {.offset = % 8d, .length = % 8d}\n", code_header.globals .offset, code_header.globals .length);
util_debug("GEN"," strings = {.offset = % 8d, .length = % 8d}\n", code_header.strings .offset, code_header.strings .length);
/* FUNCTIONS */
util_debug("GEN", "FUNCTIONS:\n");
for (; it < code_functions_elements; it++) {
size_t j = code_functions_data[it].entry;
util_debug("GEN", " {.entry =% 5d, .firstlocal =% 5d, .locals =% 5d, .profile =% 5d, .name =% 5d, .file =% 5d, .nargs =% 5d, .argsize ={%d,%d,%d,%d,%d,%d,%d,%d} }\n",
code_functions_data[it].entry,
code_functions_data[it].firstlocal,
code_functions_data[it].locals,
code_functions_data[it].profile,
code_functions_data[it].name,
code_functions_data[it].file,
code_functions_data[it].nargs,
code_functions_data[it].argsize[0],
code_functions_data[it].argsize[1],
code_functions_data[it].argsize[2],
code_functions_data[it].argsize[3],
code_functions_data[it].argsize[4],
code_functions_data[it].argsize[5],
code_functions_data[it].argsize[6],
code_functions_data[it].argsize[7]
);
util_debug("GEN", " NAME: %s\n", &code_chars_data[code_functions_data[it].name]);
/* Internal functions have no code */
if (code_functions_data[it].entry >= 0) {
util_debug("GEN", " CODE:\n");
for (;;) {
if (code_statements_data[j].opcode != AINSTR_END)
util_debug("GEN", " %-12s {% 5i,% 5i,% 5i}\n",
asm_instr[code_statements_data[j].opcode].m,
code_statements_data[j].o1.s1,
code_statements_data[j].o2.s1,
code_statements_data[j].o3.s1
);
else {
util_debug("GEN", " DONE {0x00000,0x00000,0x00000}\n");
break;
}
j++;
}
}
}
mem_d(code_statements_data);
mem_d(code_defs_data);
mem_d(code_fields_data);
mem_d(code_functions_data);
mem_d(code_globals_data);
mem_d(code_chars_data);
fclose(fp);
return true;
}

348
code.cpp Normal file
View file

@ -0,0 +1,348 @@
#include <string.h>
#include "gmqcc.h"
/*
* We could use the old method of casting to uintptr_t then to void*
* or qcint_t; however, it's incredibly unsafe for two reasons.
* 1) The compilers aliasing optimization can legally make it unstable
* (it's undefined behaviour).
*
* 2) The cast itself depends on fresh storage (newly allocated in which
* ever function is using the cast macros), the contents of which are
* transferred in a way that the obligation to release storage is not
* propagated.
*/
typedef union {
void *enter;
qcint_t leave;
} code_hash_entry_t;
/* Some sanity macros */
#define CODE_HASH_ENTER(ENTRY) ((ENTRY).enter)
#define CODE_HASH_LEAVE(ENTRY) ((ENTRY).leave)
void code_push_statement(code_t *code, prog_section_statement_t *stmt_in, lex_ctx_t ctx)
{
prog_section_statement_t stmt = *stmt_in;
if (OPTS_FLAG(TYPELESS_STORES)) {
switch (stmt.opcode) {
case INSTR_LOAD_S:
case INSTR_LOAD_ENT:
case INSTR_LOAD_FLD:
case INSTR_LOAD_FNC:
stmt.opcode = INSTR_LOAD_F;
break;
case INSTR_STORE_S:
case INSTR_STORE_ENT:
case INSTR_STORE_FLD:
case INSTR_STORE_FNC:
stmt.opcode = INSTR_STORE_F;
break;
case INSTR_STOREP_S:
case INSTR_STOREP_ENT:
case INSTR_STOREP_FLD:
case INSTR_STOREP_FNC:
stmt.opcode = INSTR_STOREP_F;
break;
}
}
if (OPTS_FLAG(SORT_OPERANDS)) {
uint16_t pair;
switch (stmt.opcode) {
case INSTR_MUL_F:
case INSTR_MUL_V:
case INSTR_ADD_F:
case INSTR_EQ_F:
case INSTR_EQ_S:
case INSTR_EQ_E:
case INSTR_EQ_FNC:
case INSTR_NE_F:
case INSTR_NE_V:
case INSTR_NE_S:
case INSTR_NE_E:
case INSTR_NE_FNC:
case INSTR_AND:
case INSTR_OR:
case INSTR_BITAND:
case INSTR_BITOR:
if (stmt.o1.u1 < stmt.o2.u1) {
uint16_t a = stmt.o2.u1;
stmt.o1.u1 = stmt.o2.u1;
stmt.o2.u1 = a;
}
break;
case INSTR_MUL_VF: pair = INSTR_MUL_FV; goto case_pair_gen;
case INSTR_MUL_FV: pair = INSTR_MUL_VF; goto case_pair_gen;
case INSTR_LT: pair = INSTR_GT; goto case_pair_gen;
case INSTR_GT: pair = INSTR_LT; goto case_pair_gen;
case INSTR_LE: pair = INSTR_GE; goto case_pair_gen;
case INSTR_GE: pair = INSTR_LE;
case_pair_gen:
if (stmt.o1.u1 < stmt.o2.u1) {
uint16_t x = stmt.o1.u1;
stmt.o1.u1 = stmt.o2.u1;
stmt.o2.u1 = x;
stmt.opcode = pair;
}
break;
}
}
code->statements.push_back(stmt);
code->linenums.push_back(ctx.line);
code->columnnums.push_back(ctx.column);
}
void code_pop_statement(code_t *code)
{
code->statements.pop_back();
code->linenums.pop_back();
code->columnnums.pop_back();
}
void *code_t::operator new(std::size_t bytes) {
return mem_a(bytes);
}
void code_t::operator delete(void *ptr) {
mem_d(ptr);
}
code_t::code_t()
{
static lex_ctx_t empty_ctx = {0, 0, 0};
static prog_section_function_t empty_function = {0,0,0,0,0,0,0,{0,0,0,0,0,0,0,0}};
static prog_section_statement_t empty_statement = {0,{0},{0},{0}};
static prog_section_def_t empty_def = {0, 0, 0};
string_cache = util_htnew(OPTS_OPTIMIZATION(OPTIM_OVERLAP_STRINGS) ? 0x100 : 1024);
// The way progs.dat is suppose to work is odd, there needs to be
// some null (empty) statements, functions, and 28 globals
globals.insert(globals.begin(), 28, 0);
chars.push_back('\0');
functions.push_back(empty_function);
code_push_statement(this, &empty_statement, empty_ctx);
defs.push_back(empty_def);
fields.push_back(empty_def);
}
code_t::~code_t()
{
util_htdel(string_cache);
}
void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin);
uint32_t code_genstring(code_t *code, const char *str) {
size_t hash;
code_hash_entry_t existing;
if (!str)
return 0;
if (!*str) {
if (!code->string_cached_empty) {
code->string_cached_empty = code->chars.size();
code->chars.push_back(0);
}
return code->string_cached_empty;
}
if (OPTS_OPTIMIZATION(OPTIM_OVERLAP_STRINGS)) {
hash = ((unsigned char*)str)[strlen(str)-1];
CODE_HASH_ENTER(existing) = code_util_str_htgeth(code->string_cache, str, hash);
} else {
hash = util_hthash(code->string_cache, str);
CODE_HASH_ENTER(existing) = util_htgeth(code->string_cache, str, hash);
}
if (CODE_HASH_ENTER(existing))
return CODE_HASH_LEAVE(existing);
CODE_HASH_LEAVE(existing) = code->chars.size();
code->chars.insert(code->chars.end(), str, str + strlen(str) + 1);
util_htseth(code->string_cache, str, hash, CODE_HASH_ENTER(existing));
return CODE_HASH_LEAVE(existing);
}
qcint_t code_alloc_field (code_t *code, size_t qcsize)
{
qcint_t pos = (qcint_t)code->entfields;
code->entfields += qcsize;
return pos;
}
static size_t code_size_generic(code_t *code, prog_header_t *code_header, bool lno) {
size_t size = 0;
if (lno) {
size += 4; /* LNOF */
size += sizeof(uint32_t); /* version */
size += sizeof(code_header->defs.length);
size += sizeof(code_header->globals.length);
size += sizeof(code_header->fields.length);
size += sizeof(code_header->statements.length);
size += sizeof(code->linenums[0]) * code->linenums.size();
size += sizeof(code->columnnums[0]) * code->columnnums.size();
} else {
size += sizeof(prog_header_t);
size += sizeof(prog_section_statement_t) * code->statements.size();
size += sizeof(prog_section_def_t) * code->defs.size();
size += sizeof(prog_section_field_t) * code->fields.size();
size += sizeof(prog_section_function_t) * code->functions.size();
size += sizeof(int32_t) * code->globals.size();
size += 1 * code->chars.size();
}
return size;
}
#define code_size_binary(C, H) code_size_generic((C), (H), false)
#define code_size_debug(C, H) code_size_generic((C), (H), true)
static void code_create_header(code_t *code, prog_header_t *code_header, const char *filename, const char *lnofile) {
size_t i;
code_header->statements.offset = sizeof(prog_header_t);
code_header->statements.length = code->statements.size();
code_header->defs.offset = code_header->statements.offset + (sizeof(prog_section_statement_t) * code->statements.size());
code_header->defs.length = code->defs.size();
code_header->fields.offset = code_header->defs.offset + (sizeof(prog_section_def_t) * code->defs.size());
code_header->fields.length = code->fields.size();
code_header->functions.offset = code_header->fields.offset + (sizeof(prog_section_field_t) * code->fields.size());
code_header->functions.length = code->functions.size();
code_header->globals.offset = code_header->functions.offset + (sizeof(prog_section_function_t) * code->functions.size());
code_header->globals.length = code->globals.size();
code_header->strings.offset = code_header->globals.offset + (sizeof(int32_t) * code->globals.size());
code_header->strings.length = code->chars.size();
code_header->version = 6;
code_header->skip = 0;
if (OPTS_OPTION_BOOL(OPTION_FORCECRC))
code_header->crc16 = OPTS_OPTION_U16(OPTION_FORCED_CRC);
else
code_header->crc16 = code->crc;
code_header->entfield = code->entfields;
if (OPTS_FLAG(DARKPLACES_STRING_TABLE_BUG)) {
/* >= + P */
code->chars.push_back('\0'); /* > */
code->chars.push_back('\0'); /* = */
code->chars.push_back('\0'); /* P */
}
/* ensure all data is in LE format */
util_swap_header(*code_header);
util_swap_statements(code->statements);
util_swap_defs_fields(code->defs);
util_swap_defs_fields(code->fields);
util_swap_functions(code->functions);
util_swap_globals(code->globals);
if (!OPTS_OPTION_BOOL(OPTION_QUIET)) {
if (lnofile)
con_out("writing '%s' and '%s'...\n", filename, lnofile);
else
con_out("writing '%s'\n", filename);
}
if (!OPTS_OPTION_BOOL(OPTION_QUIET) &&
!OPTS_OPTION_BOOL(OPTION_PP_ONLY))
{
char buffer[1024];
con_out("\nOptimizations:\n");
for (i = 0; i < COUNT_OPTIMIZATIONS; ++i) {
if (opts_optimizationcount[i]) {
util_optimizationtostr(opts_opt_list[i].name, buffer, sizeof(buffer));
con_out(
" %s: %u\n",
buffer,
(unsigned int)opts_optimizationcount[i]
);
}
}
}
}
static void code_stats(const char *filename, const char *lnofile, code_t *code, prog_header_t *code_header) {
if (OPTS_OPTION_BOOL(OPTION_QUIET) ||
OPTS_OPTION_BOOL(OPTION_PP_ONLY))
return;
con_out("\nFile statistics:\n");
con_out(" dat:\n");
con_out(" name: %s\n", filename);
con_out(" size: %u (bytes)\n", code_size_binary(code, code_header));
con_out(" crc: 0x%04X\n", code->crc);
if (lnofile) {
con_out(" lno:\n");
con_out(" name: %s\n", lnofile);
con_out(" size: %u (bytes)\n", code_size_debug(code, code_header));
}
con_out("\n");
}
bool code_write(code_t *code, const char *filename, const char *lnofile) {
prog_header_t code_header;
FILE *fp = nullptr;
code_create_header(code, &code_header, filename, lnofile);
if (lnofile) {
uint32_t version = 1;
fp = fopen(lnofile, "wb");
if (!fp)
return false;
util_endianswap(&version, 1, sizeof(version));
util_endianswap(&code->linenums[0], code->linenums.size(), sizeof(code->linenums[0]));
util_endianswap(&code->columnnums[0], code->columnnums.size(), sizeof(code->columnnums[0]));
if (fwrite("LNOF", 4, 1, fp) != 1 ||
fwrite(&version, sizeof(version), 1, fp) != 1 ||
fwrite(&code_header.defs.length, sizeof(code_header.defs.length), 1, fp) != 1 ||
fwrite(&code_header.globals.length, sizeof(code_header.globals.length), 1, fp) != 1 ||
fwrite(&code_header.fields.length, sizeof(code_header.fields.length), 1, fp) != 1 ||
fwrite(&code_header.statements.length, sizeof(code_header.statements.length), 1, fp) != 1 ||
fwrite(&code->linenums[0], sizeof(code->linenums[0]), code->linenums.size(), fp) != code->linenums.size() ||
fwrite(&code->columnnums[0], sizeof(code->columnnums[0]), code->columnnums.size(), fp) != code->columnnums.size())
{
con_err("failed to write lno file\n");
}
fclose(fp);
fp = nullptr;
}
fp = fopen(filename, "wb");
if (!fp)
return false;
if (1 != fwrite(&code_header, sizeof(prog_header_t) , 1 , fp) ||
code->statements.size() != fwrite(&code->statements[0], sizeof(prog_section_statement_t), code->statements.size(), fp) ||
code->defs.size() != fwrite(&code->defs[0], sizeof(prog_section_def_t) , code->defs.size() , fp) ||
code->fields.size() != fwrite(&code->fields[0], sizeof(prog_section_field_t) , code->fields.size() , fp) ||
code->functions.size() != fwrite(&code->functions[0], sizeof(prog_section_function_t) , code->functions.size() , fp) ||
code->globals.size() != fwrite(&code->globals[0], sizeof(int32_t) , code->globals.size() , fp) ||
code->chars.size() != fwrite(&code->chars[0], 1 , code->chars.size() , fp))
{
fclose(fp);
return false;
}
fclose(fp);
code_stats(filename, lnofile, code, &code_header);
return true;
}

226
conout.cpp Normal file
View file

@ -0,0 +1,226 @@
#include <stdio.h>
#include "gmqcc.h"
#define GMQCC_IS_STDOUT(X) ((X) == stdout)
#define GMQCC_IS_STDERR(X) ((X) == stderr)
#define GMQCC_IS_DEFINE(X) (GMQCC_IS_STDERR(X) || GMQCC_IS_STDOUT(X))
struct con_t {
FILE *handle_err;
FILE *handle_out;
int color_err;
int color_out;
};
static con_t console;
/*
* Enables color on output if supported.
* NOTE: The support for checking colors is nullptr. On windows this will
* always work, on *nix it depends if the term has colors.
*
* NOTE: This prevents colored output to piped stdout/err via isatty
* checks.
*/
static void con_enablecolor(void) {
console.color_err = util_isatty(console.handle_err);
console.color_out = util_isatty(console.handle_out);
}
/*
* Does a write to the handle with the format string and list of
* arguments. This colorizes for windows as well via translate
* step.
*/
static int con_write(FILE *handle, const char *fmt, va_list va) {
return vfprintf(handle, fmt, va);
}
/**********************************************************************
* EXPOSED INTERFACE BEGINS
*********************************************************************/
void con_close() {
if (!GMQCC_IS_DEFINE(console.handle_err))
fclose(console.handle_err);
if (!GMQCC_IS_DEFINE(console.handle_out))
fclose(console.handle_out);
}
void con_color(int state) {
if (state)
con_enablecolor();
else {
console.color_err = 0;
console.color_out = 0;
}
}
void con_init() {
console.handle_err = stderr;
console.handle_out = stdout;
con_enablecolor();
}
void con_reset() {
con_close();
con_init();
}
/*
* Defaultizer because stdio.h shouldn't be used anywhere except here
* and inside file.c To prevent mis-match of wrapper-interfaces.
*/
FILE *con_default_out() {
return console.handle_out = stdout;
}
FILE *con_default_err() {
return console.handle_err = stderr;
}
int con_verr(const char *fmt, va_list va) {
return con_write(console.handle_err, fmt, va);
}
int con_vout(const char *fmt, va_list va) {
return con_write(console.handle_out, fmt, va);
}
/*
* Standard stdout/stderr printf functions used generally where they need
* to be used.
*/
int con_err(const char *fmt, ...) {
va_list va;
int ln = 0;
va_start(va, fmt);
con_verr(fmt, va);
va_end(va);
return ln;
}
int con_out(const char *fmt, ...) {
va_list va;
int ln = 0;
va_start(va, fmt);
con_vout(fmt, va);
va_end (va);
return ln;
}
/*
* Utility console message writes for lexer contexts. These will allow
* for reporting of file:line based on lexer context, These are used
* heavily in the parser/ir/ast.
*/
static void con_vprintmsg_c(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, va_list ap, const char *condname) {
/* color selection table */
static int sel[] = {
CON_WHITE,
CON_CYAN,
CON_RED
};
int err = !!(level == LVL_ERROR);
int color = (err) ? console.color_err : console.color_out;
int (*print) (const char *, ...) = (err) ? &con_err : &con_out;
int (*vprint)(const char *, va_list) = (err) ? &con_verr : &con_vout;
if (color)
print("\033[0;%dm%s:%d:%d: \033[0;%dm%s: \033[0m", CON_CYAN, name, (int)line, (int)column, sel[level], msgtype);
else
print("%s:%d:%d: %s: ", name, (int)line, (int)column, msgtype);
vprint(msg, ap);
if (condname)
print(" [%s]\n", condname);
else
print("\n");
}
void con_vprintmsg(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, va_list ap) {
con_vprintmsg_c(level, name, line, column, msgtype, msg, ap, nullptr);
}
void con_printmsg(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, ...) {
va_list va;
va_start(va, msg);
con_vprintmsg(level, name, line, column, msgtype, msg, va);
va_end (va);
}
void con_cvprintmsg(lex_ctx_t ctx, int lvl, const char *msgtype, const char *msg, va_list ap) {
con_vprintmsg(lvl, ctx.file, ctx.line, ctx.column, msgtype, msg, ap);
}
void con_cprintmsg(lex_ctx_t ctx, int lvl, const char *msgtype, const char *msg, ...) {
va_list va;
va_start(va, msg);
con_cvprintmsg(ctx, lvl, msgtype, msg, va);
va_end (va);
}
/* General error interface: TODO seperate as part of the compiler front-end */
size_t compile_errors = 0;
size_t compile_warnings = 0;
size_t compile_Werrors = 0;
static lex_ctx_t first_werror;
void compile_show_werrors()
{
con_cprintmsg(first_werror, LVL_ERROR, "first warning", "was here");
}
void vcompile_error(lex_ctx_t ctx, const char *msg, va_list ap)
{
++compile_errors;
con_cvprintmsg(ctx, LVL_ERROR, "error", msg, ap);
}
void compile_error_(lex_ctx_t ctx, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vcompile_error(ctx, msg, ap);
va_end(ap);
}
bool GMQCC_WARN vcompile_warning(lex_ctx_t ctx, int warntype, const char *fmt, va_list ap)
{
const char *msgtype = "warning";
int lvl = LVL_WARNING;
char warn_name[1024];
if (!OPTS_WARN(warntype))
return false;
warn_name[0] = '-';
warn_name[1] = 'W';
(void)util_strtononcmd(opts_warn_list[warntype].name, warn_name+2, sizeof(warn_name)-2);
++compile_warnings;
if (OPTS_WERROR(warntype)) {
if (!compile_Werrors)
first_werror = ctx;
++compile_Werrors;
msgtype = "Werror";
if (OPTS_FLAG(BAIL_ON_WERROR)) {
msgtype = "error";
++compile_errors;
}
lvl = LVL_ERROR;
}
con_vprintmsg_c(lvl, ctx.file, ctx.line, ctx.column, msgtype, fmt, ap, warn_name);
return OPTS_WERROR(warntype) && OPTS_FLAG(BAIL_ON_WERROR);
}
bool GMQCC_WARN compile_warning_(lex_ctx_t ctx, int warntype, const char *fmt, ...)
{
bool r;
va_list ap;
va_start(ap, fmt);
r = vcompile_warning(ctx, warntype, fmt, ap);
va_end(ap);
return r;
}

View file

@ -1,4 +0,0 @@
float constant_1 = 1;
string constant_2 = "hello world";
vector constant_3 = { -0, +0, 0 };
entity constant_4 = 0

View file

@ -1,15 +0,0 @@
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
void(string) print = #1;
void(string,string) print2 = #1;
void(string,string,string) print3 = #1;
string(float) ftos = #2;
float CONST_1 = 1;
float CONST_2 = CONST_1 + 1;
void() main = {
print3("CONST_1 = ", ftos(CONST_1), "\n");
print3("CONST_2 = ", ftos(CONST_2), "\n");
};

View file

@ -1,48 +0,0 @@
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
void(string) print = #1;
void(string,string) print2 = #1;
void(string,string,string) print3 = #1;
string(float) ftos = #2;
entity() spawn = #3;
void(entity) kill = #4;
.float mema;
.float memb;
.vector memv;
.void() fun;
void(entity a, .float f) printfield = {
print3("The field is ", ftos(a.f), "\n");
};
void() funny = {
print("FUNNY\n");
};
void() main = {
local entity pawn;
pawn = spawn();
pawn.mema = 9;
pawn.memv = '1 2 3';
pawn.memb = 10;
print3("x = ", ftos(pawn.memv_x), "\n");
print3("y = ", ftos(pawn.memv_y), "\n");
print3("z = ", ftos(pawn.memv_z), "\n");
print3("a = ", ftos(pawn.mema), "\n");
print3("b = ", ftos(pawn.memb), "\n");
pawn.memv_y += 3;
print3("x = ", ftos(pawn.memv_x), "\n");
print3("y = ", ftos(pawn.memv_y), "\n");
print3("z = ", ftos(pawn.memv_z), "\n");
printfield(pawn, memv_z);
pawn.fun = funny;
pawn.fun();
};

View file

@ -1,56 +0,0 @@
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
void(string) print = #1;
void(string,string) print2 = #1;
void(string,string,string) print3 = #1;
string(float) ftos = #2;
entity() spawn = #3;
void(entity) kill = #4;
$frame stand1 stand2 standX
.float frame;
.float nextthink;
.void() think;
entity self;
float time;
// void() stand2; this is auto-prototyped
void() stand1 = [ 0, stand2 ] {
// expands to:
//self.frame = 0;
//self.nextthink = time + 0.1;
//self.think = stand2
print("In stand 1...\n");
print3("--> self.frame should be 0, is ", ftos(self.frame), "\n");
};
void() stand2 = [ 1, stand1 ] {
print("In stand 2...\n");
print3("--> self.frame should be 1, is ", ftos(self.frame), "\n");
};
void() standm = {
local string bar;
bar = ftos(self);
print3("Foo ", ftos(self), "\n");
self.frame = 0;
self.nextthink = time + 0.1;
};
void() main = {
self = spawn();
time = 10;
print("Setting think\n");
self.think = stand1;
print("Running think\n");
standm();
print("Running from 'self'\n");
self.think();
self.think();
self.think();
};

View file

@ -1,43 +0,0 @@
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
void(string) print = #1;
void(string,string) print2 = #1;
void(string,string,string) print3 = #1;
string(float) ftos = #2;
entity() spawn = #3;
void(entity) kill = #4;
.float vis;
.entity other;
float(entity targ) visible = {
return targ.vis;
};
void() printworking = {
print("Working\n");
};
void(void() callback) testcallback = {
callback();
};
void(float) has1param = {};
void() main = {
local entity pawn, pawn2;
pawn = spawn();
pawn2 = spawn();
pawn.other = pawn2;
pawn.other.vis = 0;
if (!visible(pawn.other))
print("Yes\n");
testcallback(printworking);
has1param();
};

View file

@ -1,5 +0,0 @@
/*
* all of these includes should work. No matter what the spacing
* is, we rely on it.
*/
#include "test/include2.qc"

View file

@ -1 +0,0 @@
float foo;

View file

@ -1,22 +0,0 @@
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
void(string) print = #1;
void(string,string) print2 = #1;
void(string,string,string) print3 = #1;
string(float) ftos = #2;
void() main = {
float a, b, c;
a = 3 + 4 + 5;
b = (5 * 2) + 1;
c = 3 & 1;
c = 1 | 2;
a = 3 && 4;
b = 0 && 4;
c = 4 && 0;
a = 1 || 1;
b = 1 || 0;
c = 0 || 1;
a = 0 || 0;
};

View file

@ -1,77 +0,0 @@
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
void(string,...) print = #1;
string(float) ftos = #2;
entity() spawn = #3;
void(entity) kill = #4;
.float mema;
.float memb;
$framevalue 0
$frame stand1 stand2 standX
$framerestore stand2
$frame stand3
$modelname foobar
$modelname foobar3
void(string a, ...) hasvaria = {
};
void() main = {
entity pawn;
vector vec;
float a;
vec = '3 4 5';
vec_z = 5;
a = 5;
if (a) {
print("a != 0\n");
} else {
print("not a\n");
}
a = 19;
print("Hello, World\n");
pawn = spawn();
pawn.mema = 3;
pawn.memb = 5;
print(ftos(pawn.mema), "\n");
print(ftos(pawn.memb), "\n");
print("SECOND TEST\n");
for (a = 0; a < 3; a = a + 1) {
print("LOOP ", ftos(a), "\n");
}
print("DO-WHILE test\n");
a = 2;
do {
print("Foo\n");
a = a - 1;
} while (a);
float b;
a = 5;
print("a = ", ftos(a), "\n");
b = a += 7;
print("adding\n");
print("a = ", ftos(a), "\n");
print("b = ", ftos(b), "\n");
print("memb = ", ftos(pawn.memb), "\n");
pawn.memb += -1;
print("memb = ", ftos(pawn.memb), "\n");
print("Frame stand3 is ", ftos($stand3), " wooh\n");
};
float() exprtest = {
local float x;
x = 3;
return (x); /* parens */
}

View file

@ -1,10 +0,0 @@
void test_parth() {
if (1) { }
if (2) { }
if (3) { }
if (4) { }
if (5) { }
if (6) { }
if (7) { }
if (8) { }
}

View file

@ -1,12 +0,0 @@
void(string) print = #1;
void() correct;
void(string) incorrect;
void() correct = {
print("Hello\n");
}
void() incorrect = {
printf("The compiler should error about this function having a wrong type\n");
}

View file

@ -1,103 +0,0 @@
; these are builtin functions
FUNCTION: makevectors, $1
FUNCTION: setorigin, $2
FUNCTION: setmodel, $3
FUNCTION: setsize, $4
FUNCTION: break, $6
FUNCTION: random, $7
FUNCTION: sound, $8
FUNCTION: normalize, $9
FUNCTION: error, $10
FUNCTION: objerror, $11
FUNCTION: vlen, $12
FUNCTION: vectoyaw, $13
FUNCTION: spawn, $14
FUNCTION: remove, $15
FUNCTION: traceline, $16
FUNCTION: find, $18
FUNCTION: precache_sound, $19
FUNCTION: precache_model, $20
FUNCTION: findradius, $22
FUNCTION: dprint, $25
FUNCTION: ftos, $26
FUNCTION: vtos, $27
FUNCTION: coredump, $28
FUNCTION: traceon, $29
FUNCTION: traceoff, $30
FUNCTION: eprint, $31
FUNCTION: walkmove, $32
FUNCTION: droptofloor, $34
FUNCTION: lightstyle, $35
FUNCTION: rint, $36
FUNCTION: floor, $37
FUNCTION: ceil, $38
FUNCTION: checkbottom, $40
FUNCTION: pointcontents, $41
FUNCTION: fabs, $43
FUNCTION: cvar, $45
FUNCTION: localcmd, $46
FUNCTION: nextent, $47
FUNCTION: particle, $48
FUNCTION: ChangeYaw, $49
FUNCTION: vectoangles, $51
FUNCTION: vectoangles2, $51
FUNCTION: sin, $60
FUNCTION: cos, $61
FUNCTION: sqrt, $62
FUNCTION: changepitch, $63
FUNCTION: tracetoss, $64
FUNCTION: etos, $65
FUNCTION: precache_file, $68
FUNCTION: makestatic, $69
FUNCTION: cvar_set, $72
FUNCTION: ambientsound, $74
FUNCTION: precache_model2,$75
FUNCTION: precache_sound2,$76
FUNCTION: precache_file2, $77
FUNCTION: stof, $81
FUNCTION: tracebox, $90
FUNCTION: randomvec, $91
FUNCTION: getlight, $92
FUNCTION: getlight2, $92
FUNCTION: registercvar, $93
FUNCTION: min, $94
FUNCTION: max, $95
FUNCTION: bound, $96
FUNCTION: pow, $97
FUNCTION: findfloat, $98
FUNCTION: checkextension, $99
FUNCTION: test #0
FLOAT: x, 100
FLOAT: y, 200
FLOAT: r_mul
FLOAT: r_div
FLOAT: r_add
FLOAT: r_sub
MUL_V x,y,r_mul
DIV_V x,y,r_div
ADD_V x,y,r_add
SUV_V x,y,r_sub
STORE_V r_mul
CALL0 dprint
STORE_V
END

View file

@ -1,11 +0,0 @@
typedef float my_float;
typedef vector my_vector;
typedef string my_string;
typedef entity my_entity;
typedef void my_void;
my_float type_float;
my_vector type_vector;
my_string type_string;
my_entity type_entity;
my_void type_void;

View file

@ -1,5 +0,0 @@
float typef;
vector typev;
string types;
entity typee;
void typev;

View file

@ -1,19 +0,0 @@
void(string) print = #1;
void(float) ftos = #2;
void() main = {
local float uninit, unused, setonly;
local vector invec;
print("foo\n");
setonly = 3;
invec = '1 2 3';
if (0)
uninit = 3;
ftos(uninit);
ftos(invec_x);
};
void(float par) partest = {
ftos(par);
};

View file

@ -1,43 +0,0 @@
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
void(string) print = #1;
void(string,string) print2 = #1;
void(string,string,string) print3 = #1;
string(float) ftos = #2;
entity() spawn = #3;
void(entity) kill = #4;
float multi, decla, ration;
.vector memvec;
.void(string x) printit;
float(vector different_name, vector b) dot;
float(vector a, vector b) dot = {
return a * b;
};
void(string x) myprintit = {
print3("-> ", x, "\n");
};
void(vector par) vecpar = {
// vector-parameters need _x, _y, _z as well
print3("par_y should be 5... = ", ftos(par_y), "\n");
};
void() main = {
local entity pawn;
local vector foovec;
print3("should be 1: ", ftos(dot('1 1 0', '1 0 0')), "\n");
foovec = '3 4 5';
foovec_y = 9;
pawn = spawn();
pawn.printit = myprintit;
pawn.printit("Hello");
vecpar('1 5 9');
};

View file

@ -1,10 +0,0 @@
vector vec1 = {-0 +0 0 };
vector vec2 = {.0 .0 .0 };
vector vec3 = {-.0 +.0 +0.1 };
vector vec4 = {1.1 2.2 3.3 };
vector vec5 = {2. 3. 4. };
vector vec6 = {-2. +3. -4. };
/*
* These are just comments: Ideally there is still some broken things
* for the vector yet. which sort of sucks.
*/

View file

@ -1,49 +1,771 @@
.\" Process with groff -man -Tascii file.3
.TH GMQCC 1 2012-07-12 "" "gmqcc Manual"
.SH NAME
gmqcc \- A Quake C compiler which tries to reduce suckiness.
.SH SYNOPSIS
.B gmqcc
[\fIOPTIONS\fR] [\fIfiles...\fR]
.SH DESCRIPTION
Traditionally, a QC compiler reads the file \fIprogs.src\fR which
in its first line contains the output filename, and the rest is a
.\"mdoc
.Dd January 24, 2013
.Dt GMQCC 1 PRM
.Os
.Sh NAME
.Nm gmqcc
.Nd A Quake C compiler built from the NIH realm of sarcastic wit
.Sh SYNOPSIS
.Nm gmqcc
.Op Cm options
.Op Ar files...
.Sh DESCRIPTION
Traditionally, a QC compiler reads the file
.Pa progs.src
which in its first line contains the output filename, and the rest is a
list of QC source files that are to be compiled in order.
\fBgmqcc\fR optionally takes options to specify the output and
.Nm gmqcc
optionally takes options to specify the output and
input files on the commandline, and also accepts assembly files.
.SH OPTIONS
\fBgmqcc\fR mostly tries to mimick gcc's commandline handling, though
.Sh OPTIONS
.Nm gmqcc
mostly tries to mimic gcc's commandline handling, though
there are also traditional long-options available.
.TP
.B "-h, --help"
.Bl -tag -width Ds
.It Fl h , Fl -help
Show a usage message and exit.
.TP
.BI "-o, --output=" filename
.It Fl o , Fl -output= Ns Ar filename
Specify the output filename. Defaults to progs.dat. This will overwrite
the output file listed in a \fIprogs.src\fR file in case such a file is used.
.TP
.BI "-O" n
Specify the optimization level, similar to gcc.
.TP
.BI "-a" filename
Append the specified files to the list of files to assemble using the QC-Assembler.
.TP
.BI "-s" filename
Append the specified file which is to be interpreted as a \fIprogs.src\fR file.
.TP
.BI "-std=" standard
Use the specified standard for parsing QC code. The following standards are available:
.IR gmqcc , qcc , fteqcc
.TP
.BI -W warning "\fR, " "" -Wno- warning
the output file listed in a
.Pa progs.src
file in case such a file is used.
.Bl -tag -width indent
.It Fl O Ns Ar number
Specify the optimization level
.It Ar 3
Highest optimization level
.It Ar 2
Default optimization level
.It Ar 1
Minimal optimization level
.It Ar 0
Disable optimization entirely
.El
.Pp
.It Fl O Ns Ar name , Fl Ono- Ns Ar name
Enable or disable a specific optimization. Note that these options
must be used after setting the optimization level, otherwise they'll
be overwritten.
.It Fl O Ns Cm help
List all possible optimizations and the optimization level they're
activated at.
.It Fl q , Fl -quiet
Be less verbose. In particular removes the messages about which files
are being processed, and which compilation mode is being used, and
some others. Warnings and errors will of course still be displayed.
.It Fl D Ns Ar macroname , Fl D Ns Ar macroname Ns = Ns Ar value
Predefine a macro, optionally with a optional value.
.It Fl E
Run only the preprocessor as if
.Fl f Ns Cm ftepp
was used and print the preprocessed code to stdout.
.It Fl W Ns Ar warning , Fl Wno- Ns Ar warning
Enable or disable a warning.
.TP
.B -Wall
Enable all warnings. Overrides preceding -W parameters.
.TP
.B -fdarkplaces-string-table-bug
Patch the output file to work around a string-table bug in certain darkplaces versions.
.TP
.B -fomit-nullbytes
Changes the output format to be more efficient. Requires a patched engine. See the
proposal for a better file structure in the gmqcc source tree.
.It Fl W Ns Cm all
Enable almost all warnings. Overrides preceding
.Fl W
parameters.
.Pp
The following warnings will
.Em not
be enabled:
.Bl -tag -width indent -offset indent
.It Fl W Ns Cm uninitialized-global
.El
.It Fl W Ns Cm error , Fl Wno- Ns Cm error
Controls whether or not all warnings should be treated as errors.
.It Fl Werror- Ns Ar warning , Fl Wno-error- Ns Ar warning
Controls whether a specific warning should be an error.
.It Fl W Ns Cm help
List all possible warn flags.
.It Fl f Ns Ar flag , Fl fno- Ns Ar flag
Enable or disable a specific compile flag. See the list of flags
below.
.It Fl f Ns Cm help
List all possible compile flags.
.It Fl nocolor
Disables colored output
.It Fl config= Ns Ar file
Use an ini file to read all the
.Fl O , Fl W
and
.Fl f
flag from. See the
.It Fl "debug"
Turn on some compiler debugging mechanisms.
.It Fl memchk
Turn on compiler mem-check. (Shows allocations and checks for leaks.)
.It Fl -memdumpcols Ns Ar columns
Changes the number of columns to use for the debug memory dump, defaults to 16.
.Sx CONFIG
section about the file format.
.It Fl redirout= Ns Ar file
Redirects standard output to a
.Ar file
.It Fl redirerr= Ns Ar file
Redirects standard error to a
.Ar file
.It Fl std= Ns Ar standard
Use the specified standard for parsing QC code. The following standards
are available:
.Ar gmqcc , Ar qcc , Ar fteqcc
Selecting a standard also implies some
.Fl f
options and behaves as if
those options have been written right after the
.Fl std
option, meaning
if you changed them before the
.Fl -std
option, you're now overwriting them.
.Pp
.Fl std= Ns Cm gmqcc No includes:
.Bl -tag -width indent -compact -offset Ds
.It Fl f Ns Cm adjust-vector-fields
.It Fl f Ns Cm correct-logic
.It Fl f Ns Cm true-empty-strings
.It Fl f Ns Cm loop-labels
.It Fl f Ns Cm initialized-nonconstants
.It Fl f Ns Cm translatable-strings
.It Fl fno- Ns Cm false-empty-strings
.It Fl W Ns Cm invalid-parameter-count
.It Fl W Ns Cm missing-returnvalues
.It Fl f Ns Cm correct-ternary Li (cannot be turned off)
.El
.Pp
.Fl std= Ns Cm qcc No includes:
.Bl -tag -width indent -compact -offset Ds
.It Fl f Ns Cm assign-function-types
.It Fl fIno- Ns Cm adjust-vector-fields
.El
.Pp
.Fl std= Ns Cm fteqcc No includes:
.Bl -tag -width indent -compact -offset Ds
.It Fl f Ns Cm ftepp
.It Fl f Ns Cm translatable-strings
.It Fl f Ns Cm assign-function-types
.It Fl W Ns Cm ternary-precedence
.It Fl fno- Ns Cm adjust-vector-fields
.It Fl fno- Ns Cm correct-ternary
.El
.It Fl -add-info
Adds compiler information to the generated binary file. Currently
this includes the following globals:
.Bl -tag -width indent -compact
.It Li reserved:version
String containing the compiler version as printed by the \-\-version
parameter.
.El
.It Fl -correct , Fl -no-correct
When enabled, errors about undefined values try to suggest an existing
value via spell checking.
.It Fl dump
DEBUG OPTION. Print the code's intermediate representation before the
optimization and finalization passes to stdout before generating the
binary.
.It Fl dumpfin
DEBUG OPTION. Print the code's intermediate representation after the
optimization and finalization passes to stdout before generating the
binary. The instructions will be enumerated, and values will contain a
list of liferanges.
.It Fl force-crc= Ns Ar CRC
Force the produced progs file to use the specified CRC.
.It Fl state-fps= Ns Ar NUM
Activate \-femulate-state and set the emulated FPS to
.Ar NUM Ns .
.El
.Sh COMPILE WARNINGS
.Bl -tag -width Ds
.It Fl W Ns Cm unused-variable
Generate a warning about variables which are declared but never used.
This can be avoided by adding the
.Ql noref
keyword in front of the
variable declaration. Additionally a complete section of unreferenced
variables can be opened using
.Ql #pragma noref 1
and closed via
.Ql #pragma noref 0 Ns .
.It Fl W Ns Cm unused-component
Generate a warning about vector variables which are declared but not all their
components are used.
.It Fl W Ns Cm used-uninitialized
Generate a warning if it is possible that a variable can be used
without prior initialization. Note that this warning is not
necessarily reliable if the initialization happens only under certain
conditions. The other way is
.Em not
possible: that the warning is
.Em not
generated when uninitialized use
.Em is
possible.
.It Fl W Ns Cm unknown-control-sequence
Generate an error when an unrecognized control sequence in a string is
used. Meaning: when there's a character after a backslash in a string
which has no known meaning.
.It Fl W Ns Cm extensions
Warn when using special extensions which are not part of the selected
standard.
.It Fl W Ns Cm field-redeclared
Generally QC compilers ignore redeclaration of fields. Here you can
optionally enable a warning.
.It Fl W Ns Cm missing-return-values
Functions which aren't of type
.Ft void
will warn if it possible to
reach the end without returning an actual value.
.It Fl W Ns Cm invalid-parameter-count
Warn about a function call with an invalid number of parameters.
.It Fl W Ns Cm local-shadows
Warn when a locally declared variable shadows variable.
.It Fl W Ns Cm local-constants
Warn when the initialization of a local variable turns the variable
into a constant. This is default behaviour unless
.Fl f Ns Cm initialized-nonconstants
is used.
.It Fl W Ns Cm void-variables
There are only 2 known global variables of type void:
.Ql end_sys_globals
and
.Ql end_sys_fields Ns .
Any other void-variable will warn.
.It Fl W Ns Cm implicit-function-pointer
A global function which is not declared with the
.Ql var
keyword is
expected to have an implementing body, or be a builtin. If neither is
the case, it implicitly becomes a function pointer, and a warning is
generated.
.It Fl W Ns Cm variadic-function
Currently there's no way for an in QC implemented function to access
variadic parameters. If a function with variadic parameters has an
implementing body, a warning will be generated.
.It Fl W Ns Cm frame-macros
Generate warnings about
.Ql $frame
commands, for instance about
duplicate frame definitions.
.It Fl W Ns Cm effectless-statement
Warn about statements which have no effect. Any expression which does
not call a function or assigns a variable.
.It Fl W Ns Cm end-sys-fields
The
.Ql end_sys_fields
variable is supposed to be a global variable
of type
.Ft void Ns .
It is also recognized as a \fIfield\fR but this
will generate a warning.
.It Fl W Ns Cm assign-function-types
Warn when assigning to a function pointer with an unmatching
signature. This usually happens in cases like assigning the null
function to an entity's .think function pointer.
.It Fl W Ns Cm cpp
Show warnings created using the preprocessor's '#warning' directive.
.It Fl W Ns Cm multifile-if
Warn if there's a preprocessor \fI#if\fR spanning across several
files.
.It Fl W Ns Cm double-declaration
Warn about multiple declarations of globals. This seems pretty common
in QC code so you probably do not want this unless you want to clean
up your code.
.It Fl W Ns Cm const-var
The combination of \fIconst\fR and \fIvar\fR is not illegal, however
different compilers may handle them differently. We were told, the
intention is to create a function-pointer which is not assignable.
This is exactly how we interpret it. However for this interpretation
the
.Ql var
keyword is considered superfluous (and philosophically
wrong), so it is possible to generate a warning about this.
.It Fl W Ns Cm multibyte-character
Warn about multibyte character constants, they do not work right now.
.It Fl W Ns Cm ternary-precedence
Warn if a ternary expression which contains a comma operator is used
without enclosing parenthesis, since this is most likely not what you
actually want. We recommend the
.Fl f Ns Cm correct-ternary
option.
.It Fl W Ns Cm unknown-pragmas
Warn when encountering an unrecognized
.Ql #pragma
line.
.It Fl W Ns Cm unreachable-code
Warn about unreachable code. That is: code after a return statement,
or code after a call to a function marked as 'noreturn'.
.It Fl W Ns Cm debug
Enable some warnings added in order to help debugging in the compiler.
You won't need this.
.It Fl W Ns Cm unknown-attribute
Warn on an unknown attribute. The warning will inlclude only the first
token inside the enclosing attribute-brackets. This may change when
the actual attribute syntax is better defined.
.It Fl W Ns Cm reserved-names
Warn when using reserved names such as
.Ql nil Ns .
.It Fl W Ns Cm uninitialized-constant
Warn about global constants (using the
.Ql const
keyword) with no
assigned value.
.It Fl W Ns Cm uninitialized-global
Warn about global variables with no initializing value. This is off by
default, and is added mostly to help find null-values which are
supposed to be replaced by the untyped 'nil' constant.
.It Fl W Ns Cm different-qualifiers
Warn when a variables is redeclared with a different qualifier. For
example when redeclaring a variable as \'var\' which was previously
marked \'const\'.
.It Fl W Ns Cm different-attributes
Similar to the above but for attributes like
.Ql [[noreturn]] Ns .
.It Fl W Ns Cm deprecated
Warn when a function is marked with the attribute
"[[deprecated]]". This flag enables a warning on calls to functions
marked as such.
.It Fl W Ns Cm parenthesis
Warn about possible mistakes caused by missing or wrong parenthesis,
like an assignment in an 'if' condition when there's no additional set
of parens around the assignment.
.It Fl W Ns Cm unsafe-types
When passing variadic parameters via
.Li ...(N)
it can happen that incompatible types are passed to functions. This
enables several warnings when static typechecking cannot guarantee
consistent behavior.
.It Fl W Ns Cm breakdef
When compiling original id1 QC there is a definition for `break`
which conflicts with the 'break' keyword in GMQCC. Enabling this
will print a warning when the definition occurs. The definition is
ignored for both cases.
.It Fl W Ns Cm const-overwrite
When compiling original QuakeWorld QC there are instances where
code overwrites constants. This is considered an error, however
for QuakeWorld to compile it needs to be treated as a warning
instead, as such this warning only works when \-std=qcc.
.It Fl W Ns Cm directive-inmacro
Warn about the use of preprocessor directives inside macros.
.It Fl W Ns Cm builtins
When using a function that is not explicitly defined, the compiler
will search its intrinsics table for something that matches that
function name by appending "__builtin_" to it. This behaviour may
be unexpected, so enabling this will produce a diagnostic when
such a function is resolved to a builtin.
.It Fl W Ns Cm inexact-compares
When comparing an inexact value such as `1.0/3.0' the result is
pathologically wrong. Enabling this will trigger a compiler warning
on such expressions.
.El
.Sh COMPILE FLAGS
.Bl -tag -width Ds
.It Fl f Ns Cm darkplaces-string-table-bug
Add some additional characters to the string table in order to
compensate for a wrong boundcheck in some specific version of the
darkplaces engine.
.It Fl f Ns Cm adjust-vector-fields
When assigning to field pointers of type \fI.vector\fR the common
behaviour in compilers like \fIfteqcc\fR is to only assign the
x-component of the pointer. This means that you can use the vector as
such, but you cannot use its y and z components directly. This flag
fixes this behaviour. Before using it make sure your code does not
depend on the buggy behaviour.
.It Fl f Ns Cm ftepp
Enable a partially fteqcc-compatible preprocessor. It supports all the
features used in the Xonotic codebase. If you need more, write a
ticket.
.It Fl f Ns Cm ftepp-predefs
Enable some predefined macros. This only works in combination with
\'\-fftepp' and is currently not included by '\-std=fteqcc'. The
following macros will be added:
.Bd -literal -offset indent
__LINE__
__FILE__
__COUNTER__
__COUNTER_LAST__
__RANDOM__
__RANDOM_LAST__
__DATE__
__TIME__
__FUNC__
.Ed
.Pp
Note that
.Li __FUNC__
is not actually a preprocessor macro, but is recognized by the parser
even with the preprocessor disabled.
.Pp
Note that fteqcc also defines
.Li __NULL__
which becomes the first global. Assigning it to a vector does not
yield the same result as in gmqcc where
.Li __NULL__
is defined to
.Li nil
(See
.Fl f Ns Cm untyped-nil
), which will cause the vector to be zero in all components. With fteqcc
only the first component will be 0, while the other two will become
the first to of the global return value. This behavior is odd and
relying on it should be discouraged, and thus is not supported by
gmqcc.
.It Fl f Ns Cm ftepp-mathdefs
Enable math constant definitions. This only works in combination
with \'\-fftepp' and is currently not included by '\-std=fteqcc'.
The following macros will be added:
.Bd -literal -offset indent
M_E
M_LOG2E
M_LOG10E
M_LN2
M_LN10
M_PI
M_PI_2
M_PI_4
M_1_PI
M_2_PI
M_2_SQRTPI
M_SQRT2
M_SQRT1_2
M_TAU
.Ed
.It Fl f Ns Cm ftepp-indirect-expansion
Enable indirect macro expansion. This only works in combination
with '-fftepp' and is currently not included by '-std=fteqcc'.
Enabling this behavior will allow the preprocessor to operate more
like the standard C preprocessor in that it will allow arguments
of macros which are macro-expanded to be substituted into the
definition of the macro.
.Pp
As an example:
.Bd -literal -offset indent
#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
.Ed
With this enabled, an expansion of THE_ANSWER_STR will yield
the string "42". With this disabled an expansion of THE_ANSWER_STR
will yield "THE_ANSWER"
.It Fl f Ns Cm relaxed-switch
Allow switch cases to use non constant variables.
.It Fl f Ns Cm short-logic
Perform early out in logical AND and OR expressions. The final result
will be either a 0 or a 1, see the next flag for more possibilities.
.It Fl f Ns Cm perl-logic
In many languages, logical expressions perform early out in a special
way: If the left operand of an AND yeilds true, or the one of an OR
yields false, the complete expression evaluates to the right side.
Thus
.Ql true && 5
evaluates to 5 rather than 1.
.It Fl f Ns Cm translatable-strings
Enable the underscore intrinsic: Using
.Ql _("A string constant")
will cause the string immediate to get a name with a "dotranslate_"
prefix. The darkplaces engine recognizes these and translates them in
a way similar to how gettext works.
.It Fl f Ns Cm initialized-nonconstants
Don't implicitly convert initialized variables to constants. With this
flag, the \fIconst\fR keyword is required to make a constant.
.It Fl f Ns Cm assign-function-types
If this flag is not set, (and it is set by default in the qcc and
fteqcc standards), assigning function pointers of mismatching
signatures will result in an error rather than a warning.
.It Fl f Ns Cm lno
Produce a linenumber file along with the output .dat file.
.It Fl f Ns Cm correct-ternary
Use C's operator precedence for ternary expressions. Unless your code
depends on fteqcc-compatible behaviour, you'll want to use thi
soption.
.It Fl f Ns Cm single-vector-defs
Normally vectors generate 4 defs, once for the vector, and once for
its components with _x, _y, _z suffixes. This option
prevents components from being listed.
.It Fl f Ns Cm correct-logic
Most QC compilers translate
.Ql if(a_vector)
directly as an IF on the
vector, which means only the x-component is checked. This option causes
vectors to be cast to actual booleans via a NOT_V and, if necessary, a
NOT_F chained to it.
.Bd -literal -offset indent
if (a_vector) // becomes
if not(!a_vector)
// likewise
a = a_vector && a_float // becomes
a = !!a_vector && a_float
.Ed
.It Fl f Ns Cm true-empty-strings
An empty string is considered to be true everywhere. The NOT_S
instruction usually considers an empty string to be false, this option
effectively causes the unary not in strings to use NOT_F instead.
.It Fl f Ns Cm false-empty-strings
An empty string is considered to be false everywhere. This means loops
and if statements which depend on a string will perform a NOT_S
instruction on the string before using it.
.It Fl f Ns Cm utf8
Enable utf8 characters. This allows utf-8 encoded character constants,
and escape sequence codepoints in the valid utf-8 range. Effectively
enabling escape sequences like '\\{x2211}'.
.It Fl f Ns Cm bail-on-werror
When a warning is treated as an error, and this option is set (which
it is by default), it is like any other error and will cause
compilation to stop. When disabling this flag by using
\-fno-bail-on-werror, compilation will continue until the end, but no
output is generated. Instead the first such error message's context is
shown.
.It Fl f Ns Cm loop-labels
Allow loops to be labeled, and allow 'break' and 'continue' to take an
optional label to decide which loop to actually jump out of or
continue.
.Bd -literal -offset indent
for :outer (i = 0; i < n; ++i) {
while (inner) {
...;
if (something)
continue outer;
}
}
.Ed
.It Fl f Ns Cm untyped-nil
Adds a global named 'nil' which is of no type and can be assigned to
anything. No typechecking will be performed on assignments. Assigning
to it is forbidden, using it in any other kind of expression is also
not allowed.
.sp
Note that this is different from fteqcc's __NULL__: In fteqcc,
__NULL__ maps to the integer written as '0i'. It's can be assigned to
function pointers and integers, but it'll error about invalid
instructions when assigning it to floats without enabling the FTE
instruction set. There's also a bug which allows it to be assigned to
vectors, for which the source will be the global at offset 0, meaning
the vector's y and z components will contain the OFS_RETURN x and y
components.
.sp
In that gmqcc the nil global is an actual global filled with zeroes,
and can be assigned to anything including fields, vectors or function
pointers, and they end up becoming zeroed.
.It Fl f Ns Cm permissive
Various effects, usually to weaken some conditions.
.Bl -tag -width indent -offset indent
.It with Fl f Ns Cm untyped-nil
Allow local variables named
.Ql nil Ns .
(This will not allow declaring a global of that name.)
.El
.It Fl f Ns Cm variadic-args
Allow variadic parameters to be accessed by QC code. This can be
achieved via the '...' function, which takes a parameter index and a
typename.
.Pp
Example:
.Bd -literal -offset indent
void vafunc(string...count) {
float i;
for (i = 0; i < count; ++i)
print(...(i, string), "\\n");
}
.Ed
.It Fl f Ns Cm legacy-vector-maths
Most Quake VMs, including the one from FTEQW or up till recently
Darkplaces, do not cope well with vector instructions with overlapping
input and output. This option will avoid producing such code.
.It Fl f Ns Cm expressions-for-builtins
Usually builtin-numbers are just immediate constants. With this flag
expressions can be used, as long as they are compile-time constant.
.Pp
Example:
.Bd -literal -offset indent
void printA() = #1; // the usual way
void printB() = #2-1; // with a constant expression
.Ed
.It Fl f Ns Cm return-assignments
Enabiling this option will allow assigning values or expressions to the
return keyword as if it were a local variable of the same type as the
function's signature's return type.
.Pp
Example:
.Bd -literal -offset indent
float bar() { return 1024; }
float fun() {
return = bar();
return; // returns value of bar
}
.Ed
.It Fl f Ns Cm unsafe-varargs
When passing on varargs to a different functions, this turns some
static error cases into warnings. Like when the caller's varargs are
restricted to a different type than the callee's parameter. Or a list
of unrestricted varargs is passed into restricted varargs.
.It Fl f Ns Cm typeless-stores
Always use STORE_F, LOAD_F, STOREP_F when accessing scalar variables.
This is somewhat incorrect assembly instruction use, but in all engines
they do exactly the same. This makes disassembly output harder to read,
breaks decompilers, but causes the output file to be better compressible.
.It Fl f Ns Cm sort-operands
In commutative instructions, always put the lower-numbered operand first.
This shaves off 1 byte of entropy from all these instructions, reducing
compressed size of the output file.
.It Fl f Ns Cm emulate-state
Emulate OP_STATE operations in code rather than using the instruction.
The desired fps can be set via -state-fps=NUM, defaults to 10.
Specifying \-state-fps implicitly sets this flag. Defaults to off in all
standards.
.It Fl f Ns Cm arithmetic-exceptions
Turn on arithmetic exception tests in the compiler. In constant expressions
which trigger exceptions like division by zero, overflow, underflow, etc,
the following flag will produce diagnostics for what triggered that
exception.
.It Fl f Ns Cm split-vector-parameters
With this flag immediate vector literals which only ever appear as function
parameters won't be stored as vector immediates. Instead, the 3 floats making
up the vector will be copied separately. Essentially this turns a vector-store
instruction into 3 float-store instructions for such cases. This increases
code size but can dramatically reduce the amount of vector globals, which is
after all limited to 64k. There's at least one known codebase where this
lowers the number of globals from over 80k down to around 3k. In other code
bases it doesn't reduce the globals at all but only increases code size.
Just try it and see whether it helps you.
.It Fl f Ns Cm default-eraseable
Force all expressions to be "eraseable" which permits the compiler to
remove unused functions, variables and statements. This is equivlant to
putting [[eraseable]] on all definitions. This is dangerous as it breaks
auto cvars, definitions for functions the engine may be looking for and
translatable strings. Instead, you can mark a definition with [[noerase]]
to prevent this from happening.
.El
.Sh OPTIMIZATIONS
.Bl -tag -width Ds
.It Fl O Ns Cm peephole
Some general peephole optimizations. For instance the code `a = b + c`
typically generates 2 instructions, an ADD and a STORE. This
optimization removes the STORE and lets the ADD write directly into A.
.It Fl O Ns Cm tail-recursion
Tail recursive function calls will be turned into loops to avoid the
overhead of the CALL and RETURN instructions.
.It Fl O Ns Cm overlap-locals
Make all functions which use neither local arrays nor have locals
which are seen as possibly uninitialized use the same local section.
This should be pretty safe compared to other compilers which do not
check for uninitialized values properly. The problem is that there's
QC code out there which really doesn't initialize some values. This is
fine as long as this kind of optimization isn't used, but also, only
as long as the functions cannot be called in a recursive manner. Since
it's hard to know whether or not an array is actually fully
initialized, especially when initializing it via a loop, we assume
functions with arrays to be too dangerous for this optimization.
.It Fl O Ns Cm local-temps
This promotes locally declared variables to "temps". Meaning when a
temporary result of an operation has to be stored somewhere, a local
variable which is not 'alive' at that point can be used to keep the
result. This can reduce the size of the global section.
This will not have declared variables overlap, even if it was
possible.
.It Fl O Ns Cm global-temps
Causes temporary values which do not need to be backed up on a CALL to
not be stored in the function's locals-area. With this, a CALL to a
function may need to back up fewer values and thus execute faster.
.It Fl O Ns Cm strip-constant-names
Don't generate defs for immediate values or even declared constants.
Meaning variables which are implicitly constant or qualified as such
using the 'const' keyword.
.It Fl O Ns Cm overlap-strings
Aggressively reuse strings in the string section. When a string should
be added which is the trailing substring of an already existing
string, the existing string's tail will be returned instead of the new
string being added.
.Pp
For example the following code will only generate 1 string:
.Bd -literal -offset indent
print("Hello you!\\n");
print("you!\\n"); // trailing substring of "Hello you!\\n"
.Ed
.Pp
There's however one limitation. Strings are still processed in order,
so if the above print statements were reversed, this optimization
would not happen.
.It Fl O Ns Cm call-stores
By default, all parameters of a CALL are copied into the
parameter-globals right before the CALL instructions. This is the
easiest and safest way to translate calls, but also adds a lot of
unnecessary copying and unnecessary temporary values. This
optimization makes operations which are used as a parameter evaluate
directly into the parameter-global if that is possible, which is when
there's no other CALL instruction in between.
.It Fl O Ns Cm void-return
Usually an empty RETURN instruction is added to the end of a void
typed function. However, additionally after every function a DONE
instruction is added for several reasons. (For example the qcvm's
disassemble switch uses it to know when the function ends.). This
optimization replaces that last RETURN with DONE rather than adding
the DONE additionally.
.It Fl O Ns Cm vector-components
Because traditional QC code doesn't allow you to access individual
vector components of a computed vector without storing it in a local
first, sometimes people multiply it by a constant like
.Ql '0 1 0'
to get,
in this case, the y component of a vector. This optimization will turn
such a multiplication into a direct component access. If the factor is
anything other than 1, a float-multiplication will be added, which is
still faster than a vector multiplication.
.It Fl O Ns Cm const-fold-dce
For constant expressions that result in dead code (such as a branch whos
condition can be evaluated at compile-time), this will eliminate the branch
and else body (if present) to produce more optimal code.
.El
.Sh CONFIG
The configuration file is similar to regular .ini files. Comments
start with hashtags or semicolons, sections are written in square
brackets and in each section there can be arbitrary many key-value
pairs.
.Pp
There are 3 sections currently:
.Ql flags Ns ,
.Ql warnings Ns ,
.Ql optimizations Ns .
They contain a list of boolean values of the form
.Ql VARNAME = true
or
.Ql VARNAME = false Ns .
The variable names are the same as for the
corresponding
.Fl W , Fl f
or
.Fl O
flag written with only capital letters and
dashes replaced by underscores.
.Pp
Here's an example:
.Bd -literal -offset indent
# a GMQCC configuration file
[flags]
FTEPP = true
ADJUST_VECTOR_FIELDS = false
LNO = true
[warnings]
UNUSED_VARIABLE = false
USED_UNINITIALIZED = true
[optimizations]
PEEPHOLE = true
TAIL_RECURSION = true
.Ed
.Sh FILES
.Bl -tag -width Ds
.It gmqcc.ini.example
A documented example for a gmqcc.ini file.
.El
.Sh SEE ALSO
.Xr qcvm 1
.Sh AUTHOR
See <http://graphitemaster.github.com/gmqcc>.
.Sh BUGS
Currently the '\-fftepp-predefs' flag is not included by '\-std=fteqcc',
partially because it is not entirely conformant to fteqcc.
.Pp
Please report bugs on <http://github.com/graphitemaster/gmqcc/issues>,
or see <http://graphitemaster.github.com/gmqcc> on how to contact us.

107
doc/qcvm.1 Normal file
View file

@ -0,0 +1,107 @@
.\" qcvm mdoc manpage
.Dd January 31, 2013
.Dt QCVM 1 PRM
.Os
.Sh NAME
.Nm qcvm
.Nd A standalone QuakeC VM binary executor
.Sh SYNOPSIS
.Nm qcvm
.Op Cm options
.Op Cm parameters
.Ar program-file
.Sh DESCRIPTION
.Nm qcvm
is an executor for QuakeC VM binary files created using a QC
compiler such as gmqcc(1) or fteqcc. It provides a small set of
builtin functions, and by default executes the
.Fn main
function if there is one. Some options useful for debugging are
available as well.
.Sh OPTIONS
There are 2 types of options. Options for the executor, and parameter
options used to add parameters which are passed to the main function
on execution.
.Bl -tag -width Ds
.It Fl h , Fl -help
Show a usage message and exit.
.It Fl trace
Trace the execution. Each instruction will be printed to stdout before
executing it.
.It Fl profile
Perform some profiling. This is currently not really implemented, the
option is available nonetheless.
.It Fl info
Print information from the program's header instead of executing.
.It Fl disasm
Disassemble the program by function instead of executing.
.It Fl disasm-func Ar function
Search for and disassemble the given function.
.It Fl printdefs
List all entries from the program's defs-section. Effectively
listing all the global variables of the program.
This option disables execution.
.It Fl printfields
List all entries from the program's fields-section. Listing all
entity-fields declared in the program.
This option disables execution.
.It Fl printfuns
List functions and some information about their parameters.
This option disables execution. With a verbosity level of 1, builtin
numbers are printed. With a verbosity of 2, the function's sizes are
printed as well. This takes a little longer since the size is found by
searching for a
.Ql DONE
instruction in the code.
.It Fl v
Increase verbosity level, can be used multiple times.
.It Fl vector Ar 'x y z'
Append a vector parameter to be passed to
.Fn main Ns .
.It Fl float Ar number
Append a float parameter to be passed to
.Fn main Ns .
.It Fl string Ar 'text'
Append a string parameter to be passed to
.Fn main Ns .
.El
.Sh BUILTINS
The following builtin functions are available:
.Bl -ohang
.It Li 1) void print(string...) = #1;
.Bd -unfilled -offset indent -compact
Print the passed strings to stdout. At most 8 strings are allowed.
.Ed
.It Li 2) string ftos(float) = #2;
.D1 Convert a float to a string.
.It Li 3) entity spawn() = #3;
.D1 Spawn an entity.
.It Li 4) void remove(entity) = #4;
.D1 Remove an entity.
.It Li 5) string vtos(vector) = #5;
.D1 Convert a vector to a string.
.It Li 6) void error(string...) = #6;
.D1 Print strings to stdout and then exit with an error (limited to 8 arguments)
.It Li 7) float vlen(vector) = #7;
.D1 Get the length of a vector.
.It Li 8) string etos(entity) = #8;
.D1 Get the entity ID as string.
.It Li 9) float stof(string) = #9;
.D1 Convert a string to a float.
.It Li 10) string strcat(string, string) = #10;
.D1 Concatenate two strings, returning a tempstring.
.It Li 11) float strcmp(string, string) = #11;
.Li 12) float strncmp(string, string, float) = #11;
.D1 Compare two strings. Returns the same as the corresponding C functions.
.It Li 12) vector normalize(vector) = #12;
.D1 Normalize a vector so its length is 1.
.It Li 13) float sqrt(float) = #13;
.D1 Get a value's square root.
.El
.Sh SEE ALSO
.Xr gmqcc 1
.Sh AUTHOR
See <http://graphitemaster.github.com/gmqcc>.
.Sh BUGS
Please report bugs on <http://github.com/graphitemaster/gmqcc/issues>,
or see <http://graphitemaster.github.com/gmqcc> on how to contact us.

70
error.c
View file

@ -1,70 +0,0 @@
/*
* Copyright (C) 2012
* Dale Weiler
* Wolfgang Bumiller
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "gmqcc.h"
/*
* Compiler error system, this handles the error printing, and managing
* such as after so many errors just stop the compilation, and other
* intereting like colors for the console.
*/
#ifndef WIN32
int levelcolor[] = {
CON_WHITE,
CON_CYAN,
CON_RED
};
#endif
void vprintmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap)
{
#ifndef WIN32
fprintf (stderr, "\033[0;%dm%s:%d: \033[0;%dm%s: \033[0m", CON_CYAN, name, (int)line, levelcolor[level], msgtype);
#else
fprintf (stderr, "%s:%d: %s: ", name, line, msgtype);
#endif
vfprintf(stderr, msg, ap);
fprintf (stderr, "\n");
}
void printmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, ...)
{
va_list va;
va_start(va, msg);
vprintmsg(level, name, line, msgtype, msg, va);
va_end (va);
}
void cvprintmsg(lex_ctx ctx, int lvl, const char *msgtype, const char *msg, va_list ap)
{
vprintmsg(lvl, ctx.file, ctx.line, msgtype, msg, ap);
}
void cprintmsg (lex_ctx ctx, int lvl, const char *msgtype, const char *msg, ...)
{
va_list va;
va_start(va, msg);
cvprintmsg(ctx, lvl, msgtype, msg, va);
va_end (va);
}

947
exec.c
View file

@ -1,947 +0,0 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "gmqcc.h"
MEM_VEC_FUNCTIONS(qc_program, prog_section_statement, code)
MEM_VEC_FUNCTIONS(qc_program, prog_section_def, defs)
MEM_VEC_FUNCTIONS(qc_program, prog_section_def, fields)
MEM_VEC_FUNCTIONS(qc_program, prog_section_function, functions)
MEM_VEC_FUNCTIONS(qc_program, char, strings)
MEM_VEC_FUN_APPEND(qc_program, char, strings)
MEM_VEC_FUN_RESIZE(qc_program, char, strings)
MEM_VEC_FUNCTIONS(qc_program, qcint, globals)
MEM_VEC_FUNCTIONS(qc_program, qcint, entitydata)
MEM_VEC_FUNCTIONS(qc_program, bool, entitypool)
MEM_VEC_FUNCTIONS(qc_program, qcint, localstack)
MEM_VEC_FUN_APPEND(qc_program, qcint, localstack)
MEM_VEC_FUN_RESIZE(qc_program, qcint, localstack)
MEM_VEC_FUNCTIONS(qc_program, qc_exec_stack, stack)
MEM_VEC_FUNCTIONS(qc_program, size_t, profile)
MEM_VEC_FUN_RESIZE(qc_program, size_t, profile)
MEM_VEC_FUNCTIONS(qc_program, prog_builtin, builtins)
static void loaderror(const char *fmt, ...)
{
int err = errno;
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf(": %s\n", strerror(err));
}
static void qcvmerror(qc_program *prog, const char *fmt, ...)
{
va_list ap;
prog->vmerror++;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
putchar('\n');
}
qc_program* prog_load(const char *filename)
{
qc_program *prog;
prog_header header;
size_t i;
FILE *file;
file = util_fopen(filename, "rb");
if (!file)
return NULL;
if (fread(&header, sizeof(header), 1, file) != 1) {
loaderror("failed to read header from '%s'", filename);
fclose(file);
return NULL;
}
if (header.version != 6) {
loaderror("header says this is a version %i progs, we need version 6\n", header.version);
fclose(file);
return NULL;
}
prog = (qc_program*)mem_a(sizeof(qc_program));
if (!prog) {
fclose(file);
printf("failed to allocate program data\n");
return NULL;
}
memset(prog, 0, sizeof(*prog));
prog->entityfields = header.entfield;
prog->crc16 = header.crc16;
prog->filename = util_strdup(filename);
if (!prog->filename) {
loaderror("failed to store program name");
goto error;
}
#define read_data(hdrvar, progvar, type) \
if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \
loaderror("seek failed"); \
goto error; \
} \
prog->progvar##_alloc = header.hdrvar.length; \
prog->progvar##_count = header.hdrvar.length; \
prog->progvar = (type*)mem_a(header.hdrvar.length * sizeof(*prog->progvar)); \
if (!prog->progvar) \
goto error; \
if (fread(prog->progvar, sizeof(*prog->progvar), header.hdrvar.length, file) \
!= header.hdrvar.length) { \
loaderror("read failed"); \
goto error; \
}
#define read_data1(x, y) read_data(x, x, y)
read_data (statements, code, prog_section_statement);
read_data1(defs, prog_section_def);
read_data1(fields, prog_section_def);
read_data1(functions, prog_section_function);
read_data1(strings, char);
read_data1(globals, qcint);
fclose(file);
/* profile counters */
if (!qc_program_profile_resize(prog, prog->code_count))
goto error;
/* Add tempstring area */
prog->tempstring_start = prog->strings_count;
prog->tempstring_at = prog->strings_count;
if (!qc_program_strings_resize(prog, prog->strings_count + 16*1024))
goto error;
/* spawn the world entity */
if (!qc_program_entitypool_add(prog, true)) {
loaderror("failed to allocate world entity\n");
goto error;
}
for (i = 0; i < prog->entityfields; ++i) {
if (!qc_program_entitydata_add(prog, 0)) {
loaderror("failed to allocate world data\n");
goto error;
}
}
prog->entities = 1;
return prog;
error:
if (prog->filename) mem_d(prog->filename);
if (prog->code) mem_d(prog->code);
if (prog->defs) mem_d(prog->defs);
if (prog->fields) mem_d(prog->fields);
if (prog->functions) mem_d(prog->functions);
if (prog->strings) mem_d(prog->strings);
if (prog->globals) mem_d(prog->globals);
if (prog->entitydata) mem_d(prog->entitydata);
if (prog->entitypool) mem_d(prog->entitypool);
mem_d(prog);
return NULL;
}
void prog_delete(qc_program *prog)
{
if (prog->filename) mem_d(prog->filename);
MEM_VECTOR_CLEAR(prog, code);
MEM_VECTOR_CLEAR(prog, defs);
MEM_VECTOR_CLEAR(prog, fields);
MEM_VECTOR_CLEAR(prog, functions);
MEM_VECTOR_CLEAR(prog, strings);
MEM_VECTOR_CLEAR(prog, globals);
MEM_VECTOR_CLEAR(prog, entitydata);
MEM_VECTOR_CLEAR(prog, entitypool);
MEM_VECTOR_CLEAR(prog, localstack);
MEM_VECTOR_CLEAR(prog, stack);
MEM_VECTOR_CLEAR(prog, profile);
if (prog->builtins_alloc) {
MEM_VECTOR_CLEAR(prog, builtins);
}
/* otherwise the builtins were statically allocated */
mem_d(prog);
}
/***********************************************************************
* VM code
*/
char* prog_getstring(qc_program *prog, qcint str)
{
if (str < 0 || str >= prog->strings_count)
return "<<<invalid string>>>";
return prog->strings + str;
}
prog_section_def* prog_entfield(qc_program *prog, qcint off)
{
size_t i;
for (i = 0; i < prog->fields_count; ++i) {
if (prog->fields[i].offset == off)
return (prog->fields + i);
}
return NULL;
}
prog_section_def* prog_getdef(qc_program *prog, qcint off)
{
size_t i;
for (i = 0; i < prog->defs_count; ++i) {
if (prog->defs[i].offset == off)
return (prog->defs + i);
}
return NULL;
}
qcany* prog_getedict(qc_program *prog, qcint e)
{
if (e >= prog->entitypool_count) {
prog->vmerror++;
printf("Accessing out of bounds edict %i\n", (int)e);
e = 0;
}
return (qcany*)(prog->entitydata + (prog->entityfields * e));
}
qcint prog_spawn_entity(qc_program *prog)
{
char *data;
size_t i;
qcint e;
for (e = 0; e < (qcint)prog->entitypool_count; ++e) {
if (!prog->entitypool[e]) {
data = (char*)(prog->entitydata + (prog->entityfields * e));
memset(data, 0, prog->entityfields * sizeof(qcint));
return e;
}
}
if (!qc_program_entitypool_add(prog, true)) {
prog->vmerror++;
printf("Failed to allocate entity\n");
return 0;
}
prog->entities++;
for (i = 0; i < prog->entityfields; ++i) {
if (!qc_program_entitydata_add(prog, 0)) {
printf("Failed to allocate entity\n");
return 0;
}
}
data = (char*)(prog->entitydata + (prog->entityfields * e));
memset(data, 0, prog->entityfields * sizeof(qcint));
return e;
}
void prog_free_entity(qc_program *prog, qcint e)
{
if (!e) {
prog->vmerror++;
printf("Trying to free world entity\n");
return;
}
if (e >= prog->entitypool_count) {
prog->vmerror++;
printf("Trying to free out of bounds entity\n");
return;
}
if (!prog->entitypool[e]) {
prog->vmerror++;
printf("Double free on entity\n");
return;
}
prog->entitypool[e] = false;
}
qcint prog_tempstring(qc_program *prog, const char *_str)
{
/* we don't access it, but the macro-generated functions don't use
* const
*/
char *str = (char*)_str;
size_t len = strlen(str);
size_t at = prog->tempstring_at;
/* when we reach the end we start over */
if (at + len >= prog->strings_count)
at = prog->tempstring_start;
/* when it doesn't fit, reallocate */
if (at + len >= prog->strings_count)
{
prog->strings_count = at;
if (!qc_program_strings_append(prog, str, len+1)) {
prog->vmerror = VMERR_TEMPSTRING_ALLOC;
return 0;
}
return at;
}
/* when it fits, just copy */
memcpy(prog->strings + at, str, len+1);
prog->tempstring_at += len+1;
return at;
}
static int print_escaped_string(const char *str, size_t maxlen)
{
int len = 2;
putchar('"');
--maxlen; /* because we're lazy and have escape sequences */
while (*str) {
if (len >= maxlen) {
putchar('.');
putchar('.');
putchar('.');
len += 3;
break;
}
switch (*str) {
case '\a': len += 2; putchar('\\'); putchar('a'); break;
case '\b': len += 2; putchar('\\'); putchar('b'); break;
case '\r': len += 2; putchar('\\'); putchar('r'); break;
case '\n': len += 2; putchar('\\'); putchar('n'); break;
case '\t': len += 2; putchar('\\'); putchar('t'); break;
case '\f': len += 2; putchar('\\'); putchar('f'); break;
case '\v': len += 2; putchar('\\'); putchar('v'); break;
case '\\': len += 2; putchar('\\'); putchar('\\'); break;
case '"': len += 2; putchar('\\'); putchar('"'); break;
default:
++len;
putchar(*str);
break;
}
++str;
}
putchar('"');
return len;
}
static void trace_print_global(qc_program *prog, unsigned int glob, int vtype)
{
static char spaces[28+1] = " ";
prog_section_def *def;
qcany *value;
int len;
if (!glob) {
len = printf("<null>,");
goto done;
}
def = prog_getdef(prog, glob);
value = (qcany*)(&prog->globals[glob]);
if (def) {
const char *name = prog_getstring(prog, def->name);
if (name[0] == '#')
len = printf("$");
else
len = printf("%s ", name);
vtype = def->type;
}
else
len = printf("[@%u] ", glob);
switch (vtype) {
case TYPE_VOID:
case TYPE_ENTITY:
case TYPE_FIELD:
case TYPE_FUNCTION:
case TYPE_POINTER:
len += printf("(%i),", value->_int);
break;
case TYPE_VECTOR:
len += printf("'%g %g %g',", value->vector[0],
value->vector[1],
value->vector[2]);
break;
case TYPE_STRING:
len += print_escaped_string(prog_getstring(prog, value->string), sizeof(spaces)-len-5);
len += printf(",");
/* len += printf("\"%s\",", prog_getstring(prog, value->string)); */
break;
case TYPE_FLOAT:
default:
len += printf("%g,", value->_float);
break;
}
done:
if (len < sizeof(spaces)-1) {
spaces[sizeof(spaces)-1-len] = 0;
printf(spaces);
spaces[sizeof(spaces)-1-len] = ' ';
}
}
static void prog_print_statement(qc_program *prog, prog_section_statement *st)
{
if (st->opcode >= (sizeof(asm_instr)/sizeof(asm_instr[0]))) {
printf("<illegal instruction %d>\n", st->opcode);
return;
}
printf(" <> %-12s", asm_instr[st->opcode].m);
if (st->opcode >= INSTR_IF &&
st->opcode <= INSTR_IFNOT)
{
trace_print_global(prog, st->o1.u1, TYPE_FLOAT);
printf("%d\n", st->o2.s1);
}
else if (st->opcode >= INSTR_CALL0 &&
st->opcode <= INSTR_CALL8)
{
printf("\n");
}
else if (st->opcode == INSTR_GOTO)
{
printf("%i\n", st->o1.s1);
}
else
{
int t[3] = { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT };
switch (st->opcode)
{
case INSTR_MUL_FV:
t[1] = t[2] = TYPE_VECTOR;
break;
case INSTR_MUL_VF:
t[0] = t[2] = TYPE_VECTOR;
break;
case INSTR_MUL_V:
t[0] = t[1] = TYPE_VECTOR;
break;
case INSTR_ADD_V:
case INSTR_SUB_V:
case INSTR_EQ_V:
case INSTR_NE_V:
t[0] = t[1] = t[2] = TYPE_VECTOR;
break;
case INSTR_EQ_S:
case INSTR_NE_S:
t[0] = t[1] = TYPE_STRING;
break;
case INSTR_STORE_F:
case INSTR_STOREP_F:
t[2] = -1;
break;
case INSTR_STORE_V:
t[0] = t[1] = TYPE_VECTOR; t[2] = -1;
break;
case INSTR_STORE_S:
t[0] = t[1] = TYPE_STRING; t[2] = -1;
break;
case INSTR_STORE_ENT:
t[0] = t[1] = TYPE_ENTITY; t[2] = -1;
break;
case INSTR_STORE_FLD:
t[0] = t[1] = TYPE_FIELD; t[2] = -1;
break;
case INSTR_STORE_FNC:
t[0] = t[1] = TYPE_FUNCTION; t[2] = -1;
break;
case INSTR_STOREP_V:
t[0] = TYPE_VECTOR; t[1] = TYPE_ENTITY; t[2] = -1;
break;
case INSTR_STOREP_S:
t[0] = TYPE_STRING; t[1] = TYPE_ENTITY; t[2] = -1;
break;
case INSTR_STOREP_ENT:
t[0] = TYPE_ENTITY; t[1] = TYPE_ENTITY; t[2] = -1;
break;
case INSTR_STOREP_FLD:
t[0] = TYPE_FIELD; t[1] = TYPE_ENTITY; t[2] = -1;
break;
case INSTR_STOREP_FNC:
t[0] = TYPE_FUNCTION; t[1] = TYPE_ENTITY; t[2] = -1;
break;
}
if (t[0] >= 0) trace_print_global(prog, st->o1.u1, t[0]);
else printf("(none), ");
if (t[1] >= 0) trace_print_global(prog, st->o2.u1, t[1]);
else printf("(none), ");
if (t[2] >= 0) trace_print_global(prog, st->o3.u1, t[2]);
else printf("(none)");
printf("\n");
}
fflush(stdout);
}
static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
{
qc_exec_stack st;
size_t p, parampos;
/* back up locals */
st.localsp = prog->localstack_count;
st.stmt = prog->statement;
st.function = func;
#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
if (prog->stack_count)
{
prog_section_function *cur;
cur = prog->stack[prog->stack_count-1].function;
if (cur)
{
qcint *globals = prog->globals + cur->firstlocal;
if (!qc_program_localstack_append(prog, globals, cur->locals))
{
printf("out of memory\n");
exit(1);
}
}
}
#else
{
qcint *globals = prog->globals + func->firstlocal;
if (!qc_program_localstack_append(prog, globals, func->locals))
{
printf("out of memory\n");
exit(1);
}
}
#endif
/* copy parameters */
parampos = func->firstlocal;
for (p = 0; p < func->nargs; ++p)
{
size_t s;
for (s = 0; s < func->argsize[p]; ++s) {
prog->globals[parampos] = prog->globals[OFS_PARM0 + 3*p + s];
++parampos;
}
}
if (!qc_program_stack_add(prog, st)) {
printf("out of memory\n");
exit(1);
}
return func->entry;
}
static qcint prog_leavefunction(qc_program *prog)
{
prog_section_function *prev = NULL;
size_t oldsp;
qc_exec_stack st = prog->stack[prog->stack_count-1];
#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
if (prog->stack_count > 1) {
prev = prog->stack[prog->stack_count-2].function;
oldsp = prog->stack[prog->stack_count-2].localsp;
}
#else
prev = prog->stack[prog->stack_count-1].function;
oldsp = prog->stack[prog->stack_count-1].localsp;
#endif
if (prev) {
qcint *globals = prog->globals + prev->firstlocal;
memcpy(globals, prog->localstack + oldsp, prev->locals);
if (!qc_program_localstack_resize(prog, oldsp)) {
printf("out of memory\n");
exit(1);
}
}
if (!qc_program_stack_remove(prog, prog->stack_count-1)) {
printf("out of memory\n");
exit(1);
}
return st.stmt - 1; /* offset the ++st */
}
bool prog_exec(qc_program *prog, prog_section_function *func, size_t flags, long maxjumps)
{
long jumpcount = 0;
size_t oldxflags = prog->xflags;
prog_section_statement *st;
prog->vmerror = 0;
prog->xflags = flags;
st = prog->code + prog_enterfunction(prog, func);
--st;
switch (flags)
{
default:
case 0:
{
#define QCVM_PROFILE 0
#define QCVM_TRACE 0
# include "execloop.h"
break;
}
case (VMXF_TRACE):
{
#define QCVM_PROFILE 0
#define QCVM_TRACE 1
# include "execloop.h"
break;
}
case (VMXF_PROFILE):
{
#define QCVM_PROFILE 1
#define QCVM_TRACE 0
# include "execloop.h"
break;
}
case (VMXF_TRACE|VMXF_PROFILE):
{
#define QCVM_PROFILE 1
#define QCVM_TRACE 1
# include "execloop.h"
break;
}
};
cleanup:
prog->xflags = oldxflags;
prog->localstack_count = 0;
prog->stack_count = 0;
if (prog->vmerror)
return false;
return true;
}
/***********************************************************************
* main for when building the standalone executor
*/
#if defined(QCVM_EXECUTOR)
#include <math.h>
const char *type_name[TYPE_COUNT] = {
"void",
"string",
"float",
"vector",
"entity",
"field",
"function",
"pointer",
#if 0
"integer",
#endif
"variant"
};
bool opts_debug = false;
bool opts_memchk = false;
typedef struct {
int vtype;
const char *value;
} qcvm_parameter;
VECTOR_MAKE(qcvm_parameter, main_params);
#define CheckArgs(num) do { \
if (prog->argc != (num)) { \
prog->vmerror++; \
printf("ERROR: invalid number of arguments for %s: %i, expected %i\n", \
__FUNCTION__, prog->argc, (num)); \
return -1; \
} \
} while (0)
#define GetGlobal(idx) ((qcany*)(prog->globals + (idx)))
#define GetArg(num) GetGlobal(OFS_PARM0 + 3*(num))
#define Return(any) *(GetGlobal(OFS_RETURN)) = (any)
static int qc_print(qc_program *prog)
{
size_t i;
const char *laststr = NULL;
for (i = 0; i < prog->argc; ++i) {
qcany *str = (qcany*)(prog->globals + OFS_PARM0 + 3*i);
printf("%s", (laststr = prog_getstring(prog, str->string)));
}
if (laststr && (prog->xflags & VMXF_TRACE)) {
size_t len = strlen(laststr);
if (!len || laststr[len-1] != '\n')
printf("\n");
}
return 0;
}
static int qc_error(qc_program *prog)
{
printf("*** VM raised an error:\n");
qc_print(prog);
prog->vmerror++;
return -1;
}
static int qc_ftos(qc_program *prog)
{
char buffer[512];
qcany *num;
qcany str;
CheckArgs(1);
num = GetArg(0);
snprintf(buffer, sizeof(buffer), "%g", num->_float);
str.string = prog_tempstring(prog, buffer);
Return(str);
return 0;
}
static int qc_vtos(qc_program *prog)
{
char buffer[512];
qcany *num;
qcany str;
CheckArgs(1);
num = GetArg(0);
snprintf(buffer, sizeof(buffer), "'%g %g %g'", num->vector[0], num->vector[1], num->vector[2]);
str.string = prog_tempstring(prog, buffer);
Return(str);
return 0;
}
static int qc_etos(qc_program *prog)
{
char buffer[512];
qcany *num;
qcany str;
CheckArgs(1);
num = GetArg(0);
snprintf(buffer, sizeof(buffer), "%i", num->_int);
str.string = prog_tempstring(prog, buffer);
Return(str);
return 0;
}
static int qc_spawn(qc_program *prog)
{
qcany ent;
CheckArgs(0);
ent.edict = prog_spawn_entity(prog);
Return(ent);
return (ent.edict ? 0 : -1);
}
static int qc_kill(qc_program *prog)
{
qcany *ent;
CheckArgs(1);
ent = GetArg(0);
prog_free_entity(prog, ent->edict);
return 0;
}
static int qc_vlen(qc_program *prog)
{
qcany *vec, len;
CheckArgs(1);
vec = GetArg(0);
len._float = sqrt(vec->vector[0] * vec->vector[0] +
vec->vector[1] * vec->vector[1] +
vec->vector[2] * vec->vector[2]);
Return(len);
return 0;
}
static prog_builtin qc_builtins[] = {
NULL,
&qc_print, /* 1 */
&qc_ftos, /* 2 */
&qc_spawn, /* 3 */
&qc_kill, /* 4 */
&qc_vtos, /* 5 */
&qc_error, /* 6 */
&qc_vlen, /* 7 */
&qc_etos /* 8 */
};
static size_t qc_builtins_count = sizeof(qc_builtins) / sizeof(qc_builtins[0]);
static const char *arg0 = NULL;
void usage()
{
printf("usage: [-debug] %s file\n", arg0);
exit(1);
}
static void prog_main_setparams(qc_program *prog)
{
size_t i;
qcany *arg;
for (i = 0; i < main_params_elements; ++i) {
arg = GetGlobal(OFS_PARM0 + 3*i);
arg->vector[0] = 0;
arg->vector[1] = 0;
arg->vector[2] = 0;
switch (main_params_data[i].vtype) {
case TYPE_VECTOR:
#ifdef WIN32
(void)sscanf_s(main_params_data[i].value, " %f %f %f ",
&arg->vector[0],
&arg->vector[1],
&arg->vector[2]);
#else
(void)sscanf(main_params_data[i].value, " %f %f %f ",
&arg->vector[0],
&arg->vector[1],
&arg->vector[2]);
#endif
break;
case TYPE_FLOAT:
arg->_float = atof(main_params_data[i].value);
break;
case TYPE_STRING:
arg->string = prog_tempstring(prog, main_params_data[i].value);
break;
default:
printf("error: unhandled parameter type: %i\n", main_params_data[i].vtype);
break;
}
}
}
int main(int argc, char **argv)
{
size_t i;
qcint fnmain = -1;
qc_program *prog;
size_t xflags = VMXF_DEFAULT;
bool opts_printfields = false;
bool opts_printdefs = false;
bool opts_info = false;
arg0 = argv[0];
if (argc < 2)
usage();
while (argc > 2) {
if (!strcmp(argv[1], "-trace")) {
--argc;
++argv;
xflags |= VMXF_TRACE;
}
else if (!strcmp(argv[1], "-profile")) {
--argc;
++argv;
xflags |= VMXF_PROFILE;
}
else if (!strcmp(argv[1], "-info")) {
--argc;
++argv;
opts_info = true;
}
else if (!strcmp(argv[1], "-printdefs")) {
--argc;
++argv;
opts_printdefs = true;
}
else if (!strcmp(argv[1], "-printfields")) {
--argc;
++argv;
opts_printfields = true;
}
else if (!strcmp(argv[1], "-vector") ||
!strcmp(argv[1], "-string") ||
!strcmp(argv[1], "-float") )
{
qcvm_parameter p;
if (argv[1][1] == 'f')
p.vtype = TYPE_FLOAT;
else if (argv[1][1] == 's')
p.vtype = TYPE_STRING;
else if (argv[1][1] == 'v')
p.vtype = TYPE_VECTOR;
--argc;
++argv;
if (argc < 3)
usage();
p.value = argv[1];
if (main_params_add(p) < 0) {
if (main_params_data)
mem_d(main_params_data);
printf("cannot add parameter\n");
exit(1);
}
--argc;
++argv;
}
else
usage();
}
prog = prog_load(argv[1]);
if (!prog) {
printf("failed to load program '%s'\n", argv[1]);
exit(1);
}
prog->builtins = qc_builtins;
prog->builtins_count = qc_builtins_count;
prog->builtins_alloc = 0;
if (opts_info) {
printf("Program's system-checksum = 0x%04x\n", (int)prog->crc16);
printf("Entity field space: %i\n", (int)prog->entityfields);
}
for (i = 1; i < prog->functions_count; ++i) {
const char *name = prog_getstring(prog, prog->functions[i].name);
/* printf("Found function: %s\n", name); */
if (!strcmp(name, "main"))
fnmain = (qcint)i;
}
if (opts_info) {
prog_delete(prog);
return 0;
}
if (opts_printdefs) {
for (i = 0; i < prog->defs_count; ++i) {
printf("Global: %8s %-16s at %u\n",
type_name[prog->defs[i].type & DEF_TYPEMASK],
prog_getstring(prog, prog->defs[i].name),
(unsigned int)prog->defs[i].offset);
}
}
else if (opts_printfields) {
for (i = 0; i < prog->fields_count; ++i) {
printf("Field: %8s %-16s at %u\n",
type_name[prog->fields[i].type],
prog_getstring(prog, prog->fields[i].name),
(unsigned int)prog->fields[i].offset);
}
}
else
{
if (fnmain > 0)
{
prog_main_setparams(prog);
prog_exec(prog, &prog->functions[fnmain], xflags, VM_JUMPS_DEFAULT);
}
else
printf("No main function found\n");
}
prog_delete(prog);
return 0;
}
#endif

1624
exec.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,349 +0,0 @@
#if 0
/* Expected variables */
qc_program *prog;
#endif
#define OPA ( (qcany*) (prog->globals + st->o1.u1) )
#define OPB ( (qcany*) (prog->globals + st->o2.u1) )
#define OPC ( (qcany*) (prog->globals + st->o3.u1) )
#define GLOBAL(x) ( (qcany*) (prog->globals + (x)) )
/* to be consistent with current darkplaces behaviour */
#if !defined(FLOAT_IS_TRUE_FOR_INT)
# define FLOAT_IS_TRUE_FOR_INT(x) ( (x) & 0x7FFFFFFF )
#endif
while (1) {
prog_section_function *newf;
qcany *ed;
qcany *ptr;
++st;
#if QCVM_PROFILE
prog->profile[st - prog->code]++;
#endif
#if QCVM_TRACE
prog_print_statement(prog, st);
#endif
switch (st->opcode)
{
default:
qcvmerror(prog, "Illegal instruction in %s\n", prog->filename);
goto cleanup;
case INSTR_DONE:
case INSTR_RETURN:
/* TODO: add instruction count to function profile count */
GLOBAL(OFS_RETURN)->ivector[0] = OPA->ivector[0];
GLOBAL(OFS_RETURN)->ivector[1] = OPA->ivector[1];
GLOBAL(OFS_RETURN)->ivector[2] = OPA->ivector[2];
st = prog->code + prog_leavefunction(prog);
if (!prog->stack_count)
goto cleanup;
break;
case INSTR_MUL_F:
OPC->_float = OPA->_float * OPB->_float;
break;
case INSTR_MUL_V:
OPC->_float = OPA->vector[0]*OPB->vector[0] +
OPA->vector[1]*OPB->vector[1] +
OPA->vector[2]*OPB->vector[2];
break;
case INSTR_MUL_FV:
OPC->vector[0] = OPA->_float * OPB->vector[0];
OPC->vector[1] = OPA->_float * OPB->vector[1];
OPC->vector[2] = OPA->_float * OPB->vector[2];
break;
case INSTR_MUL_VF:
OPC->vector[0] = OPB->_float * OPA->vector[0];
OPC->vector[1] = OPB->_float * OPA->vector[1];
OPC->vector[2] = OPB->_float * OPA->vector[2];
break;
case INSTR_DIV_F:
if (OPB->_float != 0.0f)
OPC->_float = OPA->_float / OPB->_float;
else
OPC->_float = 0;
break;
case INSTR_ADD_F:
OPC->_float = OPA->_float + OPB->_float;
break;
case INSTR_ADD_V:
OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
break;
case INSTR_SUB_F:
OPC->_float = OPA->_float - OPB->_float;
break;
case INSTR_SUB_V:
OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
break;
case INSTR_EQ_F:
OPC->_float = (OPA->_float == OPB->_float);
break;
case INSTR_EQ_V:
OPC->_float = ((OPA->vector[0] == OPB->vector[0]) &&
(OPA->vector[1] == OPB->vector[1]) &&
(OPA->vector[2] == OPB->vector[2]) );
break;
case INSTR_EQ_S:
OPC->_float = !strcmp(prog_getstring(prog, OPA->string),
prog_getstring(prog, OPB->string));
break;
case INSTR_EQ_E:
OPC->_float = (OPA->_int == OPB->_int);
break;
case INSTR_EQ_FNC:
OPC->_float = (OPA->function == OPB->function);
break;
case INSTR_NE_F:
OPC->_float = (OPA->_float != OPB->_float);
break;
case INSTR_NE_V:
OPC->_float = ((OPA->vector[0] != OPB->vector[0]) ||
(OPA->vector[1] != OPB->vector[1]) ||
(OPA->vector[2] != OPB->vector[2]) );
break;
case INSTR_NE_S:
OPC->_float = !!strcmp(prog_getstring(prog, OPA->string),
prog_getstring(prog, OPB->string));
break;
case INSTR_NE_E:
OPC->_float = (OPA->_int != OPB->_int);
break;
case INSTR_NE_FNC:
OPC->_float = (OPA->function != OPB->function);
break;
case INSTR_LE:
OPC->_float = (OPA->_float <= OPB->_float);
break;
case INSTR_GE:
OPC->_float = (OPA->_float >= OPB->_float);
break;
case INSTR_LT:
OPC->_float = (OPA->_float < OPB->_float);
break;
case INSTR_GT:
OPC->_float = (OPA->_float > OPB->_float);
break;
case INSTR_LOAD_F:
case INSTR_LOAD_S:
case INSTR_LOAD_FLD:
case INSTR_LOAD_ENT:
case INSTR_LOAD_FNC:
if (OPA->edict < 0 || OPA->edict >= prog->entities) {
qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
goto cleanup;
}
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields)) {
qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
prog->filename,
OPB->_int);
goto cleanup;
}
ed = prog_getedict(prog, OPA->edict);
OPC->_int = ((qcany*)( ((qcint*)ed) + OPB->_int ))->_int;
break;
case INSTR_LOAD_V:
if (OPA->edict < 0 || OPA->edict >= prog->entities) {
qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
goto cleanup;
}
if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfields)
{
qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
prog->filename,
OPB->_int + 2);
goto cleanup;
}
ed = prog_getedict(prog, OPA->edict);
OPC->ivector[0] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[0];
OPC->ivector[1] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[1];
OPC->ivector[2] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[2];
break;
case INSTR_ADDRESS:
if (OPA->edict < 0 || OPA->edict >= prog->entities) {
qcvmerror(prog, "prog `%s` attempted to address an out of bounds entity %i", prog->filename, OPA->edict);
goto cleanup;
}
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
{
qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
prog->filename,
OPB->_int);
goto cleanup;
}
ed = prog_getedict(prog, OPA->edict);
OPC->_int = ((qcint*)ed) - prog->entitydata;
OPC->_int += OPB->_int;
break;
case INSTR_STORE_F:
case INSTR_STORE_S:
case INSTR_STORE_ENT:
case INSTR_STORE_FLD:
case INSTR_STORE_FNC:
OPB->_int = OPA->_int;
break;
case INSTR_STORE_V:
OPB->ivector[0] = OPA->ivector[0];
OPB->ivector[1] = OPA->ivector[1];
OPB->ivector[2] = OPA->ivector[2];
break;
case INSTR_STOREP_F:
case INSTR_STOREP_S:
case INSTR_STOREP_ENT:
case INSTR_STOREP_FLD:
case INSTR_STOREP_FNC:
if (OPB->_int < 0 || OPB->_int >= prog->entitydata_count) {
qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
goto cleanup;
}
if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
prog->filename,
prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
OPB->_int);
ptr = (qcany*)(prog->entitydata + OPB->_int);
ptr->_int = OPA->_int;
break;
case INSTR_STOREP_V:
if (OPB->_int < 0 || OPB->_int + 2 >= prog->entitydata_count) {
qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
goto cleanup;
}
if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
prog->filename,
prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
OPB->_int);
ptr = (qcany*)(prog->entitydata + OPB->_int);
ptr->ivector[0] = OPA->ivector[0];
ptr->ivector[1] = OPA->ivector[1];
ptr->ivector[2] = OPA->ivector[2];
break;
case INSTR_NOT_F:
OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
break;
case INSTR_NOT_V:
OPC->_float = !OPA->vector[0] &&
!OPA->vector[1] &&
!OPA->vector[2];
break;
case INSTR_NOT_S:
OPC->_float = !OPA->string ||
!*prog_getstring(prog, OPA->string);
break;
case INSTR_NOT_ENT:
OPC->_float = (OPA->edict == 0);
break;
case INSTR_NOT_FNC:
OPC->_float = !OPA->function;
break;
case INSTR_IF:
/* this is consistent with darkplaces' behaviour */
if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
{
st += st->o2.s1 - 1; /* offset the s++ */
if (++jumpcount >= maxjumps)
qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
}
break;
case INSTR_IFNOT:
if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
{
st += st->o2.s1 - 1; /* offset the s++ */
if (++jumpcount >= maxjumps)
qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
}
break;
case INSTR_CALL0:
case INSTR_CALL1:
case INSTR_CALL2:
case INSTR_CALL3:
case INSTR_CALL4:
case INSTR_CALL5:
case INSTR_CALL6:
case INSTR_CALL7:
case INSTR_CALL8:
prog->argc = st->opcode - INSTR_CALL0;
if (!OPA->function)
qcvmerror(prog, "NULL function in `%s`", prog->filename);
if(!OPA->function || OPA->function >= (unsigned int)prog->functions_count)
{
qcvmerror(prog, "CALL outside the program in `%s`", prog->filename);
goto cleanup;
}
newf = &prog->functions[OPA->function];
newf->profile++;
prog->statement = (st - prog->code) + 1;
if (newf->entry < 0)
{
/* negative statements are built in functions */
int builtinnumber = -newf->entry;
if (builtinnumber < prog->builtins_count && prog->builtins[builtinnumber])
prog->builtins[builtinnumber](prog);
else
qcvmerror(prog, "No such builtin #%i in %s! Try updating your gmqcc sources",
builtinnumber, prog->filename);
}
else
st = prog->code + prog_enterfunction(prog, newf) - 1; /* offset st++ */
if (prog->vmerror)
goto cleanup;
break;
case INSTR_STATE:
qcvmerror(prog, "`%s` tried to execute a STATE operation", prog->filename);
break;
case INSTR_GOTO:
st += st->o1.s1 - 1; /* offset the s++ */
if (++jumpcount == 10000000)
qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
break;
case INSTR_AND:
OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) &&
FLOAT_IS_TRUE_FOR_INT(OPB->_int);
break;
case INSTR_OR:
OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) ||
FLOAT_IS_TRUE_FOR_INT(OPB->_int);
break;
case INSTR_BITAND:
OPC->_float = ((int)OPA->_float) & ((int)OPB->_float);
break;
case INSTR_BITOR:
OPC->_float = ((int)OPA->_float) | ((int)OPB->_float);
break;
}
}
#undef QCVM_PROFILE
#undef QCVM_TRACE

View file

@ -1,8 +0,0 @@
#ifndef GMQCC_DEFINE_FLAG
#define GMQCC_DEFINE_FLAG(x)
#endif
GMQCC_DEFINE_FLAG(OVERLAP_LOCALS)
GMQCC_DEFINE_FLAG(DARKPLACES_STRING_TABLE_BUG)
GMQCC_DEFINE_FLAG(OMIT_NULL_BYTES)
GMQCC_DEFINE_FLAG(ADJUST_VECTOR_FIELDS)

1679
fold.cpp Normal file

File diff suppressed because it is too large Load diff

121
fold.h Normal file
View file

@ -0,0 +1,121 @@
#ifndef GMQCC_FOLD_HDR
#define GMQCC_FOLD_HDR
#include "lexer.h"
#include "gmqcc.h"
struct ir_builder;
struct ir_value;
struct ast_function;
struct ast_ifthen;
struct ast_ternary;
struct ast_expression;
struct ast_value;
struct parser_t;
struct fold {
fold();
fold(parser_t *parser);
~fold();
// Bitmask describing which branches of a conditional to take after folding.
// Zero indicates all the branches can be removed.
// ON_TRUE means ON_FALSE can be removed.
// ON_FALSE means ON_TRUE can be removed.
// ON_TRUE | ON_FALSE means nothing can be removed.
enum {
ON_TRUE = 1 << 0,
ON_FALSE = 1 << 1,
};
bool generate(ir_builder *ir);
ast_expression *op(const oper_info *info, ast_expression **opexprs);
ast_expression *intrinsic(const char *intrinsic, size_t n_args, ast_expression **args);
static uint32_t cond_ternary(ast_value *condval, ast_ternary *branch);
static uint32_t cond_ifthen(ast_value *condval, ast_ifthen *branch);
static ast_expression *superfluous(ast_expression *left, ast_expression *right, int op);
static ast_expression *binary(lex_ctx_t ctx, int op, ast_expression *left, ast_expression *right);
ast_expression *constgen_float(qcfloat_t value, bool inexact);
ast_expression *constgen_vector(vec3_t value);
ast_expression *constgen_string(const char *str, bool translate);
ast_expression *constgen_string(const std::string &str, bool translate);
ast_value *imm_float(size_t index) const { return m_imm_float[index]; }
ast_value *imm_vector(size_t index) const { return m_imm_vector[index]; }
protected:
static qcfloat_t immvalue_float(ast_value *value);
static vec3_t immvalue_vector(ast_value *value);
static const char *immvalue_string(ast_value *value);
lex_ctx_t ctx();
bool immediate_true(ast_value *v);
bool check_except_float_impl(void (*callback)(void), ast_value *a, ast_value *b);
bool check_inexact_float(ast_value *a, ast_value *b);
ast_expression *op_mul_vec(vec3_t vec, ast_value *sel, const char *set);
ast_expression *op_neg(ast_value *a);
ast_expression *op_not(ast_value *a);
ast_expression *op_add(ast_value *a, ast_value *b);
ast_expression *op_sub(ast_value *a, ast_value *b);
ast_expression *op_mul(ast_value *a, ast_value *b);
ast_expression *op_div(ast_value *a, ast_value *b);
ast_expression *op_mod(ast_value *a, ast_value *b);
ast_expression *op_bor(ast_value *a, ast_value *b);
ast_expression *op_band(ast_value *a, ast_value *b);
ast_expression *op_xor(ast_value *a, ast_value *b);
ast_expression *op_lshift(ast_value *a, ast_value *b);
ast_expression *op_rshift(ast_value *a, ast_value *b);
ast_expression *op_andor(ast_value *a, ast_value *b, float expr);
ast_expression *op_tern(ast_value *a, ast_value *b, ast_value *c);
ast_expression *op_exp(ast_value *a, ast_value *b);
ast_expression *op_lteqgt(ast_value *a, ast_value *b);
ast_expression *op_ltgt(ast_value *a, ast_value *b, bool lt);
ast_expression *op_cmp(ast_value *a, ast_value *b, bool ne);
ast_expression *op_bnot(ast_value *a);
ast_expression *op_cross(ast_value *a, ast_value *b);
ast_expression *op_length(ast_value *a);
ast_expression *intrinsic_isfinite(ast_value *a);
ast_expression *intrinsic_isinf(ast_value *a);
ast_expression *intrinsic_isnan(ast_value *a);
ast_expression *intrinsic_isnormal(ast_value *a);
ast_expression *intrinsic_signbit(ast_value *a);
ast_expression *intrinsic_acosh(ast_value *a);
ast_expression *intrinsic_asinh(ast_value *a);
ast_expression *intrinsic_atanh(ast_value *a);
ast_expression *intrinsic_exp(ast_value *a);
ast_expression *intrinsic_exp2(ast_value *a);
ast_expression *intrinsic_expm1(ast_value *a);
ast_expression *intrinsic_pow(ast_value *lhs, ast_value *rhs);
ast_expression *intrinsic_mod(ast_value *lhs, ast_value *rhs);
ast_expression *intrinsic_fabs(ast_value *a);
ast_expression* intrinsic_nan(void);
ast_expression* intrinsic_epsilon(void);
ast_expression* intrinsic_inf(void);
static qcfloat_t immvalue_float(ir_value *value);
static vec3_t immvalue_vector(ir_value *value);
static uint32_t cond(ast_value *condval, ast_ifthen *branch);
private:
friend struct intrin;
std::vector<ast_value*> m_imm_float;
std::vector<ast_value*> m_imm_vector;
std::vector<ast_value*> m_imm_string;
hash_table_t *m_imm_string_untranslate; /* map<string, ast_value*> */
hash_table_t *m_imm_string_dotranslate; /* map<string, ast_value*> */
parser_t *m_parser;
bool m_initialized;
};
#endif

1947
ftepp.cpp Normal file

File diff suppressed because it is too large Load diff

1420
gmqcc.h

File diff suppressed because it is too large Load diff

745
gmqcc.ini.example Normal file
View file

@ -0,0 +1,745 @@
#This configuration file is similar to a regular .ini file. Comments start
#with hashtags or semicolons, sections are written in square brackets and
#in each section there can be arbitrary many key-value pairs.
#There are 3 sections currently: flags, warnings, optimizations.
#They contain a list of boolean values of the form VARNAME = true or
#VARNAME = false. The variable names are the same as for the corre
#sponding -W, -f or -O flag written with only capital letters and dashes
#replaced by underscores.
[flags]
#Add some additional characters to the string table in order to
#compensate for a wrong boundcheck in some specific version of the
#darkplaces engine.
DARKPLACES_STRING_TABLE_BUG = true
#When assigning to field pointers of type .vector the common be
#haviour in compilers like fteqcc is to only assign the x-compo
#nent of the pointer. This means that you can use the vector as
#such, but you cannot use its y and z components directly. This
#flag fixes this behaviour. Before using it make sure your code
#does not depend on the buggy behaviour.
ADJUST_VECTOR_FIELDS = true
#Enable a partially fteqcc-compatible preprocessor. It supports
#all the features used in the Xonotic codebase. If you need more,
#write a ticket.
FTEPP = true
#Enable some predefined macros. This only works in combination
#with '-fftepp' and is currently not included by '-std=fteqcc'.
#The following macros will be added:
#
# __LINE__
# __FILE__
# __COUNTER__
# __COUNTER_LAST__
# __RANDOM__
# __RANDOM_LAST__
# __DATE__
# __TIME__
# __FUNC__
#
#Note that __FUNC__ is not actually a preprocessor macro, but is
#recognized by the parser even with the preprocessor disabled.
#
#Note that fteqcc also defines __NULL__ which becomes the first
#global. Assigning it to a vector does not yield the same result
#as in gmqcc where __NULL__ is defined to nil (See -funtyped-nil
#), which will cause the vector to be zero in all components. With
#fteqcc only the first component will be 0, while the other two
#will become the first to of the global return value. This behav
#ior is odd and relying on it should be discouraged, and thus is
#not supported by gmqcc.
FTEPP_PREDEFS = false
#Enable math constant definitions. This only works in combination
#with '-fftepp' and is currently not included by '-std=fteqcc'.
#The following macros will be added:
#
# M_E
# M_LOG2E
# M_LOG10E
# M_LN2
# M_LN10
# M_PI
# M_PI_2
# M_PI_4
# M_1_PI
# M_2_PI
# M_2_SQRTPI
# M_SQRT2
# M_SQRT1_2
# M_TAU
FTEPP_MATHDEFS = false
#Enable indirect macro expansion. This only works in combination
#with '-fftepp' and is currently not included by '-std=fteqcc'.
#Enabling this behavior will allow the preprocessor to operate more
#like the standard C preprocessor in that it will allow arguments
#of macros which are macro-expanded to be substituted into the
#definition of the macro. As an example:
#
# #define STR1(x) #x
# #define STR2(x) STR1(x)
# #define THE_ANSWER 42
# #define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
#
#With this enabled, an expansion of THE_ANSWER_STR will yield
#the string "42". With this disabled an expansion of THE_ANSWER_STR
#will yield "THE_ANSWER"
FTEPP_INDIRECT_EXPANSION = false
#Allow switch cases to use non constant variables.
RELAXED_SWITCH = true
#Perform early out in logical AND and OR expressions. The final
#result will be either a 0 or a 1, see the next flag for more pos
#sibilities.
SHORT_LOGIC = true
#In many languages, logical expressions perform early out in a
#special way: If the left operand of an AND yeilds true, or the
#one of an OR yields false, the complete expression evaluates to
#the right side. Thus true && 5 evaluates to 5 rather than 1.
PERL_LOGIC = false
#Enable the underscore intrinsic: Using _("A string constant")
#will cause the string immediate to get a name with a "dotrans
#late_" prefix. The darkplaces engine recognizes these and trans
#lates them in a way similar to how gettext works.
TRANSLATABLE_STRINGS = true
#Don't implicitly convert initialized variables to constants. With
#this flag, the const keyword is required to make a constant.
INITIALIZED_NONCONSTANTS = false
#If this flag is not set, (and it is set by default in the qcc and
#fteqcc standards), assigning function pointers of mismatching
#signatures will result in an error rather than a warning.
ASSIGN_FUNCTION_TYPES = true
#Produce a linenumber file along with the output .dat file.
LNO = false
#Use C's operator precedence for ternary expressions. Unless your
#code depends on fteqcc-compatible behaviour, you'll want to use
#this option.
CORRECT_TERNARY = true
#Normally vectors generate 4 defs, once for the vector, and once
#for its components with _x, _y, _z suffixes. This option prevents
#components from being listed.
SINGLE_VECTOR_DEFS = true
#Most QC compilers translate if(a_vector) directly as an IF on
#the vector, which means only the x-component is checked. This
#option causes vectors to be cast to actual booleans via a NOT_V
#and, if necessary, a NOT_F chained to it.
#
# if (a_vector) // becomes
# if not(!a_vector)
# // likewise
# a = a_vector && a_float // becomes
# a = !!a_vector && a_float
CORRECT_LOGIC = true
#An empty string is considered to be true everywhere. The NOT_S
#instruction usually considers an empty string to be false, this
#option effectively causes the unary not in strings to use NOT_F
#instead.
TRUE_EMPTY_STRINGS = false
#An empty string is considered to be false everywhere. This means
#loops and if statements which depend on a string will perform a
#NOT_S instruction on the string before using it.
FALSE_EMPTY_STRINGS = true
#Enable utf8 characters. This allows utf-8 encoded character con
#stants, and escape sequence codepoints in the valid utf-8 range.
#Effectively enabling escape sequences like '\{x2211}'.
UTF8 = true
#When a warning is treated as an error, and this option is set
#(which it is by default), it is like any other error and will
#cause compilation to stop. When disabling this flag by using
#-fno-bail-on-werror, compilation will continue until the end, but
#no output is generated. Instead the first such error message's
#context is shown.
BAIL_ON_WERROR = false
#Allow loops to be labeled, and allow 'break' and 'continue' to
#take an optional label to decide which loop to actually jump out
#of or continue.
#
# for :outer (i = 0; i < n; ++i) {
# while (inner) {
# ...;
# if (something)
# continue outer;
# }
# }
LOOP_LABELS = true
#Adds a global named 'nil' which is of no type and can be assigned
#to anything. No typechecking will be performed on assignments.
#Assigning to it is forbidden, using it in any other kind of
#expression is also not allowed.
#
#Note that this is different from fteqcc's __NULL__: In fteqcc,
#__NULL__ maps to the integer written as '0i'. It's can be
#assigned to function pointers and integers, but it'll error about
#invalid instructions when assigning it to floats without enabling
#the FTE instruction set. There's also a bug which allows it to be
#assigned to vectors, for which the source will be the global at
#offset 0, meaning the vector's y and z components will contain
#the OFS_RETURN x and y components.#
#
#In that gmqcc the nil global is an actual global filled with
#zeroes, and can be assigned to anything including fields, vectors
#or function pointers, and they end up becoming zeroed.
UNTYPED_NIL = true
#Various effects, usually to weaken some conditions.
# with -funtyped-nil
# Allow local variables named nil. (This will not
# allow declaring a global of that name.)
PERMISSIVE = false
#Allow variadic parameters to be accessed by QC code. This can be
#achieved via the '...' function, which takes a parameter index
#and a typename.
#
#Example:
#
# void vafunc(string...count) {
# float i;
# for (i = 0; i < count; ++i)
# print(...(i, string), "\n");
# }
VARIADIC_ARGS = true
#Most Quake VMs, including the one from FTEQW or up till recently
#Darkplaces, do not cope well with vector instructions with over
#lapping input and output. This option will avoid producing such
#code.
LEGACY_VECTOR_MATHS = false
#Usually builtin-numbers are just immediate constants. With this
#flag expressions can be used, as long as they are compile-time
#constant.
#
#Example:
#
# void printA() = #1; // the usual way
# void printB() = #2-1; // with a constant expression
EXPRESSIONS_FOR_BUILTINS = true
#Enabiling this option will allow assigning values or expressions
#to the return keyword as if it were a local variable of the same
#type as the function's signature's return type.
#
#Example:
#
# float bar() { return 1024; }
# float fun() {
# return = bar();
# return; // returns value of bar (this can be omitted)
# }
RETURN_ASSIGNMENTS = true
#When passing on varargs to a different functions, this turns some
#static error cases into warnings. Like when the caller's varargs
#are restricted to a different type than the callee's parameter.
#Or a list of unrestricted varargs is passed into restricted
#varargs.
UNSAFE_VARARGS = false
#Always use STORE_F, LOAD_F, STOREP_F when accessing scalar variables.
#This is somewhat incorrect assembly instruction use, but in all engines
#they do exactly the same. This makes disassembly output harder to read,
#breaks decompilers, but causes the output file to be better compressible.
TYPELESS_STORES = false
#In commutative instructions, always put the lower-numbered operand first.
#This shaves off 1 byte of entropy from all these instructions, reducing
#compressed size of the output file.
SORT_OPERANDS = false
#Emulate OP_STATE operations in code rather than using the instruction.
#The desired fps can be set via -state-fps=NUM, defaults to 10.
EMULATE_STATE = false
#Turn on arithmetic exception tests in the compiler. In constant expressions
#which trigger exceptions like division by zero, overflow, underflow, etc,
#the following flag will produce diagnostics for what triggered that
#exception.
ARITHMETIC_EXCEPTIONS = false
#Split vector-literals which are only used dirctly as function parameters
#into 3 floats stored separately to reduce the number of globals at the
#expense of additional instructions.
SPLIT_VECTOR_PARAMETERS = false
#Force all expressions to be "eraseable" which permits the compiler
#to remove unused functions, variables and statements. This is
#equivlant to putting [[eraseable]] on all definitions. This is
#dangerous as it breaks auto cvars, definitions for functions the
#engine may be looking for and translatable strings. Instead, you
#can mark a definition with [[noerase]] to prevent this from happening.
DEFAULT_ERASEABLE = false
[warnings]
#Generate a warning about variables which are declared but never
#used. This can be avoided by adding the noref keyword in front
#of the variable declaration. Additionally a complete section of
#unreferenced variables can be opened using #pragma noref 1 and
#closed via #pragma noref 0.
UNUSED_VARIABLE = false
#Generate a warning about vector variables which are declared but
#components of it are never used.
UNUSED_COMPONENT = false
#Generate a warning if it is possible that a variable can be used
#without prior initialization. Note that this warning is not nec
#essarily reliable if the initialization happens only under cer
#tain conditions. The other way is not possible: that the warning
#is not generated when uninitialized use is possible.
USED_UNINITIALIZED = false
#Generate an error when an unrecognized control sequence in a
#string is used. Meaning: when there's a character after a back
#slash in a string which has no known meaning.
UNKNOWN_CONTROL_SEQUENCE = false
#Warn when using special extensions which are not part of the
#selected standard.
EXTENSIONS = false
#Generally QC compilers ignore redeclaration of fields. Here you
#can optionally enable a warning.
FIELD_REDECLARED = false
#Functions which aren't of type void will warn if it possible to
#reach the end without returning an actual value.
MISSING_RETURN_VALUES = false
#Warn about a function call with an invalid number of parameters.
INVALID_PARAMETER_COUNT = false
#Warn when a locally declared variable shadows variable.
LOCAL_SHADOWS = false
#Warn when the initialization of a local variable turns the vari
#able into a constant. This is default behaviour unless
#-finitialized-nonconstants is used.
LOCAL_CONSTANTS = false
#There are only 2 known global variables of type void:
#end_sys_globals and end_sys_fields. Any other void-variable
#will warn.
VOID_VARIABLES = false
#A global function which is not declared with the var keyword is
#expected to have an implementing body, or be a builtin. If nei
#ther is the case, it implicitly becomes a function pointer, and a
#warning is generated.
IMPLICIT_FUNCTION_POINTER = false
#Currently there's no way for an in QC implemented function to
#access variadic parameters. If a function with variadic parame
#ters has an implementing body, a warning will be generated.
VARIADIC_FUNCTION = false
#Generate warnings about $frame commands, for instance about
#duplicate frame definitions.
FRAME_MACROS = false
#Warn about statements which have no effect. Any expression which
#does not call a function or assigns a variable.
EFFECTLESS_STATEMENT = false
#The end_sys_fields variable is supposed to be a global variable
#of type void. It is also recognized as a field but this will
#generate a warning.
END_SYS_FIELDS = false
#Warn when assigning to a function pointer with an unmatching sig
#nature. This usually happens in cases like assigning the null
#function to an entity's .think function pointer.
ASSIGN_FUNCTION_TYPES = false
#Show warnings created using the preprocessor's '#warning' directive
CPP = true
#Warn if there's a preprocessor #if spanning across several files.
MULTIFILE_IF = true
#Warn about multiple declarations of globals. This seems pretty
#common in QC code so you probably do not want this unless you
#want to clean up your code.
DOUBLE_DECLARATION = false
#The combination of const and var is not illegal, however differ
#ent compilers may handle them differently. We were told, the
#intention is to create a function-pointer which is not assigna
#ble. This is exactly how we interpret it. However for this
#interpretation the var keyword is considered superfluous (and
#philosophically wrong), so it is possible to generate a warning
#about this.
CONST_VAR = true
#Warn about multibyte character constants, they do not work right
#now.
MULTIBYTE_CHARACTER = false
#Warn if a ternary expression which contains a comma operator is
#used without enclosing parenthesis, since this is most likely not
#what you actually want. We recommend the -fcorrect-ternary
#option.
TERNARY_PRECEDENCE = false
#Warn when encountering an unrecognized #pragma line.
UNKNOWN_PRAGMAS = true
#Warn about unreachable code. That is: code after a return state
#ment, or code after a call to a function marked as 'noreturn'.
UNREACHABLE_CODE = true
#Enable some warnings added in order to help debugging in the com
#piler. You won't need this.
DEBUG = false
#Warn on an unknown attribute. The warning will inlclude only the
#first token inside the enclosing attribute-brackets. This may
#change when the actual attribute syntax is better defined.
UNKNOWN_ATTRIBUTE = true
#Warn when using reserved names such as nil.
RESERVED_NAMES = true
#Warn about global constants (using the const keyword) with no
#assigned value.
UNINITIALIZED_CONSTANT = true
#Warn about global variables with no initializing value. This is
#off by default, and is added mostly to help find null-values
#which are supposed to be replaced by the untyped 'nil' constant.
UNINITIALIZED_GLOBAL = true
#Warn when a variables is redeclared with a different qualifier.
#For example when redeclaring a variable as 'var' which was previ
#ously marked 'const'.
DIFFERENT_QUALIFIERS = true
#Similar to the above but for attributes like [[noreturn]].
DIFFERENT_ATTRIBUTES = true
#Warn when a function is marked with the attribute "[[depre
#cated]]". This flag enables a warning on calls to functions
#marked as such.
DEPRECATED = true
#Warn about possible mistakes caused by missing or wrong parenthe
#sis, like an assignment in an 'if' condition when there's no
#additional set of parens around the assignment.
PARENTHESIS = true
#When passing variadic parameters via ...(N) it can happen that
#incompatible types are passed to functions. This enables several
#warnings when static typechecking cannot guarantee consistent
#behavior.
UNSAFE_TYPES = true
#When compiling original id1 QC there is a definition for `break`
#which conflicts with the 'break' keyword in GMQCC. Enabling this
#print a warning when the definition occurs. The definition is
#ignored for both cases.
BREAKDEF = true
#When compiling original QuakeWorld QC there are instances where
#code overwrites constants. This is considered an error, however
#for QuakeWorld to compile it needs to be treated as a warning
#instead, as such this warning only works when -std=qcc.
CONST_OVERWRITE = true
#Warn about the use of preprocessor directives inside macros.
DIRECTIVE_INMACRO = true
#When using a function that is not explicitly defined, the compiler
#will search its intrinsics table for something that matches that
#function name by appending "__builtin_" to it. This behaviour may
#be unexpected, so enabling this will produce a diagnostic when
#such a function is resolved to a builtin.
BUILTINS = true
#When comparing an inexact value such as `1.0/3.0' the result is
#pathologically wrong. Enabling this will trigger a compiler warning
#on such expressions.
INEXACT_COMPARES = true
[optimizations]
#Some general peephole optimizations. For instance the code `a = b
#+ c` typically generates 2 instructions, an ADD and a STORE. This
#optimization removes the STORE and lets the ADD write directly
#into A.
PEEPHOLE = true
#Tail recursive function calls will be turned into loops to avoid
#the overhead of the CALL and RETURN instructions.
TAIL_RECURSION = true
#Make all functions which use neither local arrays nor have locals
#which are seen as possibly uninitialized use the same local sec
#tion. This should be pretty safe compared to other compilers
#which do not check for uninitialized values properly. The problem
#is that there's QC code out there which really doesn't initialize
#some values. This is fine as long as this kind of optimization
#isn't used, but also, only as long as the functions cannot be
#called in a recursive manner. Since it's hard to know whether or
#not an array is actually fully initialized, especially when ini
#tializing it via a loop, we assume functions with arrays to be
#too dangerous for this optimization.
OVERLAP_LOCALS = true
#This promotes locally declared variables to "temps". Meaning when
#a temporary result of an operation has to be stored somewhere, a
#local variable which is not 'alive' at that point can be used to
#keep the result. This can reduce the size of the global section.
#This will not have declared variables overlap, even if it was
#possible.
LOCAL_TEMPS = true
#Causes temporary values which do not need to be backed up on a
#CALL to not be stored in the function's locals-area. With this, a
#CALL to a function may need to back up fewer values and thus exe
#cute faster.
GLOBAL_TEMPS = true
#Don't generate defs for immediate values or even declared con
#stants. Meaning variables which are implicitly constant or qual
#ified as such using the 'const' keyword.
STRIP_CONSTANT_NAMES = true
#Aggressively reuse strings in the string section. When a string
#should be added which is the trailing substring of an already
#existing string, the existing string's tail will be returned
#instead of the new string being added.
#
#For example the following code will only generate 1 string:
#
# print("Hello you!\n");
# print("you!\n"); // trailing substring of "Hello you!\n"
#
#There's however one limitation. Strings are still processed in
#order, so if the above print statements were reversed, this opti
#mization would not happen.
OVERLAP_STRINGS = true
#By default, all parameters of a CALL are copied into the parame
#ter-globals right before the CALL instructions. This is the easi
#est and safest way to translate calls, but also adds a lot of
#unnecessary copying and unnecessary temporary values. This opti
#mization makes operations which are used as a parameter evaluate
#directly into the parameter-global if that is possible, which is
#when there's no other CALL instruction in between.
CALL_STORES = true
#Usually an empty RETURN instruction is added to the end of a void
#typed function. However, additionally after every function a DONE
#instruction is added for several reasons. (For example the qcvm's
#disassemble switch uses it to know when the function ends.). This
#optimization replaces that last RETURN with DONE rather than
#adding the DONE additionally.
VOID_RETURN = true
#Because traditional QC code doesn't allow you to access individ
#ual vector components of a computed vector without storing it in
#a local first, sometimes people multiply it by a constant like
#'0 1 0' to get, in this case, the y component of a vector. This
#optimization will turn such a multiplication into a direct compo
#nent access. If the factor is anything other than 1, a float-mul
#tiplication will be added, which is still faster than a vector
#multiplication.
VECTOR_COMPONENTS = true
#For constant expressions that result in dead code (such as a
#branch whos condition can be evaluated at compile-time), this
#will eliminate the branch and else body (if present) to produce
#more optimal code.
CONST_FOLD_DCE = true
#For constant expressions we can fold them to immediate values.
#this option cannot be disabled or enabled, the compiler forces
#it to stay enabled by ignoring the value entierly. There are
#plans to enable some level of constant fold disabling, but right
#now the language can't function without it. This is merley here
#as an exercise to the reader.
CONST_FOLD = true

View file

@ -1,131 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{85C266A8-7938-4AE6-AB64-428DC32B1ACD}</ProjectGuid>
<RootNamespace>gmqcc</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IntDir>.\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>gmqcc</TargetName>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IntDir>.</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>gmqcc</TargetName>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FloatingPointModel>Fast</FloatingPointModel>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ManifestFile>
</ManifestFile>
<ProgramDatabaseFile>$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FloatingPointModel>Fast</FloatingPointModel>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ManifestFile>
</ManifestFile>
<ProgramDatabaseFile>$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="asm.c" />
<ClCompile Include="ast.c" />
<ClCompile Include="code.c" />
<ClCompile Include="error.c" />
<ClCompile Include="exec.c" />
<ClCompile Include="ir.c" />
<ClCompile Include="lexer.c" />
<ClCompile Include="main.c" />
<ClCompile Include="parser.c" />
<ClCompile Include="util.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ast.h" />
<ClInclude Include="execloop.h" />
<ClInclude Include="gmqcc.h" />
<ClInclude Include="ir.h" />
<ClInclude Include="lexer.h" />
</ItemGroup>
<ItemGroup>
<None Include="flags.def" />
<None Include="warns.def" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

2048
intrin.cpp Normal file

File diff suppressed because it is too large Load diff

74
intrin.h Normal file
View file

@ -0,0 +1,74 @@
#ifndef GMQCC_INTRIN_HDR
#define GMQCC_INTRIN_HDR
#include "gmqcc.h"
struct fold;
struct parser_t;
struct ast_function;
struct ast_expression;
struct ast_value;
struct intrin;
struct intrin_func_t {
ast_expression *(intrin::*function)();
const char *name;
const char *alias;
size_t args;
};
struct intrin {
intrin() = default;
intrin(parser_t *parser);
ast_expression *debug_typestring();
ast_expression *do_fold(ast_value *val, ast_expression **exprs);
ast_expression *func_try(size_t offset, const char *compare);
ast_expression *func_self(const char *name, const char *from);
ast_expression *func(const char *name);
protected:
lex_ctx_t ctx() const;
ast_function *value(ast_value **out, const char *name, qc_type vtype);
void reg(ast_value *const value, ast_function *const func);
ast_expression *nullfunc();
ast_expression *isfinite_();
ast_expression *isinf_();
ast_expression *isnan_();
ast_expression *isnormal_();
ast_expression *signbit_();
ast_expression *acosh_();
ast_expression *asinh_();
ast_expression *atanh_();
ast_expression *exp_();
ast_expression *exp2_();
ast_expression *expm1_();
ast_expression *pow_();
ast_expression *mod_();
ast_expression *fabs_();
ast_expression *epsilon_();
ast_expression *nan_();
ast_expression *inf_();
ast_expression *ln_();
ast_expression *log_variant(const char *name, float base);
ast_expression *log_();
ast_expression *log10_();
ast_expression *log2_();
ast_expression *logb_();
ast_expression *shift_variant(const char *name, size_t instr);
ast_expression *lshift();
ast_expression *rshift();
void error(const char *fmt, ...);
private:
parser_t *m_parser;
fold *m_fold;
std::vector<intrin_func_t> m_intrinsics;
std::vector<ast_expression*> m_generated;
};
#endif

3212
ir.c

File diff suppressed because it is too large Load diff

4094
ir.cpp Normal file

File diff suppressed because it is too large Load diff

502
ir.h
View file

@ -1,342 +1,334 @@
/*
* Copyright (C) 2012
* Wolfgang Bumiller
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef GMQCC_IR_HDR
#define GMQCC_IR_HDR
#include "gmqcc.h"
/* ir_value */
/*
* Type large enough to hold all the possible IR flags. This should be
* changed if the static assertion at the end of this file fails.
*/
typedef uint8_t ir_flag_t;
typedef struct
{
struct ir_value;
struct ir_instr;
struct ir_block;
struct ir_function;
struct ir_builder;
struct ir_life_entry_t {
/* both inclusive */
size_t start;
size_t end;
} ir_life_entry_t;
};
struct ir_function_s;
typedef struct ir_value_s {
char *name;
int vtype;
int store;
lex_ctx context;
/* even the IR knows the subtype of a field */
int fieldtype;
/* and the output type of a function */
int outtype;
enum {
IR_FLAG_HAS_ARRAYS = 1 << 0,
IR_FLAG_HAS_UNINITIALIZED = 1 << 1,
IR_FLAG_HAS_GOTO = 1 << 2,
IR_FLAG_INCLUDE_DEF = 1 << 3,
IR_FLAG_ERASABLE = 1 << 4,
IR_FLAG_BLOCK_COVERAGE = 1 << 5,
IR_FLAG_NOREF = 1 << 6,
IR_FLAG_SPLIT_VECTOR = 1 << 7,
MEM_VECTOR_MAKE(struct ir_instr_s*, reads);
MEM_VECTOR_MAKE(struct ir_instr_s*, writes);
IR_FLAG_LAST,
IR_FLAG_MASK_NO_OVERLAP = (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED),
IR_FLAG_MASK_NO_LOCAL_TEMPS = (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)
};
/* constantvalues */
bool isconst;
struct ir_value {
ir_value(std::string&& name, store_type storetype, qc_type vtype);
ir_value(ir_function *owner, std::string&& name, store_type storetype, qc_type vtype);
~ir_value();
ir_value *vectorMember(unsigned int member);
bool GMQCC_WARN setFloat(float);
bool GMQCC_WARN setFunc(int);
bool GMQCC_WARN setString(const char*);
bool GMQCC_WARN setVector(vec3_t);
bool GMQCC_WARN setField(ir_value*);
#if 0
bool GMQCC_WARN setInt(int);
#endif
bool lives(size_t at);
void dumpLife(int (*oprintf)(const char*, ...)) const;
void setCodeAddress(int32_t gaddr);
int32_t codeAddress() const;
bool insertLife(size_t idx, ir_life_entry_t);
bool setAlive(size_t position);
bool mergeLife(const ir_value *other);
std::string m_name;
qc_type m_vtype;
store_type m_store;
lex_ctx_t m_context;
qc_type m_fieldtype; // even the IR knows the subtype of a field
qc_type m_outtype; // and the output type of a function
int m_cvq; // 'const' vs 'var' qualifier
ir_flag_t m_flags;
std::vector<ir_instr *> m_reads;
std::vector<ir_instr *> m_writes;
// constant values
bool m_hasvalue;
union {
float vfloat;
int vint;
vector vvec;
char *vstring;
struct ir_value_s *vpointer;
struct ir_function_s *vfunc;
} constval;
qcfloat_t vfloat;
int vint;
vec3_t vvec;
int32_t ivec[3];
char *vstring;
ir_value *vpointer;
ir_function *vfunc;
} m_constval;
struct {
int32_t globaladdr;
int32_t name;
/* filled by the local-allocator */
int32_t local;
/* added for members */
int32_t addroffset;
} code;
int32_t local; // filled by the local-allocator
int32_t addroffset; // added for members
int32_t fieldaddr; // to generate field-addresses early
} m_code;
/* for acessing vectors */
struct ir_value_s *members[3];
struct ir_value_s *memberof;
// for accessing vectors
ir_value *m_members[3];
ir_value *m_memberof;
/* For the temp allocator */
MEM_VECTOR_MAKE(ir_life_entry_t, life);
} ir_value;
bool m_unique_life; // arrays will never overlap with temps
bool m_locked; // temps living during a CALL must be locked
bool m_callparam;
int32_t ir_value_code_addr(const ir_value*);
std::vector<ir_life_entry_t> m_life; // For the temp allocator
/* ir_value can be a variable, or created by an operation */
ir_value* ir_value_var(const char *name, int st, int vtype);
/* if a result of an operation: the function should store
* it to remember to delete it / garbage collect it
*/
ir_value* ir_value_out(struct ir_function_s *owner, const char *name, int st, int vtype);
void ir_value_delete(ir_value*);
bool ir_value_set_name(ir_value*, const char *name);
ir_value* ir_value_vector_member(ir_value*, unsigned int member);
size_t size() const;
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, reads);
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, writes);
bool GMQCC_WARN ir_value_set_float(ir_value*, float f);
bool GMQCC_WARN ir_value_set_func(ir_value*, int f);
#if 0
bool GMQCC_WARN ir_value_set_int(ir_value*, int i);
#endif
bool GMQCC_WARN ir_value_set_string(ir_value*, const char *s);
bool GMQCC_WARN ir_value_set_vector(ir_value*, vector v);
bool GMQCC_WARN ir_value_set_field(ir_value*, ir_value *fld);
/*bool ir_value_set_pointer_v(ir_value*, ir_value* p); */
/*bool ir_value_set_pointer_i(ir_value*, int i); */
MEM_VECTOR_PROTO(ir_value, ir_life_entry_t, life);
/* merge an instruction into the life-range */
/* returns false if the lifepoint was already known */
bool ir_value_life_merge(ir_value*, size_t);
bool ir_value_life_merge_into(ir_value*, const ir_value*);
/* check if a value lives at a specific point */
bool ir_value_lives(ir_value*, size_t);
/* check if the life-range of 2 values overlaps */
bool ir_values_overlap(const ir_value*, const ir_value*);
void ir_value_dump(ir_value*, int (*oprintf)(const char*,...));
void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...));
/* A vector of IR values */
typedef struct {
MEM_VECTOR_MAKE(ir_value*, v);
} ir_value_vector;
MEM_VECTOR_PROTO(ir_value_vector, ir_value*, v);
void dump(int (*oprintf)(const char*, ...)) const;
};
/* PHI data */
typedef struct ir_phi_entry_s
{
ir_value *value;
struct ir_block_s *from;
} ir_phi_entry_t;
struct ir_phi_entry_t {
ir_value *value;
ir_block *from;
};
/* instruction */
typedef struct ir_instr_s
{
int opcode;
lex_ctx context;
ir_value* (_ops[3]);
struct ir_block_s* (bops[2]);
struct ir_instr {
ir_instr(lex_ctx_t, ir_block *owner, int opcode);
~ir_instr();
MEM_VECTOR_MAKE(ir_phi_entry_t, phi);
MEM_VECTOR_MAKE(ir_value*, params);
int m_opcode;
lex_ctx_t m_context;
ir_value *(_m_ops[3]) = { nullptr, nullptr, nullptr };
ir_block *(m_bops[2]) = { nullptr, nullptr };
/* For the temp-allocation */
size_t eid;
std::vector<ir_phi_entry_t> m_phi;
std::vector<ir_value *> m_params;
struct ir_block_s *owner;
} ir_instr;
// For the temp-allocation
size_t m_eid = 0;
ir_instr* ir_instr_new(struct ir_block_s *owner, int opcode);
void ir_instr_delete(ir_instr*);
// For IFs
bool m_likely = true;
MEM_VECTOR_PROTO(ir_value, ir_phi_entry_t, phi);
bool GMQCC_WARN ir_instr_op(ir_instr*, int op, ir_value *value, bool writing);
MEM_VECTOR_PROTO(ir_value, ir_value*, params);
void ir_instr_dump(ir_instr* in, char *ind, int (*oprintf)(const char*,...));
ir_block *m_owner;
};
/* block */
typedef struct ir_block_s
{
char *label;
lex_ctx context;
bool final; /* once a jump is added we're done */
struct ir_block {
ir_block(ir_function *owner, const std::string& name);
~ir_block();
MEM_VECTOR_MAKE(ir_instr*, instr);
MEM_VECTOR_MAKE(struct ir_block_s*, entries);
MEM_VECTOR_MAKE(struct ir_block_s*, exits);
MEM_VECTOR_MAKE(ir_value*, living);
ir_function *m_owner;
std::string m_label;
lex_ctx_t m_context;
bool m_final = false; /* once a jump is added we're done */
std::vector<ir_instr *> m_instr;
std::vector<ir_block *> m_entries;
std::vector<ir_block *> m_exits;
std::vector<ir_value *> m_living;
/* For the temp-allocation */
size_t eid;
bool is_return;
size_t run_id;
size_t m_entry_id = 0;
size_t m_eid = 0;
bool m_is_return = false;
struct ir_function_s *owner;
bool m_generated = false;
size_t m_code_start = 0;
};
bool generated;
size_t code_start;
} ir_block;
ir_block* ir_block_new(struct ir_function_s *owner, const char *label);
void ir_block_delete(ir_block*);
bool ir_block_set_label(ir_block*, const char *label);
MEM_VECTOR_PROTO(ir_block, ir_instr*, instr);
MEM_VECTOR_PROTO_ALL(ir_block, ir_block*, exits);
MEM_VECTOR_PROTO_ALL(ir_block, ir_block*, entries);
ir_value* ir_block_create_binop(ir_block*, const char *label, int op,
ir_value *left, ir_value *right);
ir_value* ir_block_create_unary(ir_block*, const char *label, int op,
ir_value *operand);
bool GMQCC_WARN ir_block_create_store_op(ir_block*, int op, ir_value *target, ir_value *what);
bool GMQCC_WARN ir_block_create_store(ir_block*, ir_value *target, ir_value *what);
bool GMQCC_WARN ir_block_create_storep(ir_block*, ir_value *target, ir_value *what);
/* field must be of TYPE_FIELD */
ir_value* ir_block_create_load_from_ent(ir_block*, const char *label, ir_value *ent, ir_value *field, int outype);
ir_value* ir_block_create_fieldaddress(ir_block*, const char *label, ir_value *entity, ir_value *field);
ir_value* ir_block_create_binop(ir_block*, lex_ctx_t, const char *label, int op, ir_value *left, ir_value *right);
ir_value* ir_block_create_unary(ir_block*, lex_ctx_t, const char *label, int op, ir_value *operand);
bool GMQCC_WARN ir_block_create_store_op(ir_block*, lex_ctx_t, int op, ir_value *target, ir_value *what);
bool GMQCC_WARN ir_block_create_storep(ir_block*, lex_ctx_t, ir_value *target, ir_value *what);
ir_value* ir_block_create_load_from_ent(ir_block*, lex_ctx_t, const char *label, ir_value *ent, ir_value *field, qc_type outype);
ir_value* ir_block_create_fieldaddress(ir_block*, lex_ctx_t, const char *label, ir_value *entity, ir_value *field);
bool GMQCC_WARN ir_block_create_state_op(ir_block*, lex_ctx_t, ir_value *frame, ir_value *think);
/* This is to create an instruction of the form
* <outtype>%label := opcode a, b
*/
ir_value* ir_block_create_general_instr(ir_block *self, const char *label,
int op, ir_value *a, ir_value *b, int outype);
ir_value* ir_block_create_add(ir_block*, const char *label, ir_value *l, ir_value *r);
ir_value* ir_block_create_sub(ir_block*, const char *label, ir_value *l, ir_value *r);
ir_value* ir_block_create_mul(ir_block*, const char *label, ir_value *l, ir_value *r);
ir_value* ir_block_create_div(ir_block*, const char *label, ir_value *l, ir_value *r);
ir_instr* ir_block_create_phi(ir_block*, const char *label, int vtype);
ir_instr* ir_block_create_phi(ir_block*, lex_ctx_t, const char *label, qc_type vtype);
ir_value* ir_phi_value(ir_instr*);
bool GMQCC_WARN ir_phi_add(ir_instr*, ir_block *b, ir_value *v);
ir_instr* ir_block_create_call(ir_block*, const char *label, ir_value *func);
void ir_phi_add(ir_instr*, ir_block *b, ir_value *v);
ir_instr* ir_block_create_call(ir_block*, lex_ctx_t, const char *label, ir_value *func, bool noreturn);
ir_value* ir_call_value(ir_instr*);
bool GMQCC_WARN ir_call_param(ir_instr*, ir_value*);
void ir_call_param(ir_instr*, ir_value*);
bool GMQCC_WARN ir_block_create_return(ir_block*, ir_value *opt_value);
bool GMQCC_WARN ir_block_create_return(ir_block*, lex_ctx_t, ir_value *opt_value);
bool GMQCC_WARN ir_block_create_if(ir_block*, ir_value *cond,
bool GMQCC_WARN ir_block_create_if(ir_block*, lex_ctx_t, ir_value *cond,
ir_block *ontrue, ir_block *onfalse);
/* A 'goto' is an actual 'goto' coded in QC, whereas
/*
* A 'goto' is an actual 'goto' coded in QC, whereas
* a 'jump' is a virtual construct which simply names the
* next block to go to.
* A goto usually becomes an OP_GOTO in the resulting code,
* whereas a 'jump' usually doesn't add any actual instruction.
*/
bool GMQCC_WARN ir_block_create_jump(ir_block*, ir_block *to);
bool GMQCC_WARN ir_block_create_goto(ir_block*, ir_block *to);
MEM_VECTOR_PROTO_ALL(ir_block, ir_value*, living);
void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...));
bool GMQCC_WARN ir_block_create_jump(ir_block*, lex_ctx_t, ir_block *to);
bool GMQCC_WARN ir_block_create_goto(ir_block*, lex_ctx_t, ir_block *to);
/* function */
struct ir_function {
ir_function(ir_builder *owner, qc_type returntype);
~ir_function();
typedef struct ir_function_s
{
char *name;
int outtype;
MEM_VECTOR_MAKE(int, params);
MEM_VECTOR_MAKE(ir_block*, blocks);
ir_builder *m_owner;
int builtin;
std::string m_name;
qc_type m_outtype;
std::vector<int> m_params;
ir_flag_t m_flags = 0;
int m_builtin = 0;
ir_value *value;
std::vector<std::unique_ptr<ir_block>> m_blocks;
/* values generated from operations
/*
* values generated from operations
* which might get optimized away, so anything
* in there needs to be deleted in the dtor.
*/
MEM_VECTOR_MAKE(ir_value*, values);
std::vector<std::unique_ptr<ir_value>> m_values;
std::vector<std::unique_ptr<ir_value>> m_locals; /* locally defined variables */
ir_value *m_value = nullptr;
/* locally defined variables */
MEM_VECTOR_MAKE(ir_value*, locals);
size_t m_allocated_locals = 0;
size_t m_globaltemps = 0;
size_t allocated_locals;
ir_block* m_first = nullptr;
ir_block* m_last = nullptr;
ir_block* first;
ir_block* last;
lex_ctx_t m_context;
lex_ctx context;
/* for prototypes - first we generate all the
/*
* for prototypes - first we generate all the
* globals, and we remember teh function-defs
* so we can later fill in the entry pos
*
* remember the ID:
*/
qcint code_function_def;
qcint_t m_code_function_def = -1;
/* for temp allocation */
size_t run_id;
size_t m_run_id = 0;
struct ir_builder_s *owner;
} ir_function;
/* vararg support: */
size_t m_max_varargs = 0;
};
ir_function* ir_function_new(struct ir_builder_s *owner, int returntype);
void ir_function_delete(ir_function*);
bool GMQCC_WARN ir_function_collect_value(ir_function*, ir_value *value);
bool ir_function_set_name(ir_function*, const char *name);
MEM_VECTOR_PROTO(ir_function, int, params);
MEM_VECTOR_PROTO(ir_function, ir_block*, blocks);
ir_value* ir_function_get_local(ir_function *self, const char *name);
ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param);
ir_value* ir_function_create_local(ir_function *self, const std::string& name, qc_type vtype, bool param);
bool GMQCC_WARN ir_function_finalize(ir_function*);
/*
bool ir_function_naive_phi(ir_function*);
bool ir_function_enumerate(ir_function*);
bool ir_function_calculate_liferanges(ir_function*);
*/
ir_block* ir_function_create_block(ir_function*, const char *label);
void ir_function_dump(ir_function*, char *ind, int (*oprintf)(const char*,...));
ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function*, const char *label);
/* builder */
typedef struct ir_builder_s
{
char *name;
MEM_VECTOR_MAKE(ir_function*, functions);
MEM_VECTOR_MAKE(ir_value*, globals);
MEM_VECTOR_MAKE(ir_value*, fields);
#define IR_HT_SIZE 1024
#define IR_MAX_VINSTR_TEMPS 2
MEM_VECTOR_MAKE(const char*, filenames);
MEM_VECTOR_MAKE(qcint, filestrings);
/* we cache the #IMMEDIATE string here */
qcint str_immediate;
} ir_builder;
struct ir_builder {
ir_builder(const std::string& modulename);
~ir_builder();
ir_builder* ir_builder_new(const char *modulename);
void ir_builder_delete(ir_builder*);
ir_function *createFunction(const std::string &name, qc_type outtype);
ir_value *createGlobal(const std::string &name, qc_type vtype);
ir_value *createField(const std::string &name, qc_type vtype);
ir_value *get_va_count();
bool generate(const char *filename);
void dump(int (*oprintf)(const char*, ...)) const;
bool ir_builder_set_name(ir_builder *self, const char *name);
ir_value *generateExtparamProto();
void generateExtparam();
MEM_VECTOR_PROTO(ir_builder, ir_function*, functions);
MEM_VECTOR_PROTO(ir_builder, ir_value*, globals);
MEM_VECTOR_PROTO(ir_builder, ir_value*, fields);
MEM_VECTOR_PROTO(ir_builder, const char*, filenames);
MEM_VECTOR_PROTO(ir_builder, qcint, filestrings);
ir_value *literalFloat(float value, bool add_to_list);
ir_function* ir_builder_get_function(ir_builder*, const char *fun);
ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype);
std::string m_name;
std::vector<std::unique_ptr<ir_function>> m_functions;
std::vector<std::unique_ptr<ir_value>> m_globals;
std::vector<std::unique_ptr<ir_value>> m_fields;
// for reusing them in vector-splits, TODO: sort this or use a radix-tree
std::vector<ir_value*> m_const_floats;
ir_value* ir_builder_get_global(ir_builder*, const char *fun);
ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype);
ir_value* ir_builder_get_field(ir_builder*, const char *fun);
ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype);
ht m_htfunctions;
ht m_htglobals;
ht m_htfields;
bool ir_builder_generate(ir_builder *self, const char *filename);
// extparams' ir_values reference the ones from extparam_protos
std::vector<std::unique_ptr<ir_value>> m_extparam_protos;
std::vector<ir_value*> m_extparams;
void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...));
// the highest func->allocated_locals
size_t m_max_locals = 0;
size_t m_max_globaltemps = 0;
uint32_t m_first_common_local = 0;
uint32_t m_first_common_globaltemp = 0;
/* This code assumes 32 bit floats while generating binary */
extern int check_int_and_float_size
[ (sizeof(int32_t) == sizeof(qcfloat)) ? 1 : -1 ];
std::vector<const char*> m_filenames;
std::vector<qcint_t> m_filestrings;
// we cache the #IMMEDIATE string here
qcint_t m_str_immediate = 0;
// there should just be this one nil
ir_value *m_nil;
ir_value *m_reserved_va_count = nullptr;
ir_value *m_coverage_func = nullptr;
/* some virtual instructions require temps, and their code is isolated
* so that we don't need to keep track of their liveness.
*/
ir_value *m_vinstr_temp[IR_MAX_VINSTR_TEMPS];
/* code generator */
std::unique_ptr<code_t> m_code;
private:
qcint_t filestring(const char *filename);
bool generateGlobal(ir_value*, bool is_local);
bool generateGlobalFunction(ir_value*);
bool generateGlobalFunctionCode(ir_value*);
bool generateFunctionLocals(ir_value*);
};
/*
* This code assumes 32 bit floats while generating binary
* Blub: don't use extern here, it's annoying and shows up in nm
* for some reason :P
*/
typedef int static_assert_is_32bit_float [(sizeof(int32_t) == 4) ? 1 : -1];
typedef int static_assert_is_32bit_integer[(sizeof(qcfloat_t) == 4) ? 1 : -1];
/*
* If the condition creates a situation where this becomes -1 size it means there are
* more IR_FLAGs than the type ir_flag_t is capable of holding. So either eliminate
* the IR flag count or change the ir_flag_t typedef to a type large enough to accomodate
* all the flags.
*/
typedef int static_assert_is_ir_flag_safe [((IR_FLAG_LAST) <= (ir_flag_t)(-1)) ? 1 : -1];
#endif

1070
lexer.c

File diff suppressed because it is too large Load diff

1439
lexer.cpp Normal file

File diff suppressed because it is too large Load diff

358
lexer.h
View file

@ -1,38 +1,19 @@
#ifndef GMQCC_LEXER_HDR_
#define GMQCC_LEXER_HDR_
#ifndef GMQCC_LEXER_HDR
#define GMQCC_LEXER_HDR
#include "gmqcc.h"
typedef struct token_s token;
#include "ast.h"
struct token_s {
int ttype;
MEM_VECTOR_MAKE(char, value);
union {
vector v;
int i;
double f;
int t; /* type */
} constval;
#if 0
struct token_s *next;
struct token_s *prev;
#endif
lex_ctx ctx;
struct token {
int ttype;
char *value;
union {
vec3_t v;
int i;
qcfloat_t f;
qc_type t; /* type */
} constval;
lex_ctx_t ctx;
};
#if 0
token* token_new();
void token_delete(token*);
token* token_copy(const token *cp);
void token_delete_all(token *t);
token* token_copy_all(const token *cp);
#endif
/* Lexer
*
*/
@ -51,13 +32,27 @@ enum {
TOKEN_DOTS, /* 3 dots, ... */
TOKEN_ATTRIBUTE_OPEN, /* [[ */
TOKEN_ATTRIBUTE_CLOSE, /* ]] */
TOKEN_VA_ARGS, /* for the ftepp only */
TOKEN_VA_ARGS_ARRAY, /* for the ftepp only */
TOKEN_VA_COUNT, /* to get the count of vaargs */
TOKEN_STRINGCONST, /* not the typename but an actual "string" */
TOKEN_CHARCONST,
TOKEN_VECTORCONST,
TOKEN_INTCONST,
TOKEN_FLOATCONST,
TOKEN_EOF,
TOKEN_WHITE,
TOKEN_EOL,
/* if we add additional tokens before this, the exposed API
* should not be broken anyway, but EOF/ERROR/... should
* still be at the bottom
*/
TOKEN_EOF = 1024,
/* We use '< TOKEN_ERROR', so TOKEN_FATAL must come after it and any
* other error related tokens as well
@ -66,59 +61,45 @@ enum {
TOKEN_FATAL /* internal error, eg out of memory */
};
static const char *_tokennames[] = {
"TOKEN_START",
"TOKEN_IDENT",
"TOKEN_TYPENAME",
"TOKEN_OPERATOR",
"TOKEN_KEYWORD",
"TOKEN_DOTS",
"TOKEN_STRINGCONST",
"TOKEN_CHARCONST",
"TOKEN_VECTORCONST",
"TOKEN_INTCONST",
"TOKEN_FLOATCONST",
"TOKEN_EOF",
"TOKEN_ERROR",
"TOKEN_FATAL",
};
typedef int
_all_tokennames_added_[
((TOKEN_FATAL - TOKEN_START + 1) ==
(sizeof(_tokennames)/sizeof(_tokennames[0])))
? 1 : -1];
typedef struct {
struct frame_macro {
char *name;
int value;
} frame_macro;
int value;
};
typedef struct {
FILE *file;
char *name;
size_t line;
size_t sline; /* line at the start of a token */
struct lex_file {
FILE *file;
const char *open_string;
size_t open_string_length;
size_t open_string_pos;
char peek[256];
size_t peekpos;
char *name;
size_t line;
size_t sline; /* line at the start of a token */
size_t column;
bool eof;
int peek[256];
size_t peekpos;
token tok; /* not a pointer anymore */
bool eof;
struct {
bool noops;
bool nodigraphs; /* used when lexing string constants */
} flags;
token tok; /* not a pointer anymore */
struct {
unsigned noops:1;
unsigned nodigraphs:1; /* used when lexing string constants */
unsigned preprocessing:1; /* whitespace and EOLs become actual tokens */
unsigned mergelines:1; /* backslash at the end of a line escapes the newline */
} flags; /* sizeof == 1 */
int framevalue;
MEM_VECTOR_MAKE(frame_macro, frames);
char *modelname;
} lex_file;
frame_macro *frames;
char *modelname;
MEM_VECTOR_PROTO(lex_file, char, token);
size_t push_line;
};
lex_file* lex_open (const char *file);
lex_file* lex_open_string(const char *str, size_t len, const char *name);
void lex_close(lex_file *lex);
int lex_do (lex_file *lex);
void lex_cleanup(void);
@ -135,125 +116,188 @@ enum {
#define OP_SUFFIX 1
#define OP_PREFIX 2
typedef struct {
struct oper_info {
const char *op;
unsigned int operands;
unsigned int id;
unsigned int assoc;
unsigned int prec;
signed int prec;
unsigned int flags;
} oper_info;
bool folds;
};
#define opid1(a) (a)
#define opid2(a,b) ((a<<8)|b)
#define opid3(a,b,c) ((a<<16)|(b<<8)|c)
/*
* Explicit uint8_t casts since the left operand of shift operator cannot
* be negative, even though it won't happen, this supresses the future
* possibility.
*/
#define opid1(a) ((uint8_t)a)
#define opid2(a,b) (((uint8_t)a<<8) |(uint8_t)b)
#define opid3(a,b,c) (((uint8_t)a<<16)|((uint8_t)b<<8)|(uint8_t)c)
static const oper_info c_operators[] = {
{ "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX}, /* paren expression - non function call */
{ "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */
{ "_length", 1, opid3('l','e','n'), ASSOC_RIGHT, 98, OP_PREFIX, true},
{ "++", 1, opid3('S','+','+'), ASSOC_LEFT, 16, OP_SUFFIX},
{ "--", 1, opid3('S','-','-'), ASSOC_LEFT, 16, OP_SUFFIX},
{ "++", 1, opid3('S','+','+'), ASSOC_LEFT, 17, OP_SUFFIX, false},
{ "--", 1, opid3('S','-','-'), ASSOC_LEFT, 17, OP_SUFFIX, false},
{ ".", 2, opid1('.'), ASSOC_LEFT, 17, 0, false},
{ "(", 0, opid1('('), ASSOC_LEFT, 17, 0, false}, /* function call */
{ "[", 2, opid1('['), ASSOC_LEFT, 17, 0, false}, /* array subscript */
{ ".", 2, opid1('.'), ASSOC_LEFT, 15, 0 },
{ "(", 0, opid1('('), ASSOC_LEFT, 15, 0 }, /* function call */
{ "++", 1, opid3('+','+','P'), ASSOC_RIGHT, 16, OP_PREFIX, false},
{ "--", 1, opid3('-','-','P'), ASSOC_RIGHT, 16, OP_PREFIX, false},
{ "!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "~", 1, opid2('~', 'P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "++", 1, opid3('+','+','P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "--", 1, opid3('-','-','P'), ASSOC_RIGHT, 14, OP_PREFIX },
/* { "&", 1, opid2('&','P'), ASSOC_RIGHT, 14, OP_PREFIX }, */
{ "**", 2, opid2('*','*'), ASSOC_RIGHT, 14, 0, true},
{ "!", 1, opid2('!','P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
{ "~", 1, opid2('~','P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
{ "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
{ "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
/* { "&", 1, opid2('&','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, */
{ "*", 2, opid1('*'), ASSOC_LEFT, 13, 0 },
{ "/", 2, opid1('/'), ASSOC_LEFT, 13, 0 },
{ "%", 2, opid1('%'), ASSOC_LEFT, 13, 0 },
{ "*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true},
{ "/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true},
{ "%", 2, opid1('%'), ASSOC_LEFT, 13, 0, true},
{ "><", 2, opid2('>','<'), ASSOC_LEFT, 13, 0, true},
{ "+", 2, opid1('+'), ASSOC_LEFT, 12, 0 },
{ "-", 2, opid1('-'), ASSOC_LEFT, 12, 0 },
{ "+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true},
{ "-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true},
{ "<<", 2, opid2('<','<'), ASSOC_LEFT, 11, 0 },
{ ">>", 2, opid2('>','>'), ASSOC_LEFT, 11, 0 },
{ "<<", 2, opid2('<','<'), ASSOC_LEFT, 11, 0, true},
{ ">>", 2, opid2('>','>'), ASSOC_LEFT, 11, 0, true},
{ "<", 2, opid1('<'), ASSOC_LEFT, 10, 0 },
{ ">", 2, opid1('>'), ASSOC_LEFT, 10, 0 },
{ "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0 },
{ ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0 },
{ "<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false},
{ ">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false},
{ "<=>", 2, opid3('<','=','>'), ASSOC_LEFT, 10, 0, true},
{ "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0, false},
{ ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0, false},
{ "==", 2, opid2('=','='), ASSOC_LEFT, 9, 0 },
{ "!=", 2, opid2('!','='), ASSOC_LEFT, 9, 0 },
{ "==", 2, opid2('=','='), ASSOC_LEFT, 9, 0, true},
{ "!=", 2, opid2('!','='), ASSOC_LEFT, 9, 0, true},
{ "&", 2, opid1('&'), ASSOC_LEFT, 8, 0 },
{ "&", 2, opid1('&'), ASSOC_LEFT, 8, 0, true},
{ "^", 2, opid1('^'), ASSOC_LEFT, 7, 0 },
{ "^", 2, opid1('^'), ASSOC_LEFT, 7, 0, true},
{ "|", 2, opid1('|'), ASSOC_LEFT, 6, 0 },
{ "|", 2, opid1('|'), ASSOC_LEFT, 6, 0, true},
{ "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0 },
{ "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0, true},
{ "||", 2, opid2('|','|'), ASSOC_LEFT, 4, 0 },
{ "||", 2, opid2('|','|'), ASSOC_LEFT, 4, 0, true},
{ "?", 3, opid2('?',':'), ASSOC_RIGHT, 3, 0 },
{ "?", 3, opid2('?',':'), ASSOC_RIGHT, 3, 0, true},
{ "=", 2, opid1('='), ASSOC_RIGHT, 2, 0 },
{ "+=", 2, opid2('+','='), ASSOC_RIGHT, 2, 0 },
{ "-=", 2, opid2('-','='), ASSOC_RIGHT, 2, 0 },
{ "*=", 2, opid2('*','='), ASSOC_RIGHT, 2, 0 },
{ "/=", 2, opid2('/','='), ASSOC_RIGHT, 2, 0 },
{ "%=", 2, opid2('%','='), ASSOC_RIGHT, 2, 0 },
{ ">>=", 2, opid3('>','>','='), ASSOC_RIGHT, 2, 0 },
{ "<<=", 2, opid3('<','<','='), ASSOC_RIGHT, 2, 0 },
{ "&=", 2, opid2('&','='), ASSOC_RIGHT, 2, 0 },
{ "^=", 2, opid2('^','='), ASSOC_RIGHT, 2, 0 },
{ "|=", 2, opid2('|','='), ASSOC_RIGHT, 2, 0 },
{ "=", 2, opid1('='), ASSOC_RIGHT, 2, 0, false},
{ "+=", 2, opid2('+','='), ASSOC_RIGHT, 2, 0, false},
{ "-=", 2, opid2('-','='), ASSOC_RIGHT, 2, 0, false},
{ "*=", 2, opid2('*','='), ASSOC_RIGHT, 2, 0, false},
{ "/=", 2, opid2('/','='), ASSOC_RIGHT, 2, 0, false},
{ "%=", 2, opid2('%','='), ASSOC_RIGHT, 2, 0, false},
{ ">>=", 2, opid3('>','>','='), ASSOC_RIGHT, 2, 0, false},
{ "<<=", 2, opid3('<','<','='), ASSOC_RIGHT, 2, 0, false},
{ "&=", 2, opid2('&','='), ASSOC_RIGHT, 2, 0, false},
{ "^=", 2, opid2('^','='), ASSOC_RIGHT, 2, 0, false},
{ "|=", 2, opid2('|','='), ASSOC_RIGHT, 2, 0, false},
{ ",", 2, opid1(','), ASSOC_LEFT, 1, 0 }
{ ":", 0, opid2(':','?'), ASSOC_RIGHT, 1, 0, false},
{ ",", 2, opid1(','), ASSOC_LEFT, 0, 0, false}
};
static const oper_info fte_operators[] = {
{ "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */
{ "++", 1, opid3('S','+','+'), ASSOC_LEFT, 15, OP_SUFFIX, false},
{ "--", 1, opid3('S','-','-'), ASSOC_LEFT, 15, OP_SUFFIX, false},
{ ".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false},
{ "(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */
{ "[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */
{ "!", 1, opid2('!','P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
{ "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
{ "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
{ "++", 1, opid3('+','+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
{ "--", 1, opid3('-','-','P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
{ "*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true},
{ "/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true},
{ "&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true},
{ "|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true},
{ "+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true},
{ "-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true},
{ "<<", 2, opid2('<','<'), ASSOC_LEFT, 11, 0, true},
{ ">>", 2, opid2('>','>'), ASSOC_LEFT, 11, 0, true},
{ "<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false},
{ ">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false},
{ "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0, false},
{ ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0, false},
{ "==", 2, opid2('=','='), ASSOC_LEFT, 10, 0, true},
{ "!=", 2, opid2('!','='), ASSOC_LEFT, 10, 0, true},
{ "?", 3, opid2('?',':'), ASSOC_RIGHT, 9, 0, true},
{ "=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false},
{ "+=", 2, opid2('+','='), ASSOC_RIGHT, 8, 0, false},
{ "-=", 2, opid2('-','='), ASSOC_RIGHT, 8, 0, false},
{ "*=", 2, opid2('*','='), ASSOC_RIGHT, 8, 0, false},
{ "/=", 2, opid2('/','='), ASSOC_RIGHT, 8, 0, false},
{ "%=", 2, opid2('%','='), ASSOC_RIGHT, 8, 0, false},
{ "&=", 2, opid2('&','='), ASSOC_RIGHT, 8, 0, false},
{ "|=", 2, opid2('|','='), ASSOC_RIGHT, 8, 0, false},
{ "&~=", 2, opid3('&','~','='), ASSOC_RIGHT, 8, 0, false},
{ "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0, true},
{ "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0, true},
/* Leave precedence 3 for : with -fcorrect-ternary */
{ ",", 2, opid1(','), ASSOC_LEFT, 2, 0, false},
{ ":", 0, opid2(':','?'), ASSOC_RIGHT, 1, 0, false}
};
static const size_t c_operator_count = (sizeof(c_operators) / sizeof(c_operators[0]));
static const oper_info qcc_operators[] = {
{ "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX}, /* paren expression - non function call */
{ "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */
{ ".", 2, opid1('.'), ASSOC_LEFT, 15, 0 },
{ "(", 0, opid1('('), ASSOC_LEFT, 15, 0 }, /* function call */
{ ".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false},
{ "(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */
{ "[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */
{ "!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX },
{ "!", 1, opid2('!','P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
{ "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
{ "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
{ "*", 2, opid1('*'), ASSOC_LEFT, 13, 0 },
{ "/", 2, opid1('/'), ASSOC_LEFT, 13, 0 },
{ "&", 2, opid1('&'), ASSOC_LEFT, 13, 0 },
{ "|", 2, opid1('|'), ASSOC_LEFT, 13, 0 },
{ "*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true},
{ "/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true},
{ "&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true},
{ "|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true},
{ "+", 2, opid1('+'), ASSOC_LEFT, 12, 0 },
{ "-", 2, opid1('-'), ASSOC_LEFT, 12, 0 },
{ "+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true},
{ "-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true},
{ "<", 2, opid1('<'), ASSOC_LEFT, 10, 0 },
{ ">", 2, opid1('>'), ASSOC_LEFT, 10, 0 },
{ "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0 },
{ ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0 },
{ "==", 2, opid2('=','='), ASSOC_LEFT, 10, 0 },
{ "!=", 2, opid2('!','='), ASSOC_LEFT, 10, 0 },
{ "<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false},
{ ">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false},
{ "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0, false},
{ ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0, false},
{ "==", 2, opid2('=','='), ASSOC_LEFT, 10, 0, true},
{ "!=", 2, opid2('!','='), ASSOC_LEFT, 10, 0, true},
{ "=", 2, opid1('='), ASSOC_RIGHT, 8, 0 },
{ "+=", 2, opid2('+','='), ASSOC_RIGHT, 8, 0 },
{ "-=", 2, opid2('-','='), ASSOC_RIGHT, 8, 0 },
{ "*=", 2, opid2('*','='), ASSOC_RIGHT, 8, 0 },
{ "/=", 2, opid2('/','='), ASSOC_RIGHT, 8, 0 },
{ "%=", 2, opid2('%','='), ASSOC_RIGHT, 8, 0 },
{ "&=", 2, opid2('&','='), ASSOC_RIGHT, 8, 0 },
{ "|=", 2, opid2('|','='), ASSOC_RIGHT, 8, 0 },
{ "=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false},
{ "+=", 2, opid2('+','='), ASSOC_RIGHT, 8, 0, false},
{ "-=", 2, opid2('-','='), ASSOC_RIGHT, 8, 0, false},
{ "*=", 2, opid2('*','='), ASSOC_RIGHT, 8, 0, false},
{ "/=", 2, opid2('/','='), ASSOC_RIGHT, 8, 0, false},
{ "%=", 2, opid2('%','='), ASSOC_RIGHT, 8, 0, false},
{ "&=", 2, opid2('&','='), ASSOC_RIGHT, 8, 0, false},
{ "|=", 2, opid2('|','='), ASSOC_RIGHT, 8, 0, false},
{ "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0 },
{ "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0 },
{ "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0, true},
{ "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0, true},
{ ",", 2, opid1(','), ASSOC_LEFT, 1, 0 }
{ ",", 2, opid1(','), ASSOC_LEFT, 2, 0, false},
};
static const size_t qcc_operator_count = (sizeof(qcc_operators) / sizeof(qcc_operators[0]));
extern const oper_info *operators;
extern size_t operator_count;
void lexerror(lex_file*, const char *fmt, ...);
#endif

524
main.c
View file

@ -1,524 +0,0 @@
/*
* Copyright (C) 2012
* Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "gmqcc.h"
#include "lexer.h"
uint32_t opts_flags[1 + (COUNT_FLAGS / 32)];
uint32_t opts_warn [1 + (COUNT_WARNINGS / 32)];
uint32_t opts_O = 1;
const char *opts_output = "progs.dat";
int opts_standard = COMPILER_GMQCC;
bool opts_debug = false;
bool opts_memchk = false;
bool opts_dump = false;
bool opts_werror = false;
bool opts_forcecrc = false;
uint16_t opts_forced_crc;
static bool opts_output_wasset = false;
/* set by the standard */
const oper_info *operators = NULL;
size_t operator_count = 0;
typedef struct { char *filename; int type; } argitem;
VECTOR_MAKE(argitem, items);
#define TYPE_QC 0
#define TYPE_ASM 1
#define TYPE_SRC 2
static const char *app_name;
static int usage() {
printf("usage: %s [options] [files...]", app_name);
printf("options:\n"
" -h, --help show this help message\n"
" -debug turns on compiler debug messages\n"
" -memchk turns on compiler memory leak check\n");
printf(" -o, --output=file output file, defaults to progs.dat\n"
" -a filename add an asm file to be assembled\n"
" -s filename add a progs.src file to be used\n");
printf(" -f<flag> enable a flag\n"
" -fno-<flag> disable a flag\n"
" -std standard select one of the following standards\n"
" -std=qcc original QuakeC\n"
" -std=fteqcc fteqcc QuakeC\n"
" -std=gmqcc this compiler (default)\n");
printf(" -W<warning> enable a warning\n"
" -Wno-<warning> disable a warning\n"
" -Wall enable all warnings\n"
" -Werror treat warnings as errors\n");
printf(" -force-crc=num force a specific checksum into the header\n");
printf("\n");
printf("flags:\n"
" -fadjust-vector-fields\n"
" when assigning a vector field, its _y and _z fields also get assigned\n"
);
return -1;
}
static bool options_setflag_all(const char *name, bool on, uint32_t *flags, const opts_flag_def *list, size_t listsize) {
size_t i;
for (i = 0; i < listsize; ++i) {
if (!strcmp(name, list[i].name)) {
longbit lb = list[i].bit;
#if 0
if (on)
flags[lb.idx] |= (1<<(lb.bit));
else
flags[lb.idx] &= ~(1<<(lb.bit));
#else
if (on)
flags[0] |= (1<<lb);
else
flags[0] &= ~(1<<(lb));
#endif
return true;
}
}
return false;
}
static bool options_setflag(const char *name, bool on) {
return options_setflag_all(name, on, opts_flags, opts_flag_list, COUNT_FLAGS);
}
static bool options_setwarn(const char *name, bool on) {
return options_setflag_all(name, on, opts_warn, opts_warn_list, COUNT_WARNINGS);
}
static bool options_witharg(int *argc_, char ***argv_, char **out) {
int argc = *argc_;
char **argv = *argv_;
if (argv[0][2]) {
*out = argv[0]+2;
return true;
}
/* eat up the next */
if (argc < 2) /* no parameter was provided */
return false;
*out = argv[1];
--*argc_;
++*argv_;
return true;
}
static bool options_long_witharg_all(const char *optname, int *argc_, char ***argv_, char **out, int ds, bool split) {
int argc = *argc_;
char **argv = *argv_;
size_t len = strlen(optname);
if (strncmp(argv[0]+ds, optname, len))
return false;
/* it's --optname, check how the parameter is supplied */
if (argv[0][ds+len] == '=') {
/* using --opt=param */
*out = argv[0]+ds+len+1;
return true;
}
if (!split || argc < ds) /* no parameter was provided, or only single-arg form accepted */
return false;
/* using --opt param */
*out = argv[1];
--*argc_;
++*argv_;
return true;
}
static bool options_long_witharg(const char *optname, int *argc_, char ***argv_, char **out) {
return options_long_witharg_all(optname, argc_, argv_, out, 2, true);
}
static bool options_long_gcc(const char *optname, int *argc_, char ***argv_, char **out) {
return options_long_witharg_all(optname, argc_, argv_, out, 1, false);
}
static bool options_parse(int argc, char **argv) {
bool argend = false;
size_t itr;
char buffer[1024];
while (!argend && argc > 1) {
char *argarg;
argitem item;
++argv;
--argc;
if (argv[0][0] == '-') {
/* All gcc-type long options */
if (options_long_gcc("std", &argc, &argv, &argarg)) {
if (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default"))
opts_standard = COMPILER_GMQCC;
else if (!strcmp(argarg, "qcc"))
opts_standard = COMPILER_QCC;
else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc"))
opts_standard = COMPILER_FTEQCC;
else if (!strcmp(argarg, "qccx"))
opts_standard = COMPILER_QCCX;
else {
printf("Unknown standard: %s\n", argarg);
return false;
}
continue;
}
if (options_long_gcc("force-crc", &argc, &argv, &argarg)) {
opts_forcecrc = true;
opts_forced_crc = strtol(argarg, NULL, 0);
continue;
}
if (!strcmp(argv[0]+1, "debug")) {
opts_debug = true;
continue;
}
if (!strcmp(argv[0]+1, "dump")) {
opts_dump = true;
continue;
}
if (!strcmp(argv[0]+1, "memchk")) {
opts_memchk = true;
continue;
}
switch (argv[0][1]) {
/* -h, show usage but exit with 0 */
case 'h':
usage();
exit(0);
break;
/* handle all -fflags */
case 'f':
util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
if (!strcmp(argv[0]+2, "HELP")) {
printf("Possible flags:\n");
for (itr = 0; itr < COUNT_FLAGS; ++itr) {
util_strtononcmd(opts_flag_list[itr].name, buffer, sizeof(buffer));
printf(" -f%s\n", buffer);
}
exit(0);
}
else if (!strncmp(argv[0]+2, "NO_", 3)) {
if (!options_setflag(argv[0]+5, false)) {
printf("unknown flag: %s\n", argv[0]+2);
return false;
}
}
else if (!options_setflag(argv[0]+2, true)) {
printf("unknown flag: %s\n", argv[0]+2);
return false;
}
break;
case 'W':
util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
if (!strcmp(argv[0]+2, "HELP")) {
printf("Possible warnings:\n");
for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
util_strtononcmd(opts_warn_list[itr].name, buffer, sizeof(buffer));
printf(" -W%s\n", buffer);
}
exit(0);
}
else if (!strcmp(argv[0]+2, "NO_ERROR")) {
opts_werror = false;
break;
}
else if (!strcmp(argv[0]+2, "ERROR")) {
opts_werror = true;
break;
}
else if (!strcmp(argv[0]+2, "NONE")) {
for (itr = 0; itr < sizeof(opts_warn)/sizeof(opts_warn[0]); ++itr)
opts_warn[itr] = 0;
break;
}
else if (!strcmp(argv[0]+2, "ALL")) {
for (itr = 0; itr < sizeof(opts_warn)/sizeof(opts_warn[0]); ++itr)
opts_warn[itr] = 0xFFFFFFFFL;
break;
}
if (!strncmp(argv[0]+2, "NO_", 3)) {
if (!options_setwarn(argv[0]+5, false)) {
printf("unknown warning: %s\n", argv[0]+2);
return false;
}
}
else if (!options_setwarn(argv[0]+2, true)) {
printf("unknown warning: %s\n", argv[0]+2);
return false;
}
break;
case 'O':
if (!options_witharg(&argc, &argv, &argarg)) {
printf("option -O requires a numerical argument\n");
return false;
}
opts_O = atoi(argarg);
break;
case 'o':
if (!options_witharg(&argc, &argv, &argarg)) {
printf("option -o requires an argument: the output file name\n");
return false;
}
opts_output = argarg;
opts_output_wasset = true;
break;
case 'a':
case 's':
item.type = argv[0][1] == 'a' ? TYPE_ASM : TYPE_SRC;
if (!options_witharg(&argc, &argv, &argarg)) {
printf("option -a requires a filename %s\n",
(argv[0][1] == 'a' ? "containing QC-asm" : "containing a progs.src formatted list"));
return false;
}
item.filename = argarg;
items_add(item);
break;
case '-':
if (!argv[0][2]) {
/* anything following -- is considered a non-option argument */
argend = true;
break;
}
/* All long options without arguments */
else if (!strcmp(argv[0]+2, "help")) {
usage();
exit(0);
}
else {
/* All long options with arguments */
if (options_long_witharg("output", &argc, &argv, &argarg)) {
opts_output = argarg;
opts_output_wasset = true;
} else {
printf("Unknown parameter: %s\n", argv[0]);
return false;
}
}
break;
default:
printf("Unknown parameter: %s\n", argv[0]);
return false;
}
}
else
{
/* it's a QC filename */
argitem item;
item.filename = argv[0];
item.type = TYPE_QC;
items_add(item);
}
}
return true;
}
static void options_set(uint32_t *flags, size_t idx, bool on)
{
longbit lb = LONGBIT(idx);
#if 0
if (on)
flags[lb.idx] |= (1<<(lb.bit));
else
flags[lb.idx] &= ~(1<<(lb.bit));
#else
if (on)
flags[0] |= (1<<(lb));
else
flags[0] &= ~(1<<(lb));
#endif
}
/* returns the line number, or -1 on error */
static bool progs_nextline(char **out, size_t *alen,FILE *src)
{
int len;
char *line;
char *start;
char *end;
line = *out;
len = util_getline(&line, alen, src);
if (len == -1)
return false;
/* start at first non-blank */
for (start = line; isspace(*start); ++start) {}
/* end at the first non-blank */
for (end = start; *end && !isspace(*end); ++end) {}
*out = line;
/* move the actual filename to the beginning */
while (start != end) {
*line++ = *start++;
}
*line = 0;
return true;
}
int main(int argc, char **argv) {
size_t itr;
int retval = 0;
bool opts_output_free = false;
app_name = argv[0];
/* default options / warn flags */
options_set(opts_warn, WARN_UNKNOWN_CONTROL_SEQUENCE, true);
options_set(opts_warn, WARN_EXTENSIONS, true);
options_set(opts_warn, WARN_FIELD_REDECLARED, true);
options_set(opts_warn, WARN_TOO_FEW_PARAMETERS, true);
options_set(opts_warn, WARN_MISSING_RETURN_VALUES, true);
options_set(opts_warn, WARN_USED_UNINITIALIZED, true);
options_set(opts_warn, WARN_LOCAL_CONSTANTS, true);
options_set(opts_warn, WARN_VOID_VARIABLES, true);
options_set(opts_warn, WARN_IMPLICIT_FUNCTION_POINTER, true);
options_set(opts_warn, WARN_VARIADIC_FUNCTION, true);
options_set(opts_warn, WARN_FRAME_MACROS, true);
options_set(opts_warn, WARN_UNUSED_VARIABLE, true);
options_set(opts_warn, WARN_EFFECTLESS_STATEMENT, true);
options_set(opts_warn, WARN_END_SYS_FIELDS, true);
options_set(opts_warn, WARN_ASSIGN_FUNCTION_TYPES, true);
if (!options_parse(argc, argv)) {
return usage();
}
/* the standard decides which set of operators to use */
if (opts_standard == COMPILER_GMQCC) {
operators = c_operators;
operator_count = c_operator_count;
} else {
operators = qcc_operators;
operator_count = qcc_operator_count;
}
if (opts_dump) {
for (itr = 0; itr < COUNT_FLAGS; ++itr) {
printf("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr));
}
for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
printf("Warning %s = %i\n", opts_warn_list[itr].name, OPTS_WARN(itr));
}
printf("output = %s\n", opts_output);
printf("optimization level = %i\n", (int)opts_O);
printf("standard = %i\n", opts_standard);
}
if (!parser_init()) {
printf("failed to initialize parser\n");
retval = 1;
goto cleanup;
}
util_debug("COM", "starting ...\n");
if (items_elements) {
printf("Mode: manual\n");
printf("There are %lu items to compile:\n", (unsigned long)items_elements);
for (itr = 0; itr < items_elements; ++itr) {
printf(" item: %s (%s)\n",
items_data[itr].filename,
( (items_data[itr].type == TYPE_QC ? "qc" :
(items_data[itr].type == TYPE_ASM ? "asm" :
(items_data[itr].type == TYPE_SRC ? "progs.src" :
("unknown"))))));
if (!parser_compile(items_data[itr].filename)) {
retval = 1;
goto cleanup;
}
}
if (!parser_finish(opts_output)) {
retval = 1;
goto cleanup;
}
} else {
FILE *src;
char *line;
size_t linelen = 0;
printf("Mode: progs.src\n");
src = util_fopen("progs.src", "rb");
if (!src) {
printf("failed to open `progs.src` for reading\n");
retval = 1;
goto cleanup;
}
line = NULL;
if (!progs_nextline(&line, &linelen, src) || !line[0]) {
printf("illformatted progs.src file: expected output filename in first line\n");
retval = 1;
goto srcdone;
}
if (!opts_output_wasset) {
opts_output = util_strdup(line);
opts_output_free = true;
}
while (progs_nextline(&line, &linelen, src)) {
if (!line[0] || (line[0] == '/' && line[1] == '/'))
continue;
printf(" src: %s\n", line);
if (!parser_compile(line)) {
retval = 1;
goto srcdone;
}
}
parser_finish(opts_output);
srcdone:
fclose(src);
mem_d(line);
}
/* stuff */
cleanup:
util_debug("COM", "cleaning ...\n");
mem_d(items_data);
parser_cleanup();
if (opts_output_free)
mem_d((char*)opts_output);
lex_cleanup();
util_meminfo();
return retval;
}

772
main.cpp Normal file
View file

@ -0,0 +1,772 @@
#include <stdlib.h>
#include <string.h>
#include "gmqcc.h"
#include "lexer.h"
#include "parser.h"
/* TODO: cleanup this whole file .. it's a fuckign mess */
/* set by the standard */
const oper_info *operators = nullptr;
size_t operator_count = 0;
static bool opts_output_wasset = false;
struct argitem { char *filename; int type; };
struct ppitem { char *name; char *value; };
static argitem *items = nullptr;
static ppitem *ppems = nullptr;
#define TYPE_QC 0
#define TYPE_ASM 1
#define TYPE_SRC 2
static const char *app_name;
static void version(void) {
con_out("GMQCC %d.%d.%d Built %s %s\n" GMQCC_DEV_VERSION_STRING,
GMQCC_VERSION_MAJOR,
GMQCC_VERSION_MINOR,
GMQCC_VERSION_PATCH,
__DATE__,
__TIME__
);
}
static int usage(void) {
con_out("usage: %s [options] [files...]", app_name);
con_out("options:\n"
" -h, --help show this help message\n"
" -debug turns on compiler debug messages\n");
con_out(" -o, --output=file output file, defaults to progs.dat\n"
" -s filename add a progs.src file to be used\n");
con_out(" -E stop after preprocessing\n");
con_out(" -q, --quiet be less verbose\n");
con_out(" -config file use the specified ini file\n");
con_out(" -std=standard select one of the following standards\n"
" -std=qcc original QuakeC\n"
" -std=fteqcc fteqcc QuakeC\n"
" -std=gmqcc this compiler (default)\n");
con_out(" -f<flag> enable a flag\n"
" -fno-<flag> disable a flag\n"
" -fhelp list possible flags\n");
con_out(" -W<warning> enable a warning\n"
" -Wno-<warning> disable a warning\n"
" -Wall enable all warnings\n");
con_out(" -Werror treat warnings as errors\n"
" -Werror-<warning> treat a warning as error\n"
" -Wno-error-<warning> opposite of the above\n");
con_out(" -Whelp list possible warnings\n");
con_out(" -O<number> optimization level\n"
" -O<name> enable specific optimization\n"
" -Ono-<name> disable specific optimization\n"
" -Ohelp list optimizations\n");
con_out(" -force-crc=num force a specific checksum into the header\n");
con_out(" -state-fps=num emulate OP_STATE with the specified FPS\n");
con_out(" -coverage add coverage support\n");
return -1;
}
/* command line parsing */
static bool options_witharg(int *argc_, char ***argv_, char **out) {
int argc = *argc_;
char **argv = *argv_;
if (argv[0][2]) {
*out = argv[0]+2;
return true;
}
/* eat up the next */
if (argc < 2) /* no parameter was provided */
return false;
*out = argv[1];
--*argc_;
++*argv_;
return true;
}
static bool options_long_witharg_all(const char *optname, int *argc_, char ***argv_, char **out, int ds, bool split) {
int argc = *argc_;
char **argv = *argv_;
size_t len = strlen(optname);
if (strncmp(argv[0]+ds, optname, len))
return false;
/* it's --optname, check how the parameter is supplied */
if (argv[0][ds+len] == '=') {
/* using --opt=param */
*out = argv[0]+ds+len+1;
return true;
}
if (!split || argc < ds) /* no parameter was provided, or only single-arg form accepted */
return false;
/* using --opt param */
*out = argv[1];
--*argc_;
++*argv_;
return true;
}
static bool options_long_witharg(const char *optname, int *argc_, char ***argv_, char **out) {
return options_long_witharg_all(optname, argc_, argv_, out, 2, true);
}
static bool options_long_gcc(const char *optname, int *argc_, char ***argv_, char **out) {
return options_long_witharg_all(optname, argc_, argv_, out, 1, false);
}
static bool options_parse(int argc, char **argv, bool *has_progs_src) {
bool argend = false;
size_t itr;
char buffer[1024];
char *config = nullptr;
while (!argend && argc > 1) {
char *argarg;
argitem item;
ppitem macro;
++argv;
--argc;
if (argv[0][0] == '-') {
/* All gcc-type long options */
if (options_long_gcc("std", &argc, &argv, &argarg)) {
if (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default")) {
opts_set(opts.flags, ADJUST_VECTOR_FIELDS, true);
opts_set(opts.flags, CORRECT_LOGIC, true);
opts_set(opts.flags, SHORT_LOGIC, true);
opts_set(opts.flags, UNTYPED_NIL, true);
opts_set(opts.flags, VARIADIC_ARGS, true);
opts_set(opts.flags, FALSE_EMPTY_STRINGS, false);
opts_set(opts.flags, TRUE_EMPTY_STRINGS, true);
opts_set(opts.flags, LOOP_LABELS, true);
opts_set(opts.flags, TRANSLATABLE_STRINGS, true);
opts_set(opts.flags, INITIALIZED_NONCONSTANTS, true);
opts_set(opts.werror, WARN_INVALID_PARAMETER_COUNT, true);
opts_set(opts.werror, WARN_MISSING_RETURN_VALUES, true);
opts_set(opts.flags, EXPRESSIONS_FOR_BUILTINS, true);
opts_set(opts.warn, WARN_BREAKDEF, true);
OPTS_OPTION_U32(OPTION_STANDARD) = COMPILER_GMQCC;
} else if (!strcmp(argarg, "qcc")) {
opts_set(opts.flags, ADJUST_VECTOR_FIELDS, false);
opts_set(opts.flags, ASSIGN_FUNCTION_TYPES, true);
OPTS_OPTION_U32(OPTION_STANDARD) = COMPILER_QCC;
} else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc")) {
opts_set(opts.flags, FTEPP, true);
opts_set(opts.flags, TRANSLATABLE_STRINGS, true);
opts_set(opts.flags, ADJUST_VECTOR_FIELDS, false);
opts_set(opts.flags, ASSIGN_FUNCTION_TYPES, true);
opts_set(opts.flags, CORRECT_TERNARY, false);
opts_set(opts.warn, WARN_TERNARY_PRECEDENCE, true);
opts_set(opts.warn, WARN_BREAKDEF, true);
OPTS_OPTION_U32(OPTION_STANDARD) = COMPILER_FTEQCC;
} else if (!strcmp(argarg, "qccx")) {
opts_set(opts.flags, ADJUST_VECTOR_FIELDS, false);
OPTS_OPTION_U32(OPTION_STANDARD) = COMPILER_QCCX;
} else {
con_out("Unknown standard: %s\n", argarg);
return false;
}
continue;
}
if (options_long_gcc("force-crc", &argc, &argv, &argarg)) {
OPTS_OPTION_BOOL(OPTION_FORCECRC) = true;
OPTS_OPTION_U16 (OPTION_FORCED_CRC) = strtol(argarg, nullptr, 0);
continue;
}
if (options_long_gcc("state-fps", &argc, &argv, &argarg)) {
OPTS_OPTION_U32(OPTION_STATE_FPS) = strtol(argarg, nullptr, 0);
opts_set(opts.flags, EMULATE_STATE, true);
continue;
}
if (options_long_gcc("config", &argc, &argv, &argarg)) {
config = argarg;
continue;
}
if (options_long_gcc("progsrc", &argc, &argv, &argarg)) {
OPTS_OPTION_STR(OPTION_PROGSRC) = argarg;
*has_progs_src = true;
continue;
}
/* show defaults (like pathscale) */
if (!strcmp(argv[0]+1, "show-defaults")) {
for (itr = 0; itr < COUNT_FLAGS; ++itr) {
if (!OPTS_FLAG(itr))
continue;
memset(buffer, 0, sizeof(buffer));
util_strtononcmd(opts_flag_list[itr].name, buffer, strlen(opts_flag_list[itr].name) + 1);
con_out("-f%s ", buffer);
}
for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
if (!OPTS_WARN(itr))
continue;
memset(buffer, 0, sizeof(buffer));
util_strtononcmd(opts_warn_list[itr].name, buffer, strlen(opts_warn_list[itr].name) + 1);
con_out("-W%s ", buffer);
}
con_out("\n");
exit(0);
}
if (!strcmp(argv[0]+1, "debug")) {
OPTS_OPTION_BOOL(OPTION_DEBUG) = true;
continue;
}
if (!strcmp(argv[0]+1, "dump")) {
OPTS_OPTION_BOOL(OPTION_DUMP) = true;
continue;
}
if (!strcmp(argv[0]+1, "dumpfin")) {
OPTS_OPTION_BOOL(OPTION_DUMPFIN) = true;
continue;
}
if (!strcmp(argv[0]+1, "nocolor")) {
con_color(0);
continue;
}
if (!strcmp(argv[0]+1, "coverage")) {
OPTS_OPTION_BOOL(OPTION_COVERAGE) = true;
continue;
}
switch (argv[0][1]) {
/* -h, show usage but exit with 0 */
case 'h':
usage();
exit(0);
/* break; never reached because of exit(0) */
case 'v':
version();
exit(0);
case 'E':
OPTS_OPTION_BOOL(OPTION_PP_ONLY) = true;
opts_set(opts.flags, FTEPP_PREDEFS, true); /* predefs on for -E */
break;
/* debug turns on -flno */
case 'g':
opts_setflag("LNO", true);
OPTS_OPTION_BOOL(OPTION_G) = true;
break;
case 'q':
OPTS_OPTION_BOOL(OPTION_QUIET) = true;
break;
case 'D':
if (!strlen(argv[0]+2)) {
con_err("expected name after -D\n");
exit(0);
}
if (!(argarg = strchr(argv[0] + 2, '='))) {
macro.name = util_strdup(argv[0]+2);
macro.value = nullptr;
} else {
*argarg='\0'; /* terminate for name */
macro.name = util_strdup(argv[0]+2);
macro.value = util_strdup(argarg+1);
}
vec_push(ppems, macro);
break;
/* handle all -fflags */
case 'f':
util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
if (!strcmp(argv[0]+2, "HELP") || *(argv[0]+2) == '?') {
con_out("Possible flags:\n\n");
for (itr = 0; itr < COUNT_FLAGS; ++itr) {
util_strtononcmd(opts_flag_list[itr].name, buffer, sizeof(buffer));
con_out(" -f%s\n", buffer);
}
exit(0);
}
else if (!strncmp(argv[0]+2, "NO_", 3)) {
if (!opts_setflag(argv[0]+5, false)) {
con_out("unknown flag: %s\n", argv[0]+2);
return false;
}
}
else if (!opts_setflag(argv[0]+2, true)) {
con_out("unknown flag: %s\n", argv[0]+2);
return false;
}
break;
case 'W':
util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
if (!strcmp(argv[0]+2, "HELP") || *(argv[0]+2) == '?') {
con_out("Possible warnings:\n");
for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
util_strtononcmd(opts_warn_list[itr].name, buffer, sizeof(buffer));
con_out(" -W%s\n", buffer);
if (itr == WARN_DEBUG)
con_out(" Warnings included by -Wall:\n");
}
exit(0);
}
else if (!strcmp(argv[0]+2, "NO_ERROR") ||
!strcmp(argv[0]+2, "NO_ERROR_ALL"))
{
for (itr = 0; itr < GMQCC_ARRAY_COUNT(opts.werror); ++itr)
opts.werror[itr] = 0;
break;
}
else if (!strcmp(argv[0]+2, "ERROR") ||
!strcmp(argv[0]+2, "ERROR_ALL"))
{
opts_backup_non_Werror_all();
for (itr = 0; itr < GMQCC_ARRAY_COUNT(opts.werror); ++itr)
opts.werror[itr] = 0xFFFFFFFFL;
opts_restore_non_Werror_all();
break;
}
else if (!strcmp(argv[0]+2, "NONE")) {
for (itr = 0; itr < GMQCC_ARRAY_COUNT(opts.warn); ++itr)
opts.warn[itr] = 0;
break;
}
else if (!strcmp(argv[0]+2, "ALL")) {
opts_backup_non_Wall();
for (itr = 0; itr < GMQCC_ARRAY_COUNT(opts.warn); ++itr)
opts.warn[itr] = 0xFFFFFFFFL;
opts_restore_non_Wall();
break;
}
else if (!strncmp(argv[0]+2, "ERROR_", 6)) {
if (!opts_setwerror(argv[0]+8, true)) {
con_out("unknown warning: %s\n", argv[0]+2);
return false;
}
}
else if (!strncmp(argv[0]+2, "NO_ERROR_", 9)) {
if (!opts_setwerror(argv[0]+11, false)) {
con_out("unknown warning: %s\n", argv[0]+2);
return false;
}
}
else if (!strncmp(argv[0]+2, "NO_", 3)) {
if (!opts_setwarn(argv[0]+5, false)) {
con_out("unknown warning: %s\n", argv[0]+2);
return false;
}
}
else if (!opts_setwarn(argv[0]+2, true)) {
con_out("unknown warning: %s\n", argv[0]+2);
return false;
}
break;
case 'O':
if (!options_witharg(&argc, &argv, &argarg)) {
con_out("option -O requires a numerical argument, or optimization name with an optional 'no-' prefix\n");
return false;
}
if (util_isdigit(argarg[0])) {
uint32_t val = (uint32_t)strtol(argarg, nullptr, 10);
OPTS_OPTION_U32(OPTION_O) = val;
opts_setoptimlevel(val);
} else {
util_strtocmd(argarg, argarg, strlen(argarg)+1);
if (!strcmp(argarg, "HELP")) {
con_out("Possible optimizations:\n");
for (itr = 0; itr < COUNT_OPTIMIZATIONS; ++itr) {
util_strtononcmd(opts_opt_list[itr].name, buffer, sizeof(buffer));
con_out(" -O%-20s (-O%u)\n", buffer, opts_opt_oflag[itr]);
}
exit(0);
}
else if (!strcmp(argarg, "ALL"))
opts_setoptimlevel(OPTS_OPTION_U32(OPTION_O) = 9999);
else if (!strncmp(argarg, "NO_", 3)) {
/* constant folding cannot be turned off for obvious reasons */
if (!strcmp(argarg, "NO_CONST_FOLD") || !opts_setoptim(argarg+3, false)) {
con_out("unknown optimization: %s\n", argarg+3);
return false;
}
}
else {
if (!opts_setoptim(argarg, true)) {
con_out("unknown optimization: %s\n", argarg);
return false;
}
}
}
break;
case 'o':
if (!options_witharg(&argc, &argv, &argarg)) {
con_out("option -o requires an argument: the output file name\n");
return false;
}
OPTS_OPTION_STR(OPTION_OUTPUT) = argarg;
opts_output_wasset = true;
break;
case 'a':
case 's':
item.type = argv[0][1] == 'a' ? TYPE_ASM : TYPE_SRC;
if (!options_witharg(&argc, &argv, &argarg)) {
con_out("option -a requires a filename %s\n",
(argv[0][1] == 'a' ? "containing QC-asm" : "containing a progs.src formatted list"));
return false;
}
item.filename = argarg;
vec_push(items, item);
if (item.type == TYPE_SRC) {
*has_progs_src = true;
}
break;
case '-':
if (!argv[0][2]) {
/* anything following -- is considered a non-option argument */
argend = true;
break;
}
/* All long options without arguments */
else if (!strcmp(argv[0]+2, "help")) {
usage();
exit(0);
}
else if (!strcmp(argv[0]+2, "version")) {
version();
exit(0);
}
else if (!strcmp(argv[0]+2, "quiet")) {
OPTS_OPTION_BOOL(OPTION_QUIET) = true;
break;
}
else if (!strcmp(argv[0]+2, "add-info")) {
OPTS_OPTION_BOOL(OPTION_ADD_INFO) = true;
break;
}
else {
/* All long options with arguments */
if (options_long_witharg("output", &argc, &argv, &argarg)) {
OPTS_OPTION_STR(OPTION_OUTPUT) = argarg;
opts_output_wasset = true;
} else {
con_out("Unknown parameter: %s\n", argv[0]);
return false;
}
}
break;
default:
con_out("Unknown parameter: %s\n", argv[0]);
return false;
}
}
else
{
/* it's a QC filename */
item.filename = argv[0];
item.type = TYPE_QC;
vec_push(items, item);
}
}
opts_ini_init(config);
return true;
}
/* returns the line number, or -1 on error */
static bool progs_nextline(char **out, size_t *alen, FILE *src) {
int len;
char *line;
char *start;
char *end;
line = *out;
len = util_getline(&line, alen, src);
if (len == -1)
return false;
/* start at first non-blank */
for (start = line; util_isspace(*start); ++start) {}
/* end at the first non-blank */
for (end = start; *end && !util_isspace(*end); ++end) {}
*out = line;
/* move the actual filename to the beginning */
while (start != end) {
*line++ = *start++;
}
*line = 0;
return true;
}
int main(int argc, char **argv) {
size_t itr;
int retval = 0;
bool operators_free = false;
bool has_progs_src = false;
FILE *outfile = nullptr;
parser_t *parser = nullptr;
ftepp_t *ftepp = nullptr;
app_name = argv[0];
con_init ();
opts_init("progs.dat", COMPILER_QCC, (1024 << 3));
util_seed(time(0));
if (!options_parse(argc, argv, &has_progs_src)) {
return usage();
}
if (OPTS_FLAG(TRUE_EMPTY_STRINGS) && OPTS_FLAG(FALSE_EMPTY_STRINGS)) {
con_err("-ftrue-empty-strings and -ffalse-empty-strings are mutually exclusive");
exit(EXIT_FAILURE);
}
/* the standard decides which set of operators to use */
if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_GMQCC) {
operators = c_operators;
operator_count = GMQCC_ARRAY_COUNT(c_operators);
} else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC) {
operators = fte_operators;
operator_count = GMQCC_ARRAY_COUNT(fte_operators);
} else {
operators = qcc_operators;
operator_count = GMQCC_ARRAY_COUNT(qcc_operators);
}
if (operators == fte_operators) {
/* fix ternary? */
if (OPTS_FLAG(CORRECT_TERNARY)) {
oper_info *newops;
if (operators[operator_count-2].id != opid1(',') ||
operators[operator_count-1].id != opid2(':','?'))
{
con_err("internal error: operator precedence table wasn't updated correctly!\n");
exit(EXIT_FAILURE);
}
operators_free = true;
newops = (oper_info*)mem_a(sizeof(operators[0]) * operator_count);
memcpy(newops, operators, sizeof(operators[0]) * operator_count);
memcpy(&newops[operator_count-2], &operators[operator_count-1], sizeof(newops[0]));
memcpy(&newops[operator_count-1], &operators[operator_count-2], sizeof(newops[0]));
newops[operator_count-2].prec = newops[operator_count-1].prec+1;
operators = newops;
}
}
if (OPTS_OPTION_BOOL(OPTION_DUMP)) {
for (itr = 0; itr < COUNT_FLAGS; ++itr)
con_out("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr));
for (itr = 0; itr < COUNT_WARNINGS; ++itr)
con_out("Warning %s = %i\n", opts_warn_list[itr].name, OPTS_WARN(itr));
con_out("output = %s\n", OPTS_OPTION_STR(OPTION_OUTPUT));
con_out("optimization level = %u\n", OPTS_OPTION_U32(OPTION_O));
con_out("standard = %u\n", OPTS_OPTION_U32(OPTION_STANDARD));
}
if (OPTS_OPTION_BOOL(OPTION_PP_ONLY)) {
if (opts_output_wasset) {
outfile = fopen(OPTS_OPTION_STR(OPTION_OUTPUT), "wb");
if (!outfile) {
con_err("failed to open `%s` for writing\n", OPTS_OPTION_STR(OPTION_OUTPUT));
retval = 1;
goto cleanup;
}
}
else {
outfile = con_default_out();
}
}
if (!OPTS_OPTION_BOOL(OPTION_PP_ONLY)) {
if (!(parser = parser_create())) {
con_err("failed to initialize parser\n");
retval = 1;
goto cleanup;
}
}
if (OPTS_OPTION_BOOL(OPTION_PP_ONLY) || OPTS_FLAG(FTEPP)) {
if (!(ftepp = ftepp_create())) {
con_err("failed to initialize parser\n");
retval = 1;
goto cleanup;
}
}
/* add macros */
if (OPTS_OPTION_BOOL(OPTION_PP_ONLY) || OPTS_FLAG(FTEPP)) {
for (itr = 0; itr < vec_size(ppems); itr++) {
ftepp_add_macro(ftepp, ppems[itr].name, ppems[itr].value);
mem_d(ppems[itr].name);
/* can be null */
if (ppems[itr].value)
mem_d(ppems[itr].value);
}
}
if (!vec_size(items) && !has_progs_src) {
FILE *fp = fopen(OPTS_OPTION_STR(OPTION_PROGSRC), "rb");
if (fp) {
has_progs_src = true;
fclose(fp);
}
}
if (has_progs_src) {
FILE *src;
char *line = nullptr;
size_t linelen = 0;
bool has_first_line = false;
src = fopen(OPTS_OPTION_STR(OPTION_PROGSRC), "rb");
if (!src) {
con_err("failed to open `%s` for reading\n", OPTS_OPTION_STR(OPTION_PROGSRC));
retval = 1;
goto cleanup;
}
while (progs_nextline(&line, &linelen, src)) {
argitem item;
if (!line[0] || (line[0] == '/' && line[1] == '/')) {
continue;
}
if (has_first_line) {
item.filename = util_strdup(line);
item.type = TYPE_QC;
vec_push(items, item);
} else {
if (!opts_output_wasset) {
OPTS_OPTION_DUP(OPTION_OUTPUT) = util_strdup(line);
}
has_first_line = true;
}
}
fclose(src);
mem_d(line);
}
if (vec_size(items)) {
if (!OPTS_OPTION_BOOL(OPTION_QUIET) &&
!OPTS_OPTION_BOOL(OPTION_PP_ONLY))
{
con_out("Mode: %s\n", (has_progs_src ? "progs.src" : "manual"));
con_out("There are %lu items to compile:\n", (unsigned long)vec_size(items));
}
for (itr = 0; itr < vec_size(items); ++itr) {
if (!OPTS_OPTION_BOOL(OPTION_QUIET) &&
!OPTS_OPTION_BOOL(OPTION_PP_ONLY))
{
con_out(" item: %s (%s)\n",
items[itr].filename,
( (items[itr].type == TYPE_QC ? "qc" :
(items[itr].type == TYPE_ASM ? "asm" :
(items[itr].type == TYPE_SRC ? "progs.src" :
("unknown"))))));
}
if (items[itr].type == TYPE_SRC) {
continue;
}
if (OPTS_OPTION_BOOL(OPTION_PP_ONLY)) {
const char *out;
if (!ftepp_preprocess_file(ftepp, items[itr].filename)) {
retval = 1;
goto cleanup;
}
out = ftepp_get(ftepp);
if (out)
fprintf(outfile, "%s", out);
ftepp_flush(ftepp);
}
else {
if (OPTS_FLAG(FTEPP)) {
const char *data;
if (!ftepp_preprocess_file(ftepp, items[itr].filename)) {
retval = 1;
goto cleanup;
}
data = ftepp_get(ftepp);
if (vec_size(data)) {
if (!parser_compile_string(parser, items[itr].filename, data, vec_size(data))) {
retval = 1;
goto cleanup;
}
}
ftepp_flush(ftepp);
}
else {
if (!parser_compile_file(parser, items[itr].filename)) {
retval = 1;
goto cleanup;
}
}
}
if (has_progs_src) {
mem_d(items[itr].filename);
items[itr].filename = nullptr;
}
}
ftepp_finish(ftepp);
ftepp = nullptr;
if (!OPTS_OPTION_BOOL(OPTION_PP_ONLY)) {
if (!parser_finish(parser, OPTS_OPTION_STR(OPTION_OUTPUT))) {
retval = 1;
goto cleanup;
}
}
}
cleanup:
if (ftepp)
ftepp_finish(ftepp);
con_close();
vec_free(items);
vec_free(ppems);
if (!OPTS_OPTION_BOOL(OPTION_PP_ONLY))
delete parser;
/* free allocated option strings */
for (itr = 0; itr < OPTION_COUNT; itr++)
if (OPTS_OPTION_DUPED(itr))
mem_d(OPTS_OPTION_STR(itr));
if (operators_free)
mem_d((void*)operators);
lex_cleanup();
if (!retval && compile_errors)
retval = 1;
return retval;
}

51
misc/check-doc.sh Executable file
View file

@ -0,0 +1,51 @@
#!/bin/sh
prog=$0
die() {
echo "$@"
exit 1
}
want() {
test -e "$1" && return
echo "$prog: missing $1"
echo "$prog: run this script from the top of a gmqcc source tree"
exit 1
}
for i in opts.def \
doc/gmqcc.1 \
gmqcc.ini.example
do want "$i"; done
# y/_ABCDEFGHIJKLMNOPQRSTUVWXYZ/-abcdefghijklmnopqrstuvwxyz/;
check_opt() {
opt_def_name=$1
arg_char=$2
for i in $(sed -ne \
'/^#ifdef GMQCC_TYPE_'${opt_def_name}'$/,/^#endif/{
/GMQCC_DEFINE_FLAG/{
s/^.*GMQCC_DEFINE_FLAG(\([^,)]*\)[),].*$/\1/;p;
}
}' opts.def)
do
opt=$(echo "$i" | tr -- '_A-Z' '-a-z')
grep -qF -- ".It Fl "${arg_char}" Ns Cm $opt" \
doc/gmqcc.1 || echo "doc/gmqcc.1: missing: -${arg_char}$opt"
grep -q -- "[^a-zA-Z_]$i[^a-zA-Z_]" \
gmqcc.ini.example || echo "gmqcc.ini.example: missing: $i"
done
}
check_opt FLAGS f
check_opt WARNS W
check_opt OPTIMIZATIONS O
# TODO: linux version
if [ "$(uname -s)" != "Linux" ]; then
for i in doc/*.1;
do
mandoc -Tlint -Wall "$i";
done
fi

424
opts.cpp Normal file
View file

@ -0,0 +1,424 @@
#include <string.h>
#include <stdlib.h>
#include "gmqcc.h"
const unsigned int opts_opt_oflag[COUNT_OPTIMIZATIONS+1] = {
# define GMQCC_TYPE_OPTIMIZATIONS
# define GMQCC_DEFINE_FLAG(NAME, MIN_O) MIN_O,
# include "opts.def"
0
};
const opts_flag_def_t opts_opt_list[COUNT_OPTIMIZATIONS+1] = {
# define GMQCC_TYPE_OPTIMIZATIONS
# define GMQCC_DEFINE_FLAG(NAME, MIN_O) { #NAME, LONGBIT(OPTIM_##NAME) },
# include "opts.def"
{ nullptr, LONGBIT(0) }
};
const opts_flag_def_t opts_warn_list[COUNT_WARNINGS+1] = {
# define GMQCC_TYPE_WARNS
# define GMQCC_DEFINE_FLAG(X) { #X, LONGBIT(WARN_##X) },
# include "opts.def"
{ nullptr, LONGBIT(0) }
};
const opts_flag_def_t opts_flag_list[COUNT_FLAGS+1] = {
# define GMQCC_TYPE_FLAGS
# define GMQCC_DEFINE_FLAG(X) { #X, LONGBIT(X) },
# include "opts.def"
{ nullptr, LONGBIT(0) }
};
unsigned int opts_optimizationcount[COUNT_OPTIMIZATIONS];
opts_cmd_t opts; /* command line options */
static void opts_setdefault(void) {
memset(&opts, 0, sizeof(opts_cmd_t));
OPTS_OPTION_STR(OPTION_PROGSRC) = "progs.src";
/* warnings */
opts_set(opts.warn, WARN_UNUSED_VARIABLE, true);
opts_set(opts.warn, WARN_USED_UNINITIALIZED, true);
opts_set(opts.warn, WARN_UNKNOWN_CONTROL_SEQUENCE, true);
opts_set(opts.warn, WARN_EXTENSIONS, true);
opts_set(opts.warn, WARN_FIELD_REDECLARED, true);
opts_set(opts.warn, WARN_MISSING_RETURN_VALUES, true);
opts_set(opts.warn, WARN_INVALID_PARAMETER_COUNT, true);
opts_set(opts.warn, WARN_LOCAL_CONSTANTS, true);
opts_set(opts.warn, WARN_VOID_VARIABLES, true);
opts_set(opts.warn, WARN_IMPLICIT_FUNCTION_POINTER, true);
opts_set(opts.warn, WARN_VARIADIC_FUNCTION, true);
opts_set(opts.warn, WARN_FRAME_MACROS, true);
opts_set(opts.warn, WARN_EFFECTLESS_STATEMENT, true);
opts_set(opts.warn, WARN_END_SYS_FIELDS, true);
opts_set(opts.warn, WARN_ASSIGN_FUNCTION_TYPES, true);
opts_set(opts.warn, WARN_CPP, true);
opts_set(opts.warn, WARN_MULTIFILE_IF, true);
opts_set(opts.warn, WARN_DOUBLE_DECLARATION, true);
opts_set(opts.warn, WARN_CONST_VAR, true);
opts_set(opts.warn, WARN_MULTIBYTE_CHARACTER, true);
opts_set(opts.warn, WARN_UNKNOWN_PRAGMAS, true);
opts_set(opts.warn, WARN_UNREACHABLE_CODE, true);
opts_set(opts.warn, WARN_UNKNOWN_ATTRIBUTE, true);
opts_set(opts.warn, WARN_RESERVED_NAMES, true);
opts_set(opts.warn, WARN_UNINITIALIZED_CONSTANT, true);
opts_set(opts.warn, WARN_DEPRECATED, true);
opts_set(opts.warn, WARN_PARENTHESIS, true);
opts_set(opts.warn, WARN_CONST_OVERWRITE, true);
opts_set(opts.warn, WARN_DIRECTIVE_INMACRO, true);
opts_set(opts.warn, WARN_BUILTINS, true);
opts_set(opts.warn, WARN_INEXACT_COMPARES, true);
/* flags */
opts_set(opts.flags, ADJUST_VECTOR_FIELDS, true);
opts_set(opts.flags, CORRECT_TERNARY, true);
opts_set(opts.flags, BAIL_ON_WERROR, true);
opts_set(opts.flags, LEGACY_VECTOR_MATHS, true);
opts_set(opts.flags, DARKPLACES_STRING_TABLE_BUG, true);
/* options */
OPTS_OPTION_U32(OPTION_STATE_FPS) = 10;
}
void opts_backup_non_Wall() {
size_t i;
for (i = 0; i <= WARN_DEBUG; ++i)
opts_set(opts.warn_backup, i, OPTS_WARN(i));
}
void opts_restore_non_Wall() {
size_t i;
for (i = 0; i <= WARN_DEBUG; ++i)
opts_set(opts.warn, i, OPTS_GENERIC(opts.warn_backup, i));
}
void opts_backup_non_Werror_all() {
size_t i;
for (i = 0; i <= WARN_DEBUG; ++i)
opts_set(opts.werror_backup, i, OPTS_WERROR(i));
}
void opts_restore_non_Werror_all() {
size_t i;
for (i = 0; i <= WARN_DEBUG; ++i)
opts_set(opts.werror, i, OPTS_GENERIC(opts.werror_backup, i));
}
void opts_init(const char *output, int standard, size_t arraysize) {
opts_setdefault();
OPTS_OPTION_STR(OPTION_OUTPUT) = output;
OPTS_OPTION_U32(OPTION_STANDARD) = standard;
OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE) = arraysize;
}
static bool opts_setflag_all(const char *name, bool on, uint32_t *flags, const opts_flag_def_t *list, size_t listsize) {
size_t i;
for (i = 0; i < listsize; ++i) {
if (!strcmp(name, list[i].name)) {
longbit lb = list[i].bit;
if (on)
flags[lb.idx] |= (1<<(lb.bit));
else
flags[lb.idx] &= ~(1<<(lb.bit));
return true;
}
}
return false;
}
bool opts_setflag (const char *name, bool on) {
return opts_setflag_all(name, on, opts.flags, opts_flag_list, COUNT_FLAGS);
}
bool opts_setwarn (const char *name, bool on) {
return opts_setflag_all(name, on, opts.warn, opts_warn_list, COUNT_WARNINGS);
}
bool opts_setwerror(const char *name, bool on) {
return opts_setflag_all(name, on, opts.werror, opts_warn_list, COUNT_WARNINGS);
}
bool opts_setoptim (const char *name, bool on) {
return opts_setflag_all(name, on, opts.optimization, opts_opt_list, COUNT_OPTIMIZATIONS);
}
void opts_set(uint32_t *flags, size_t idx, bool on) {
longbit lb;
LONGBIT_SET(lb, idx);
if (on)
flags[lb.idx] |= (1u<<(lb.bit));
else
flags[lb.idx] &= ~(1u<<(lb.bit));
}
void opts_setoptimlevel(unsigned int level) {
size_t i;
for (i = 0; i < COUNT_OPTIMIZATIONS; ++i)
opts_set(opts.optimization, i, level >= opts_opt_oflag[i]);
if (!level)
opts.optimizeoff = true;
}
/*
* Standard configuration parser and subsystem. Yes, optionally you may
* create ini files or cfg (the driver accepts both) for a project opposed
* to supplying just a progs.src (since you also may need to supply command
* line arguments or set the options of the compiler) [which cannot be done
* from a progs.src.
*/
static char *opts_ini_rstrip(char *s) {
char *p = s + strlen(s) - 1;
while (p > s && util_isspace(*p))
*p = '\0', p--;
return s;
}
static char *opts_ini_lskip(const char *s) {
while (*s && util_isspace(*s))
s++;
return (char*)s;
}
static char *opts_ini_next(const char *s, char c) {
bool last = false;
while (*s && *s != c && !(last && *s == ';'))
last = !!util_isspace(*s), s++;
return (char*)s;
}
static size_t opts_ini_parse (
FILE *filehandle,
char *(*loadhandle)(const char *, const char *, const char *, char **),
char **errorhandle,
char **parse_file
) {
size_t linesize;
size_t lineno = 1;
size_t error = 0;
char *line = nullptr;
char section_data[2048] = "";
char oldname_data[2048] = "";
/* parsing and reading variables */
char *parse_beg;
char *parse_end;
char *read_name;
char *read_value;
while (util_getline(&line, &linesize, filehandle) != EOF) {
parse_beg = line;
/* handle BOM */
if (lineno == 1 && (
(unsigned char)parse_beg[0] == 0xEF &&
(unsigned char)parse_beg[1] == 0xBB &&
(unsigned char)parse_beg[2] == 0xBF
)
) {
parse_beg ++; /* 0xEF */
parse_beg ++; /* 0xBB */
parse_beg ++; /* 0xBF */
}
if (*(parse_beg = opts_ini_lskip(opts_ini_rstrip(parse_beg))) == ';' || *parse_beg == '#') {
/* ignore '#' is a perl extension */
} else if (*parse_beg == '[') {
/* section found */
if (*(parse_end = opts_ini_next(parse_beg + 1, ']')) == ']') {
* parse_end = '\0'; /* terminate bro */
util_strncpy(section_data, parse_beg + 1, sizeof(section_data));
section_data[sizeof(section_data) - 1] = '\0';
*oldname_data = '\0';
} else if (!error) {
/* otherwise set error to the current line number */
error = lineno;
}
} else if (*parse_beg && *parse_beg != ';') {
/* not a comment, must be a name value pair :) */
if (*(parse_end = opts_ini_next(parse_beg, '=')) != '=')
parse_end = opts_ini_next(parse_beg, ':');
if (*parse_end == '=' || *parse_end == ':') {
*parse_end = '\0'; /* terminate bro */
read_name = opts_ini_rstrip(parse_beg);
read_value = opts_ini_lskip(parse_end + 1);
if (*(parse_end = opts_ini_next(read_value, '\0')) == ';')
* parse_end = '\0';
opts_ini_rstrip(read_value);
/* valid name value pair, lets call down to handler */
util_strncpy(oldname_data, read_name, sizeof(oldname_data));
oldname_data[sizeof(oldname_data) - 1] ='\0';
if ((*errorhandle = loadhandle(section_data, read_name, read_value, parse_file)) && !error)
error = lineno;
} else if (!strcmp(section_data, "includes")) {
/* Includes are special */
if (*(parse_end = opts_ini_next(parse_beg, '=')) == '='
|| *(parse_end = opts_ini_next(parse_beg, ':')) == ':') {
static const char *invalid_include = "invalid use of include";
vec_append(*errorhandle, strlen(invalid_include), invalid_include);
error = lineno;
} else {
read_name = opts_ini_rstrip(parse_beg);
if ((*errorhandle = loadhandle(section_data, read_name, read_name, parse_file)) && !error)
error = lineno;
}
} else if (!error) {
/* otherwise set error to the current line number */
error = lineno;
}
}
lineno++;
}
mem_d(line);
return error;
}
/*
* returns true/false for a char that contains ("true" or "false" or numeric 0/1)
*/
static bool opts_ini_bool(const char *value) {
if (!strcmp(value, "true")) return true;
if (!strcmp(value, "false")) return false;
return !!strtol(value, nullptr, 10);
}
static char *opts_ini_load(const char *section, const char *name, const char *value, char **parse_file) {
char *error = nullptr;
bool found = false;
/*
* undef all of these because they may still be defined like in my
* case they where.
*/
#undef GMQCC_TYPE_FLAGS
#undef GMQCC_TYPE_OPTIMIZATIONS
#undef GMQCC_TYPE_WARNS
/* deal with includes */
if (!strcmp(section, "includes")) {
static const char *include_error_beg = "failed to open file `";
static const char *include_error_end = "' for inclusion";
FILE *file = fopen(value, "r");
found = true;
if (!file) {
vec_append(error, strlen(include_error_beg), include_error_beg);
vec_append(error, strlen(value), value);
vec_append(error, strlen(include_error_end), include_error_end);
} else {
if (opts_ini_parse(file, &opts_ini_load, &error, parse_file) != 0)
found = false;
/* Change the file name */
mem_d(*parse_file);
*parse_file = util_strdup(value);
fclose(file);
}
}
/* flags */
#define GMQCC_TYPE_FLAGS
#define GMQCC_DEFINE_FLAG(X) \
if (!strcmp(section, "flags") && !strcmp(name, #X)) { \
opts_set(opts.flags, X, opts_ini_bool(value)); \
found = true; \
}
#include "opts.def"
/* warnings */
#define GMQCC_TYPE_WARNS
#define GMQCC_DEFINE_FLAG(X) \
if (!strcmp(section, "warnings") && !strcmp(name, #X)) { \
opts_set(opts.warn, WARN_##X, opts_ini_bool(value)); \
found = true; \
}
#include "opts.def"
/* Werror-individuals */
#define GMQCC_TYPE_WARNS
#define GMQCC_DEFINE_FLAG(X) \
if (!strcmp(section, "errors") && !strcmp(name, #X)) { \
opts_set(opts.werror, WARN_##X, opts_ini_bool(value)); \
found = true; \
}
#include "opts.def"
/* optimizations */
#define GMQCC_TYPE_OPTIMIZATIONS
#define GMQCC_DEFINE_FLAG(X,Y) \
if (!strcmp(section, "optimizations") && !strcmp(name, #X)) { \
opts_set(opts.optimization, OPTIM_##X, opts_ini_bool(value)); \
found = true; \
}
#include "opts.def"
/* nothing was found ever! */
if (!found) {
if (strcmp(section, "includes") &&
strcmp(section, "flags") &&
strcmp(section, "warnings") &&
strcmp(section, "optimizations"))
{
static const char *invalid_section = "invalid_section `";
vec_append(error, strlen(invalid_section), invalid_section);
vec_append(error, strlen(section), section);
vec_push(error, '`');
} else if (strcmp(section, "includes")) {
static const char *invalid_variable = "invalid_variable `";
static const char *in_section = "` in section: `";
vec_append(error, strlen(invalid_variable), invalid_variable);
vec_append(error, strlen(name), name);
vec_append(error, strlen(in_section), in_section);
vec_append(error, strlen(section), section);
vec_push(error, '`');
} else {
static const char *expected_something = "expected something";
vec_append(error, strlen(expected_something), expected_something);
}
}
vec_push(error, '\0');
return error;
}
/*
* Actual loading subsystem, this finds the ini or cfg file, and properly
* loads it and executes it to set compiler options.
*/
void opts_ini_init(const char *file) {
/*
* Possible matches are:
* gmqcc.ini
* gmqcc.cfg
*/
char *error = nullptr;
char *parse_file = nullptr;
size_t line;
FILE *ini;
if (!file) {
/* try ini */
if (!(ini = fopen((file = "gmqcc.ini"), "r")))
/* try cfg */
if (!(ini = fopen((file = "gmqcc.cfg"), "r")))
return;
} else if (!(ini = fopen(file, "r")))
return;
con_out("found ini file `%s`\n", file);
parse_file = util_strdup(file);
if ((line = opts_ini_parse(ini, &opts_ini_load, &error, &parse_file)) != 0) {
/* there was a parse error with the ini file */
con_printmsg(LVL_ERROR, parse_file, line, 0 /*TODO: column for ini error*/, "error", error);
vec_free(error);
}
mem_d(parse_file);
fclose(ini);
}

126
opts.def Normal file
View file

@ -0,0 +1,126 @@
#ifndef GMQCC_DEFINE_FLAG
# error "bad opts.def usage"
#endif
/* codegen flags */
#ifdef GMQCC_TYPE_FLAGS
GMQCC_DEFINE_FLAG(DARKPLACES_STRING_TABLE_BUG)
GMQCC_DEFINE_FLAG(ADJUST_VECTOR_FIELDS)
GMQCC_DEFINE_FLAG(FTEPP)
GMQCC_DEFINE_FLAG(FTEPP_PREDEFS)
GMQCC_DEFINE_FLAG(FTEPP_MATHDEFS)
GMQCC_DEFINE_FLAG(FTEPP_INDIRECT_EXPANSION)
GMQCC_DEFINE_FLAG(RELAXED_SWITCH)
GMQCC_DEFINE_FLAG(SHORT_LOGIC)
GMQCC_DEFINE_FLAG(PERL_LOGIC)
GMQCC_DEFINE_FLAG(TRANSLATABLE_STRINGS)
GMQCC_DEFINE_FLAG(INITIALIZED_NONCONSTANTS)
GMQCC_DEFINE_FLAG(ASSIGN_FUNCTION_TYPES)
GMQCC_DEFINE_FLAG(LNO)
GMQCC_DEFINE_FLAG(CORRECT_TERNARY)
GMQCC_DEFINE_FLAG(SINGLE_VECTOR_DEFS)
GMQCC_DEFINE_FLAG(CORRECT_LOGIC)
GMQCC_DEFINE_FLAG(TRUE_EMPTY_STRINGS)
GMQCC_DEFINE_FLAG(FALSE_EMPTY_STRINGS)
GMQCC_DEFINE_FLAG(UTF8)
GMQCC_DEFINE_FLAG(BAIL_ON_WERROR)
GMQCC_DEFINE_FLAG(LOOP_LABELS)
GMQCC_DEFINE_FLAG(UNTYPED_NIL)
GMQCC_DEFINE_FLAG(PERMISSIVE)
GMQCC_DEFINE_FLAG(VARIADIC_ARGS)
GMQCC_DEFINE_FLAG(LEGACY_VECTOR_MATHS)
GMQCC_DEFINE_FLAG(EXPRESSIONS_FOR_BUILTINS)
GMQCC_DEFINE_FLAG(RETURN_ASSIGNMENTS)
GMQCC_DEFINE_FLAG(UNSAFE_VARARGS)
GMQCC_DEFINE_FLAG(TYPELESS_STORES)
GMQCC_DEFINE_FLAG(SORT_OPERANDS)
GMQCC_DEFINE_FLAG(EMULATE_STATE)
GMQCC_DEFINE_FLAG(ARITHMETIC_EXCEPTIONS)
GMQCC_DEFINE_FLAG(SPLIT_VECTOR_PARAMETERS)
GMQCC_DEFINE_FLAG(DEFAULT_ERASEABLE)
#endif
/* warning flags */
#ifdef GMQCC_TYPE_WARNS
GMQCC_DEFINE_FLAG(UNINITIALIZED_GLOBAL)
GMQCC_DEFINE_FLAG(DEBUG)
GMQCC_DEFINE_FLAG(UNUSED_VARIABLE)
GMQCC_DEFINE_FLAG(UNUSED_COMPONENT)
GMQCC_DEFINE_FLAG(USED_UNINITIALIZED)
GMQCC_DEFINE_FLAG(UNKNOWN_CONTROL_SEQUENCE)
GMQCC_DEFINE_FLAG(EXTENSIONS)
GMQCC_DEFINE_FLAG(FIELD_REDECLARED)
GMQCC_DEFINE_FLAG(MISSING_RETURN_VALUES)
GMQCC_DEFINE_FLAG(INVALID_PARAMETER_COUNT)
GMQCC_DEFINE_FLAG(LOCAL_SHADOWS)
GMQCC_DEFINE_FLAG(LOCAL_CONSTANTS)
GMQCC_DEFINE_FLAG(VOID_VARIABLES)
GMQCC_DEFINE_FLAG(IMPLICIT_FUNCTION_POINTER)
GMQCC_DEFINE_FLAG(VARIADIC_FUNCTION)
GMQCC_DEFINE_FLAG(FRAME_MACROS)
GMQCC_DEFINE_FLAG(EFFECTLESS_STATEMENT)
GMQCC_DEFINE_FLAG(END_SYS_FIELDS)
GMQCC_DEFINE_FLAG(ASSIGN_FUNCTION_TYPES)
GMQCC_DEFINE_FLAG(CPP)
GMQCC_DEFINE_FLAG(MULTIFILE_IF)
GMQCC_DEFINE_FLAG(DOUBLE_DECLARATION)
GMQCC_DEFINE_FLAG(CONST_VAR)
GMQCC_DEFINE_FLAG(MULTIBYTE_CHARACTER)
GMQCC_DEFINE_FLAG(TERNARY_PRECEDENCE)
GMQCC_DEFINE_FLAG(UNKNOWN_PRAGMAS)
GMQCC_DEFINE_FLAG(UNREACHABLE_CODE)
GMQCC_DEFINE_FLAG(UNKNOWN_ATTRIBUTE)
GMQCC_DEFINE_FLAG(RESERVED_NAMES)
GMQCC_DEFINE_FLAG(UNINITIALIZED_CONSTANT)
GMQCC_DEFINE_FLAG(DIFFERENT_QUALIFIERS)
GMQCC_DEFINE_FLAG(DIFFERENT_ATTRIBUTES)
GMQCC_DEFINE_FLAG(DEPRECATED)
GMQCC_DEFINE_FLAG(PARENTHESIS)
GMQCC_DEFINE_FLAG(UNSAFE_TYPES)
GMQCC_DEFINE_FLAG(BREAKDEF)
GMQCC_DEFINE_FLAG(CONST_OVERWRITE)
GMQCC_DEFINE_FLAG(DIRECTIVE_INMACRO)
GMQCC_DEFINE_FLAG(BUILTINS)
GMQCC_DEFINE_FLAG(INEXACT_COMPARES)
#endif
#ifdef GMQCC_TYPE_OPTIMIZATIONS
GMQCC_DEFINE_FLAG(PEEPHOLE, 1)
GMQCC_DEFINE_FLAG(TAIL_RECURSION, 1)
GMQCC_DEFINE_FLAG(OVERLAP_LOCALS, 3)
GMQCC_DEFINE_FLAG(LOCAL_TEMPS, 3)
GMQCC_DEFINE_FLAG(GLOBAL_TEMPS, 3)
GMQCC_DEFINE_FLAG(STRIP_CONSTANT_NAMES, 1)
GMQCC_DEFINE_FLAG(OVERLAP_STRINGS, 2)
GMQCC_DEFINE_FLAG(CALL_STORES, 3)
GMQCC_DEFINE_FLAG(VOID_RETURN, 1)
GMQCC_DEFINE_FLAG(VECTOR_COMPONENTS, 1)
GMQCC_DEFINE_FLAG(CONST_FOLD_DCE, 2)
GMQCC_DEFINE_FLAG(CONST_FOLD, 0) /* cannot be turned off */
#endif
#ifdef GMQCC_TYPE_OPTIONS
GMQCC_DEFINE_FLAG(O)
GMQCC_DEFINE_FLAG(OUTPUT)
GMQCC_DEFINE_FLAG(QUIET)
GMQCC_DEFINE_FLAG(G)
GMQCC_DEFINE_FLAG(STANDARD)
GMQCC_DEFINE_FLAG(DEBUG)
GMQCC_DEFINE_FLAG(DUMPFIN)
GMQCC_DEFINE_FLAG(DUMP)
GMQCC_DEFINE_FLAG(FORCECRC)
GMQCC_DEFINE_FLAG(FORCED_CRC)
GMQCC_DEFINE_FLAG(PP_ONLY)
GMQCC_DEFINE_FLAG(MAX_ARRAY_SIZE)
GMQCC_DEFINE_FLAG(ADD_INFO)
GMQCC_DEFINE_FLAG(PROGSRC)
GMQCC_DEFINE_FLAG(COVERAGE)
GMQCC_DEFINE_FLAG(STATE_FPS)
#endif
/* some cleanup so we don't have to */
#undef GMQCC_TYPE_FLAGS
#undef GMQCC_TYPE_WARNS
#undef GMQCC_TYPE_OPTIONS
#undef GMQCC_TYPE_OPTIMIZATIONS
#undef GMQCC_DEFINE_FLAG

3130
parser.c

File diff suppressed because it is too large Load diff

6416
parser.cpp Normal file

File diff suppressed because it is too large Load diff

84
parser.h Normal file
View file

@ -0,0 +1,84 @@
#ifndef GMQCC_PARSER_HDR
#define GMQCC_PARSER_HDR
#include "gmqcc.h"
#include "lexer.h"
#include "ast.h"
#include "intrin.h"
#include "fold.h"
struct parser_t;
#define parser_ctx(p) ((p)->lex->tok.ctx)
struct parser_t {
parser_t();
~parser_t();
void remove_ast();
lex_file *lex;
int tok;
bool ast_cleaned;
std::vector<ast_expression *> globals;
std::vector<ast_expression *> fields;
std::vector<ast_function *> functions;
size_t translated;
/* must be deleted first, they reference immediates and values */
std::vector<ast_value *> accessors;
ast_value *nil;
ast_value *reserved_version;
size_t crc_globals;
size_t crc_fields;
ast_function *function;
ht aliases;
/* All the labels the function defined...
* Should they be in ast_function instead?
*/
std::vector<ast_label*> labels;
std::vector<ast_goto*> gotos;
std::vector<const char *> breaks;
std::vector<const char *> continues;
/* A list of hashtables for each scope */
std::vector<ht> variables;
ht htfields;
ht htglobals;
std::vector<ht> typedefs;
/* not to be used directly, we use the hash table */
std::vector<ast_expression*> _locals;
std::vector<size_t> _blocklocals;
std::vector<std::unique_ptr<ast_value>> _typedefs;
std::vector<size_t> _blocktypedefs;
std::vector<lex_ctx_t> _block_ctx;
/* we store the '=' operator info */
const oper_info *assign_op;
/* magic values */
ast_value *const_vec[3];
/* pragma flags */
bool noref;
/* collected information */
size_t max_param_count;
fold m_fold;
intrin m_intrin;
};
/* parser.c */
char *parser_strdup (const char *str);
ast_expression *parser_find_global(parser_t *parser, const char *name);
#endif

View file

@ -1,35 +0,0 @@
This is a propsal to extend the progs.dat file format without breaking
backwards compatability. Currently the progs file format header has a
description simaler to this:
struct {
uint32_t version;
uint32_t crc16;
....
uint32_t entfield;
}
The obvious notable issue here is version and crc16 are larger than they
essentially need to be, if we made version and crc16 both uint16_t we can
give ourselfs 32 bytes (2x16) to store additional data that can be used
to make smaller progs.dat files.
I propose a new structual layout like this:
struct {
uint16_t version;
uint16_t flags; /* contains a skip field */
uint16_t crc16;
uint16_t skip; /* skiped globals */
....
uint32_t entfield;
}
about 45% of globals are zero, if we could order them at the top of the
globals array we can essentially use the skip field to specify how much
zero globals the engine would have to populate (instead of being stored
in the actual file itself) flags can specify if the progs.dat file skiped
globals on the write of the progs.dat file.
Of course only one bit in the flags would have to be set to specify if the
file contains a skip field. Which lends itself to the fact that flags could
later be extended for other things.

250
stat.cpp Normal file
View file

@ -0,0 +1,250 @@
#include <string.h>
#include <stdlib.h>
#include "gmqcc.h"
/*
* strdup does it's own malloc, we need to track malloc. We don't want
* to overwrite malloc though, infact, we can't really hook it at all
* without library specific assumptions. So we re implement strdup.
*/
char *stat_mem_strdup(const char *src, bool empty) {
size_t len = 0;
char *ptr = nullptr;
if (!src)
return nullptr;
len = strlen(src);
if ((!empty ? len : true) && (ptr = (char*)mem_a(len + 1))) {
memcpy(ptr, src, len);
ptr[len] = '\0';
}
return ptr;
}
/*
* The reallocate function for resizing vectors.
*/
void _util_vec_grow(void **a, size_t i, size_t s) {
vector_t *d = nullptr;
size_t m = 0;
void *p = nullptr;
if (*a) {
d = vec_meta(*a);
m = 2 * d->allocated + i;
p = mem_r(d, s * m + sizeof(vector_t));
} else {
m = i + 1;
p = mem_a(s * m + sizeof(vector_t));
((vector_t*)p)->used = 0;
}
d = (vector_t*)p;
d->allocated = m;
*a = d + 1;
}
void _util_vec_delete(void *data) {
mem_d(vec_meta(data));
}
/*
* Hash table for generic data, based on dynamic memory allocations
* all around. This is the internal interface, please look for
* EXPOSED INTERFACE comment below
*/
struct hash_node_t {
char *key; /* the key for this node in table */
void *value; /* pointer to the data as void* */
hash_node_t *next; /* next node (linked list) */
};
size_t hash(const char *key);
size_t util_hthash(hash_table_t *ht, const char *key) {
return hash(key) % ht->size;
}
static hash_node_t *_util_htnewpair(const char *key, void *value) {
hash_node_t *node;
if (!(node = (hash_node_t*)mem_a(sizeof(hash_node_t))))
return nullptr;
if (!(node->key = util_strdupe(key))) {
mem_d(node);
return nullptr;
}
node->value = value;
node->next = nullptr;
return node;
}
/*
* EXPOSED INTERFACE for the hashtable implementation
* util_htnew(size) -- to make a new hashtable
* util_htset(table, key, value, sizeof(value)) -- to set something in the table
* util_htget(table, key) -- to get something from the table
* util_htdel(table) -- to delete the table
*/
hash_table_t *util_htnew(size_t size) {
hash_table_t *hashtable = nullptr;
if (size < 1)
return nullptr;
if (!(hashtable = (hash_table_t*)mem_a(sizeof(hash_table_t))))
return nullptr;
if (!(hashtable->table = (hash_node_t**)mem_a(sizeof(hash_node_t*) * size))) {
mem_d(hashtable);
return nullptr;
}
hashtable->size = size;
memset(hashtable->table, 0, sizeof(hash_node_t*) * size);
return hashtable;
}
void util_htseth(hash_table_t *ht, const char *key, size_t bin, void *value) {
hash_node_t *newnode = nullptr;
hash_node_t *next = nullptr;
hash_node_t *last = nullptr;
next = ht->table[bin];
while (next && next->key && strcmp(key, next->key) > 0)
last = next, next = next->next;
/* already in table, do a replace */
if (next && next->key && strcmp(key, next->key) == 0) {
next->value = value;
} else {
/* not found, grow a pair man :P */
newnode = _util_htnewpair(key, value);
if (next == ht->table[bin]) {
newnode->next = next;
ht->table[bin] = newnode;
} else if (!next) {
last->next = newnode;
} else {
newnode->next = next;
last->next = newnode;
}
}
}
void util_htset(hash_table_t *ht, const char *key, void *value) {
util_htseth(ht, key, util_hthash(ht, key), value);
}
void *util_htgeth(hash_table_t *ht, const char *key, size_t bin) {
hash_node_t *pair = ht->table[bin];
while (pair && pair->key && strcmp(key, pair->key) > 0)
pair = pair->next;
if (!pair || !pair->key || strcmp(key, pair->key) != 0)
return nullptr;
return pair->value;
}
void *util_htget(hash_table_t *ht, const char *key) {
return util_htgeth(ht, key, util_hthash(ht, key));
}
void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin);
void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin) {
hash_node_t *pair;
size_t len, keylen;
int cmp;
keylen = strlen(key);
pair = ht->table[bin];
while (pair && pair->key) {
len = strlen(pair->key);
if (len < keylen) {
pair = pair->next;
continue;
}
if (keylen == len) {
cmp = strcmp(key, pair->key);
if (cmp == 0)
return pair->value;
if (cmp < 0)
return nullptr;
pair = pair->next;
continue;
}
cmp = strcmp(key, pair->key + len - keylen);
if (cmp == 0) {
uintptr_t up = (uintptr_t)pair->value;
up += len - keylen;
return (void*)up;
}
pair = pair->next;
}
return nullptr;
}
/*
* Free all allocated data in a hashtable, this is quite the amount
* of work.
*/
void util_htrem(hash_table_t *ht, void (*callback)(void *data)) {
size_t i = 0;
for (; i < ht->size; ++i) {
hash_node_t *n = ht->table[i];
hash_node_t *p;
/* free in list */
while (n) {
if (n->key)
mem_d(n->key);
if (callback)
callback(n->value);
p = n;
n = p->next;
mem_d(p);
}
}
/* free table */
mem_d(ht->table);
mem_d(ht);
}
void util_htrmh(hash_table_t *ht, const char *key, size_t bin, void (*cb)(void*)) {
hash_node_t **pair = &ht->table[bin];
hash_node_t *tmp;
while (*pair && (*pair)->key && strcmp(key, (*pair)->key) > 0)
pair = &(*pair)->next;
tmp = *pair;
if (!tmp || !tmp->key || strcmp(key, tmp->key) != 0)
return;
if (cb)
(*cb)(tmp->value);
*pair = tmp->next;
mem_d(tmp->key);
mem_d(tmp);
}
void util_htrm(hash_table_t *ht, const char *key, void (*cb)(void*)) {
util_htrmh(ht, key, util_hthash(ht, key), cb);
}
void util_htdel(hash_table_t *ht) {
util_htrem(ht, nullptr);
}

1305
test.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,163 +0,0 @@
#ifndef TEST_AST_MACROS_HDR
#define TEST_AST_MACROS_HDR
#define TESTVARS() \
ast_block *curblock; \
lex_ctx ctx
#define TESTINIT() \
ctx.file = NULL; \
ctx.line = 1;
#define DEFVAR(name) \
ast_value *name
#define VAR(type, name) \
name = ast_value_new(ctx, #name, type)
#define VARnamed(type, name, varname) \
name = ast_value_new(ctx, #varname, type)
#define MKGLOBAL(name) \
assert(globals_add(name) >= 0)
#define FIELD(type, name) \
name = ast_value_new(ctx, #name, TYPE_FIELD); \
do { \
ast_value *field_##name = ast_value_new(ctx, #name, type); \
name->expression.next = (ast_expression*)field_##name; \
MKFIELD(name); \
} while (0)
#define MKFIELD(name) \
assert(fields_add(name) >= 0)
#define MKCONSTFLOAT(name, value) \
do { \
name->isconst = true; \
name->constval.vfloat = value; \
MKGLOBAL(name); \
} while(0)
#define MKCONSTSTRING(name, value) \
do { \
name->isconst = true; \
name->constval.vstring = util_strdup(value); \
MKGLOBAL(name); \
} while(0)
#define MKCONSTVECTOR(name, valx, valy, valz) \
do { \
name->isconst = true; \
name->constval.vvec.x = (valx); \
name->constval.vvec.y = (valy); \
name->constval.vvec.z = (valz); \
MKGLOBAL(name); \
} while(0)
#define STATE(a) \
do { \
ast_expression *exp = (ast_expression*)(a); \
assert(ast_block_exprs_add(curblock, exp)); \
} while(0)
#define ASSIGN(op, a, b) \
(ast_expression*)ast_store_new(ctx, INSTR_##op, (ast_expression*)(a), (ast_expression*)(b))
#define BIN(op, a, b) \
(ast_expression*)ast_binary_new(ctx, INSTR_##op, (ast_expression*)(a), (ast_expression*)(b))
#define ENTFIELD(a, b) \
(ast_expression*)ast_entfield_new(ctx, (ast_expression*)(a), (ast_expression*)(b))
#define VECMEM(vec, mem) \
(ast_expression*)ast_member_new(ctx, (ast_expression*)(vec), (mem))
#define CALL(what) \
do { \
ast_call *call = ast_call_new(ctx, (ast_expression*)what); \
#define CALLPARAM(x) \
assert(ast_call_params_add(call, (ast_expression*)x));
#define ENDCALL() \
STATE(call); \
} while(0)
#define ENDCALLWITH(as, where) \
{ \
ast_expression *as = (ast_expression*)call; \
where; \
} \
} while(0)
#define WHILE(cond) \
do { \
ast_expression *wh_cond = (ast_expression*)(cond); \
ast_block *wh_body = ast_block_new(ctx); \
ast_block *oldcur = curblock; \
ast_loop *loop; \
curblock = wh_body;
#define ENDWHILE() \
curblock = oldcur; \
loop = ast_loop_new(ctx, NULL, (ast_expression*)wh_cond, \
NULL, NULL, (ast_expression*)wh_body); \
assert(loop); \
STATE(loop); \
} while(0)
#define BUILTIN(name, outtype, number) \
do { \
ast_function *func_##name; \
ast_value *thisfuncval; \
ast_function *thisfunc; \
DEFVAR(return_##name); \
VARnamed(TYPE_FUNCTION, name, name); \
VARnamed(outtype, return_##name, "#returntype"); \
name->expression.next = (ast_expression*)return_##name; \
MKGLOBAL(name); \
func_##name = ast_function_new(ctx, #name, name); \
thisfunc = func_##name; \
(void)thisfunc; \
thisfuncval = name; \
(void)thisfuncval; \
assert(functions_add(func_##name) >= 0); \
func_##name->builtin = number;
#define ENDBUILTIN() } while(0)
#define PARAM(ptype, name) \
do { \
DEFVAR(parm); \
VARnamed(ptype, parm, name); \
assert(ast_value_params_add(thisfuncval, parm)); \
} while(0)
#define FUNCTION(name, outtype) \
do { \
ast_function *thisfunc; \
ast_function *func_##name; \
ast_block *my_funcblock; \
DEFVAR(var_##name); \
DEFVAR(return_##name); \
VARnamed(TYPE_FUNCTION, var_##name, name); \
VARnamed(outtype, return_##name, "#returntype"); \
var_##name->expression.next = (ast_expression*)return_##name; \
MKGLOBAL(var_##name); \
func_##name = ast_function_new(ctx, #name, var_##name); \
thisfunc = func_##name; \
(void)thisfunc; \
assert(functions_add(func_##name) >= 0); \
my_funcblock = ast_block_new(ctx); \
assert(my_funcblock); \
assert(ast_function_blocks_add(func_##name, my_funcblock)); \
curblock = my_funcblock;
#define MKLOCAL(var) \
assert(ast_block_locals_add(curblock, var))
#define ENDFUNCTION(name) \
} while(0)
#endif

View file

@ -1,201 +0,0 @@
#include "gmqcc.h"
#include "ast.h"
/* NOTE: it's a test - I'll abort() on epic-failure */
#ifdef assert
# undef assert
#endif
/* (note: 'do {} while(0)' forces the need for a semicolon after assert() */
#define assert(x) do { if ( !(x) ) { printf("Assertion failed: %s\n", #x); abort(); } } while(0)
VECTOR_MAKE(ast_value*, globals);
VECTOR_MAKE(ast_value*, fields);
VECTOR_MAKE(ast_function*, functions);
uint32_t opts_flags[1 + (COUNT_FLAGS / 32)];
uint32_t opts_warn [1 + (COUNT_WARNINGS / 32)];
uint32_t opts_O = 1;
const char *opts_output = "progs.dat";
int opts_standard = COMPILER_GMQCC;
bool opts_debug = false;
bool opts_memchk = false;
bool opts_werror = false;
#include "ast-macros.h"
int main()
{
size_t i;
ir_builder *ir;
TESTVARS();
DEFVAR(vi);
DEFVAR(vx);
DEFVAR(f0);
DEFVAR(f1);
DEFVAR(f5);
DEFVAR(cv3x4x5);
DEFVAR(cv1x1x1);
DEFVAR(sHello);
DEFVAR(sNL);
DEFVAR(print);
DEFVAR(ftos);
DEFVAR(spawn);
DEFVAR(mema);
DEFVAR(memb);
DEFVAR(memv);
DEFVAR(pawn);
/* opts_debug = true; */
BUILTIN(print, TYPE_VOID, -1);
PARAM(TYPE_STRING, text);
ENDBUILTIN();
BUILTIN(ftos, TYPE_STRING, -2);
PARAM(TYPE_FLOAT, value);
ENDBUILTIN();
BUILTIN(spawn, TYPE_ENTITY, -3);
ENDBUILTIN();
TESTINIT();
VAR(TYPE_FLOAT, f0);
VAR(TYPE_FLOAT, f1);
VAR(TYPE_FLOAT, f5);
VAR(TYPE_STRING, sHello);
VAR(TYPE_STRING, sNL);
VAR(TYPE_VECTOR, cv3x4x5);
VAR(TYPE_VECTOR, cv1x1x1);
FIELD(TYPE_FLOAT, mema);
FIELD(TYPE_FLOAT, memb);
FIELD(TYPE_VECTOR, memv);
MKCONSTFLOAT(f0, 0.0);
MKCONSTFLOAT(f1, 1.0);
MKCONSTFLOAT(f5, 5.0);
MKCONSTSTRING(sHello, "Hello, World\n");
MKCONSTSTRING(sNL, "\n");
MKCONSTVECTOR(cv3x4x5, 3, 4, 5);
MKCONSTVECTOR(cv1x1x1, 1, 1, 1);
FUNCTION(foo, TYPE_VOID);
ENDFUNCTION(foo);
#define PRINTNL() do { CALL(print) CALLPARAM(sNL) ENDCALL(); } while(0)
FUNCTION(main, TYPE_VOID);
VAR(TYPE_FLOAT, vi);
VAR(TYPE_FLOAT, vx);
VAR(TYPE_ENTITY, pawn);
MKLOCAL(vi);
MKLOCAL(vx);
MKLOCAL(pawn);
STATE(ASSIGN(STORE_F, vi, f0));
WHILE(BIN(LT, vi, f5));
STATE(ASSIGN(STORE_F, vx, BIN(MUL_F, vi, f5)));
STATE(ASSIGN(STORE_F, vi, BIN(ADD_F, vi, f1)));
ENDWHILE();
CALL(print)
CALLPARAM(sHello)
ENDCALL();
CALL(spawn)
ENDCALLWITH(newent, STATE(ASSIGN(STORE_ENT, pawn, newent)));
STATE(ASSIGN(STOREP_F, ENTFIELD(pawn, mema), f5));
STATE(ASSIGN(STOREP_F, ENTFIELD(pawn, memb), f1));
STATE(ASSIGN(STOREP_V, ENTFIELD(pawn, memv), cv3x4x5));
CALL(ftos)
CALLPARAM(ENTFIELD(pawn, mema))
ENDCALLWITH(output,
CALL(print)
CALLPARAM(output)
CALLPARAM(sNL)
ENDCALL();
);
CALL(ftos)
CALLPARAM(ENTFIELD(pawn, memb))
ENDCALLWITH(output,
CALL(print)
CALLPARAM(output)
CALLPARAM(sNL)
ENDCALL();
);
CALL(ftos)
CALLPARAM(ENTFIELD(pawn, VECMEM(memv, 2)))
ENDCALLWITH(output,
CALL(print)
CALLPARAM(output)
CALLPARAM(sNL)
ENDCALL();
);
ENDFUNCTION(main);
ir = ir_builder_new("ast_test");
assert(ir);
/* gen fields */
for (i = 0; i < fields_elements; ++i) {
if (!ast_global_codegen(fields_data[i], ir)) {
assert(!"failed to generate field");
}
}
/* gen globals */
for (i = 0; i < globals_elements; ++i) {
if (!ast_global_codegen(globals_data[i], ir)) {
assert(!"failed to generate global");
}
}
/* gen functions */
for (i = 0; i < functions_elements; ++i) {
if (!ast_function_codegen(functions_data[i], ir)) {
assert(!"failed to generate function");
}
if (!ir_function_finalize(functions_data[i]->ir_func))
assert(!"finalize on function failed...");
}
/* dump */
ir_builder_dump(ir, printf);
/* Now create a file */
if (!ir_builder_generate(ir, "test_ast.dat"))
printf("*** failed to generate code\n");
/* ir cleanup */
ir_builder_delete(ir);
/* cleanup */
/* Functions must be deleted FIRST since their expressions
* reference global variables.
*/
for (i = 0; i < functions_elements; ++i) {
ast_function_delete(functions_data[i]);
}
if (functions_data)
mem_d(functions_data);
/* We must delete not only globals, but also the functions'
* ast_values (their type and name), that's why we added them to the globals vector.
*/
for (i = 0; i < globals_elements; ++i) {
ast_value_delete(globals_data[i]);
}
if (globals_data)
mem_d(globals_data);
return 0;
}

View file

@ -1,150 +0,0 @@
#include "gmqcc.h"
#include "ir.h"
#ifdef assert
# undef assert
#endif
/* (note: 'do {} while(0)' forces the need for a semicolon after assert() */
#define assert(x) do { if ( !(x) ) { printf("Assertion failed: %s\n", #x); abort(); } } while(0)
int main()
{
int lf;
ir_builder *b = ir_builder_new("test");
ir_value *va = ir_builder_create_global(b, "a", TYPE_FLOAT);
ir_value *v3 = ir_builder_create_global(b, "const_f_3", TYPE_FLOAT);
ir_value *vb = ir_builder_create_global(b, "b", TYPE_FLOAT);
ir_value *vc = ir_builder_create_global(b, "c", TYPE_FLOAT);
ir_value *vd = ir_builder_create_global(b, "d", TYPE_FLOAT);
ir_value *life1 = ir_builder_create_global(b, "life1", TYPE_FLOAT);
ir_value *life2 = ir_builder_create_global(b, "life2", TYPE_FLOAT);
ir_value *life3 = ir_builder_create_global(b, "life3", TYPE_FLOAT);
ir_function *fmain = NULL;
ir_value *la = NULL;
ir_block *bmain = NULL;
ir_block *blt = NULL;
ir_block *bge = NULL;
ir_block *bend = NULL;
ir_value *sum = NULL;
ir_value *prd = NULL;
ir_value *less = NULL;
ir_value *x1 = NULL;
ir_value *vig = NULL;
ir_value *x2 = NULL;
ir_instr *retphi = NULL;
ir_value *retval = NULL;
assert(ir_value_set_float(v3, 3.0f) );
assert(ir_value_set_float(vb, 4.0f) );
assert(ir_value_set_float(vc, 10.0f) );
assert(ir_value_set_float(vd, 20.0f) );
fmain = ir_builder_create_function(b, "main");
assert(fmain);
la = ir_function_create_local(fmain, "loc1", TYPE_FLOAT);
assert(la);
assert( bmain = ir_function_create_block(fmain, "top") );
assert( blt = ir_function_create_block(fmain, "less") );
assert( bge = ir_function_create_block(fmain, "greaterequal") );
assert( bend = ir_function_create_block(fmain, "end") );
assert(ir_block_create_store_op(bmain, INSTR_STORE_F, va, v3));
assert( sum = ir_block_create_add(bmain, "%sum", va, vb) );
assert( prd = ir_block_create_mul(bmain, "%mul", sum, vc) );
assert( less = ir_block_create_binop(bmain, "%less", INSTR_LT, prd, vd) );
assert(ir_block_create_if(bmain, less, blt, bge));
x1 = ir_block_create_binop(blt, "%x1", INSTR_ADD_F, sum, v3);
assert(x1);
assert(ir_block_create_goto(blt, bend));
vig = ir_block_create_binop(bge, "%ignore", INSTR_ADD_F, va, vb);
assert(vig);
assert(ir_block_create_store_op(bge, INSTR_STORE_F, la, vig));
x2 = ir_block_create_binop(bge, "%x2", INSTR_ADD_F, sum, v3);
assert(x2);
assert(ir_block_create_goto(bge, bend));
retphi = ir_block_create_phi(bend, "%retval", TYPE_FLOAT);
assert(retphi);
assert(ir_phi_add(retphi, blt, x1));
assert(ir_phi_add(retphi, bge, x2));
retval = ir_phi_value(retphi);
assert(retval);
assert(ir_block_create_return(bend, retval));
/*
printf("%i should be 1\n", ir_value_life_merge(va, 31));
printf("%i should be 1\n", ir_value_life_merge(va, 33));
printf("%i should be 0\n", ir_value_life_merge(va, 33));
printf("%i should be 1\n", ir_value_life_merge(va, 1));
printf("%i should be 1\n", ir_value_life_merge(va, 2));
printf("%i should be 1\n", ir_value_life_merge(va, 20));
printf("%i should be 1\n", ir_value_life_merge(va, 21));
printf("%i should be 1\n", ir_value_life_merge(va, 8));
printf("%i should be 1\n", ir_value_life_merge(va, 9));
printf("%i should be 1\n", ir_value_life_merge(va, 3));
printf("%i should be 0\n", ir_value_life_merge(va, 9));
printf("%i should be 1\n", ir_value_life_merge(va, 17));
printf("%i should be 1\n", ir_value_life_merge(va, 18));
printf("%i should be 1\n", ir_value_life_merge(va, 19));
printf("%i should be 0\n", ir_value_life_merge(va, 19));
ir_value_dump_life(va, printf);
printf("%i should be 1\n", ir_value_life_merge(va, 10));
printf("%i should be 1\n", ir_value_life_merge(va, 9));
printf("%i should be 0\n", ir_value_life_merge(va, 10));
printf("%i should be 0\n", ir_value_life_merge(va, 10));
ir_value_dump_life(va, printf);
*/
ir_builder_dump(b, printf);
assert(ir_function_finalize(fmain));
ir_builder_dump(b, printf);
ir_value_dump_life(sum, printf);
ir_value_dump_life(prd, printf);
ir_value_dump_life(less, printf);
ir_value_dump_life(x1, printf);
ir_value_dump_life(x2, printf);
ir_value_dump_life(retval, printf);
ir_value_dump_life(vig, printf);
ir_value_dump_life(la, printf);
ir_value_life_merge_into(retval, vig);
ir_value_dump_life(retval, printf);
ir_value_life_merge(x1, 12);
ir_value_life_merge(x1, 13);
ir_value_life_merge(x1, 14);
ir_value_life_merge_into(retval, x1);
ir_value_dump_life(retval, printf);
ir_value_life_merge(x1, 20);
ir_value_life_merge(x1, 21);
ir_value_life_merge(x1, 22);
ir_value_life_merge_into(retval, x1);
ir_value_dump_life(retval, printf);
ir_value_life_merge(x2, 1);
ir_value_life_merge(x2, 2);
ir_value_life_merge_into(retval, x2);
ir_value_dump_life(retval, printf);
for (lf = 4; lf <= 15; ++lf)
ir_value_life_merge(life1, lf);
ir_value_life_merge_into(retval, life1);
ir_value_dump_life(retval, printf);
for (lf = 17; lf <= 18; ++lf)
ir_value_life_merge(life2, lf);
ir_value_life_merge_into(retval, life2);
ir_value_dump_life(retval, printf);
for (lf = 2; lf <= 29; ++lf)
ir_value_life_merge(life3, lf);
ir_value_life_merge_into(retval, life3);
ir_value_dump_life(retval, printf);
ir_builder_delete(b);
return 0;
}

18
tests/accumulate.qc Normal file
View file

@ -0,0 +1,18 @@
#define ACCUMULATE_FUNCTION(FUNC) \
[[accumulate]] void FUNC ()
ACCUMULATE_FUNCTION(foo) {
print("hello ");
}
ACCUMULATE_FUNCTION(foo) {
print("accumulation ");
}
ACCUMULATE_FUNCTION(foo) {
print("world\n");
}
void main() {
foo();
}

5
tests/accumulate.tmpl Normal file
View file

@ -0,0 +1,5 @@
I: accumulate.qc
D: test function accumulation
T: -execute
C: -std=gmqcc -fftepp
M: hello accumulation world

34
tests/aliases.qc Normal file
View file

@ -0,0 +1,34 @@
float alias_1 = 3.14;
void alias_2() {
print("alias_2\n");
}
[[alias("alias_2")]] void alias_2_aliased();
[[alias("alias_1")]] float alias_1_aliased;
// alias to an alias?
vector alias_3;
[[alias("alias_3")]] vector alias_3_aliased;
// expected output
// alias_2
// 3.14
void main() {
alias_2_aliased();
alias_3_aliased= '1 2 3';
print(
ftos(
alias_1_aliased
),
"\n"
);
print(
"x ", ftos(alias_3_aliased_x), "\n",
"y ", ftos(alias_3_aliased_y), "\n",
"z ", ftos(alias_3_aliased_z), "\n"
);
}

9
tests/aliases.tmpl Normal file
View file

@ -0,0 +1,9 @@
I: aliases.qc
D: test aliases
T: -execute
C: -std=gmqcc
M: alias_2
M: 3.14
M: x 1
M: y 2
M: z 3

13
tests/arithexcept.qc Normal file
View file

@ -0,0 +1,13 @@
const float huge = 340282346638528859811704183484516925440.000000; // FLT_MAX
#ifdef DIVBYZERO
const float a = 1.0 / 0.0;
#endif
#ifdef OVERFLOW
const float a = huge * huge;
#endif
#ifdef UNDERFLOW
const float a = 1 / huge;
#endif

4
tests/arithexcept.tmpl Normal file
View file

@ -0,0 +1,4 @@
I: arithexcept.qc
D: arithmetic exceptions (divide by zero)
T: -fail
C: -std=fteqcc -farithmetic-exceptions -DDIVBYZERO

View file

@ -0,0 +1,4 @@
I: arithexcept.qc
D: arithmetic exceptions (overflow)
T: -fail
C: -std=fteqcc -farithmetic-exceptions -DOVERFLOW

View file

@ -0,0 +1,4 @@
I: arithexcept.qc
D: arithmetic exceptions (underflow)
T: -fail
C: -std=fteqcc -farithmetic-exceptions -DUNDERFLOW

52
tests/arrays.qc Normal file
View file

@ -0,0 +1,52 @@
float glob[7];
.float above;
.float flds[6];
.float below;
void main() {
float loc[6];
loc[0] = 1000;
loc[1] = 1100;
loc[2] = 1200;
loc[3] = 1300;
loc[4] = 1400;
loc[5] = 1500;
float i;
for (i = 0; i < 6; i += 1)
loc[i] += 1;
for (i = 0; i < 5; i += 1)
print(ftos(loc[i]), " ");
print(ftos(loc[i]), "\n");
glob[0] = 1000;
glob[1] = 1100;
glob[2] = 1200;
glob[3] = 1300;
glob[4] = 1400;
glob[5] = 1500;
glob[6] = 1600;
for (i = 0; i < 7; i += 1)
glob[i] += 1;
for (i = 0; i < 6; i += 1)
print(ftos(glob[i]), " ");
print(ftos(glob[i]), "\n");
entity e = spawn();
e.above = 7777;
e.below = 9999;
e.flds[0] = 1000;
e.flds[1] = 1100;
e.flds[2] = 1200;
e.flds[3] = 1300;
e.flds[4] = 1400;
e.flds[5] = 1500;
for (i = 0; i < 6; i += 1)
e.flds[i] += 1;
for (i = 0; i < 5; i += 1)
print(ftos(e.flds[i]), " ");
print(ftos(e.flds[i]), "\n");
}

7
tests/arrays.tmpl Normal file
View file

@ -0,0 +1,7 @@
I: arrays2.qc
D: initialized arrays
T: -execute
C: -std=fteqcc
M: 10 20 30 40 50 60 70
M: 100 200 300 400 500 600 0
M: Hello World

18
tests/arrays2.qc Normal file
View file

@ -0,0 +1,18 @@
float glob1[7] = { 10, 20, 30, 40, 50, 60, 70 };
float glob2[7] = { 100, 200, 300, 400, 500, 600 };
string globs[] = { "Hello ", "World" };
void main() {
float i;
print(ftos(glob1[0]));
for (i = 1; i != 7; ++i)
print(" ", ftos(glob1[i]));
print("\n");
print(ftos(glob2[0]));
for (i = 1; i != 7; ++i)
print(" ", ftos(glob2[i]));
print("\n");
print(globs[0], globs[1], "\n");
}

7
tests/arrays2.tmpl Normal file
View file

@ -0,0 +1,7 @@
I: arrays.qc
D: array accessors and functionality
T: -execute
C: -std=fteqcc
M: 1001 1101 1201 1301 1401 1501
M: 1001 1101 1201 1301 1401 1501 1601
M: 1001 1101 1201 1301 1401 1501

37
tests/bitnot.qc Normal file
View file

@ -0,0 +1,37 @@
void main() {
float a; a = 1;
float b; b = 1;
float c; c = 1;
float d; d = 1;
vector e; e = '1 1 1';
vector f; f = '1 1 1';
#ifdef __STD_FTEQCC__
a &~= 1; // 0
#else
a &= ~1; // 0
#endif
#ifdef __STD_GMQCC__
b &= ~1; // 0
c &= ~d; // 0
#else
b &~= 1; // 0
c &~= 1; // 0
#endif
#ifdef __STD_FTEQCC__
f &~= e; // '0 0 0'
#else
f &= ~e; // '0 0 0'
#endif
#ifdef __STD_GMQCC__
e &= ~e; // '0 0 0'
#else
e &~= e; // '0 0 0'
#endif
print("a: ", ftos(a), "\nb: ",
ftos(b), "\nc: ",
ftos(c), "\n");
print("e: ", vtos(e), "\n");
print("f: ", vtos(f), "\n");
}

11
tests/bitnot.tmpl Normal file
View file

@ -0,0 +1,11 @@
# used to test the builtins
I: bitnot.qc
D: test bitwise not operators (fteqcc operators)
T: -execute
C: -std=fteqcc
E: $null
M: a: 0
M: b: 0
M: c: 0
M: e: '0 0 0'
M: f: '0 0 0'

11
tests/bitnotgmqcc.tmpl Normal file
View file

@ -0,0 +1,11 @@
# used to test the builtins
I: bitnot.qc
D: test bitwise not operators (gmqcc operators)
T: -execute
C: -std=gmqcc -fftepp
E: $null
M: a: 0
M: b: 0
M: c: 0
M: e: '0 0 0'
M: f: '0 0 0'

23
tests/break.qc Normal file
View file

@ -0,0 +1,23 @@
void test(float brkat, float contat) {
float i;
for (i = 0; i < 10; i += 1) {
if (i == contat) {
print("ct ");
continue;
}
print(ftos(i), " ");
if (i == brkat) {
print("brk ");
break;
}
}
print("end\n");
}
void main() {
test(-1, -1);
test( 3, -1);
test(-1, 3);
test( 5, 2);
}

8
tests/break.tmpl Normal file
View file

@ -0,0 +1,8 @@
I: break.qc
D: test break and continue
T: -execute
C: -std=fteqcc
M: 0 1 2 3 4 5 6 7 8 9 end
M: 0 1 2 3 brk end
M: 0 1 2 ct 4 5 6 7 8 9 end
M: 0 1 ct 3 4 5 brk end

3
tests/builtin.qc Normal file
View file

@ -0,0 +1,3 @@
void() main = {
print("hello world");
}

7
tests/builtin.tmpl Normal file
View file

@ -0,0 +1,7 @@
# used to test the builtins
I: builtin.qc
D: test builtin functions
T: -execute
C: -std=gmqcc
E: $null
M: hello world

View file

@ -1,6 +1,3 @@
void(string, ...) print = #1;
string(float) ftos = #2;
float(float x, float y, float z) sum = {
return x + y + z;
};
@ -11,4 +8,5 @@ void(float a, float b, float c) main = {
sum(sum(sum(a, b, c), b, sum(a, b, c)), b, sum(a, b, sum(a, b, c))),
sum(sum(a, b, c), b, c));
print(ftos(f), "\n");
};

6
tests/calls.tmpl Normal file
View file

@ -0,0 +1,6 @@
I: calls.qc
D: test calls
T: -execute
C: -std=gmqcc
E: -float 100 -float 200 -float 300
M: 4600

View file

@ -0,0 +1,12 @@
I: correct-logic.qc
D: vector logic flags
T: -execute
C: -std=fteqcc -fshort-logic
M: ! & | i N
M: 0, 0 -> 1 0 0 0 1
M: 0, x -> 1 0 1 0 1
M: x, 0 -> 0 0 1 1 0
M: x, x -> 0 1 1 1 0
M: 0, y -> 1 0 0 0 1
M: y, 0 -> 0 0 0 0 1
M: y, y -> 0 0 0 0 1

View file

@ -0,0 +1,12 @@
I: correct-logic.qc
D: vector logic flags
T: -execute
C: -std=fteqcc
M: ! & | i N
M: 0, 0 -> 1 0 0 0 1
M: 0, x -> 1 0 1 0 1
M: x, 0 -> 0 0 1 1 0
M: x, x -> 0 1 1 1 0
M: 0, y -> 1 0 0 0 1
M: y, 0 -> 0 0 0 0 1
M: y, y -> 0 0 0 0 1

View file

@ -0,0 +1,12 @@
I: correct-logic.qc
D: vector logic flags
T: -execute
C: -std=fteqcc -fcorrect-logic -fshort-logic
M: ! & | i N
M: 0, 0 -> 1 0 0 0 1
M: 0, x -> 1 0 1 0 1
M: x, 0 -> 0 0 1 1 0
M: x, x -> 0 1 1 1 0
M: 0, y -> 1 0 1 0 1
M: y, 0 -> 0 0 1 1 0
M: y, y -> 0 1 1 1 0

View file

@ -0,0 +1,12 @@
I: correct-logic.qc
D: vector logic flags
T: -execute
C: -std=fteqcc -fcorrect-logic
M: ! & | i N
M: 0, 0 -> 1 0 0 0 1
M: 0, x -> 1 0 1 0 1
M: x, 0 -> 0 0 1 1 0
M: x, x -> 0 1 1 1 0
M: 0, y -> 1 0 1 0 1
M: y, 0 -> 0 0 1 1 0
M: y, y -> 0 1 1 1 0

24
tests/correct-logic.qc Normal file
View file

@ -0,0 +1,24 @@
float test_s_not (vector s) { return !s; }
float test_s_and (vector s, vector t) { return s && t; }
float test_s_or (vector s, vector t) { return s || t; }
float test_s_if (vector s) { if (s) return 1; return 0; }
float test_s_ifnot(vector s) { if not (s) return 1; return 0; }
void test(vector s, vector t) {
print(ftos(!!test_s_not (s)), " ");
print(ftos(!!test_s_and (s, t)), " ");
print(ftos(!!test_s_or (s, t)), " ");
print(ftos(!!test_s_if (s)), " ");
print(ftos(!!test_s_ifnot(s)), "\n");
}
void main() {
print(" ! & | i N\n");
print("0, 0 -> "); test('0 0 0', '0 0 0');
print("0, x -> "); test('0 0 0', '1 0 0');
print("x, 0 -> "); test('1 0 0', '0 0 0');
print("x, x -> "); test('1 0 0', '1 0 0');
print("0, y -> "); test('0 0 0', '0 1 0');
print("y, 0 -> "); test('0 1 0', '0 0 0');
print("y, y -> "); test('0 1 0', '0 1 0');
}

View file

@ -0,0 +1,14 @@
I: correct-vs-short.qc
D: correct-logic vs short-logic without perl-logic
T: -execute
C: -std=fteqcc
M: X & | B
M: 0 0 0, 0 0 0 :: 0 0 0
M: 0 0 0, 5 0 0 :: 0 2 1
M: 5 0 0, 0 0 0 :: 0 2 1
M: 5 0 0, 5 0 0 :: 2 2 2
M: Y & | B
M: 0 0 0, 0 0 0 :: 0 0 0
M: 0 0 0, 0 5 0 :: 0 0 0
M: 0 5 0, 0 0 0 :: 0 0 0
M: 0 5 0, 0 5 0 :: 0 0 0

View file

@ -0,0 +1,14 @@
I: correct-vs-short.qc
D: correct-logic vs short-logic without perl-logic
T: -execute
C: -std=fteqcc -fcorrect-logic
M: X & | B
M: 0 0 0, 0 0 0 :: 0 0 0
M: 0 0 0, 5 0 0 :: 0 2 1
M: 5 0 0, 0 0 0 :: 0 2 1
M: 5 0 0, 5 0 0 :: 2 2 2
M: Y & | B
M: 0 0 0, 0 0 0 :: 0 0 0
M: 0 0 0, 0 5 0 :: 0 2 1
M: 0 5 0, 0 0 0 :: 0 2 1
M: 0 5 0, 0 5 0 :: 2 2 2

View file

@ -0,0 +1,14 @@
I: correct-vs-short.qc
D: correct-logic vs short-logic without perl-logic
T: -execute
C: -std=fteqcc -fcorrect-logic -fshort-logic
M: X & | B
M: 0 0 0, 0 0 0 :: 0 0 0
M: 0 0 0, 5 0 0 :: 0 2 1
M: 5 0 0, 0 0 0 :: 0 2 1
M: 5 0 0, 5 0 0 :: 2 2 2
M: Y & | B
M: 0 0 0, 0 0 0 :: 0 0 0
M: 0 0 0, 0 5 0 :: 0 2 1
M: 0 5 0, 0 0 0 :: 0 2 1
M: 0 5 0, 0 5 0 :: 2 2 2

18
tests/correct-vs-short.qc Normal file
View file

@ -0,0 +1,18 @@
void test(vector a, vector b) {
print(ftos((a && b) + (a && b)), " ");
print(ftos((a || b) + (a || b)), " ");
print(ftos((a && b) + (a || b)), "\n");
}
void main() {
print("X & | B\n");
print("0 0 0, 0 0 0 :: "); test('0 0 0', '0 0 0');
print("0 0 0, 5 0 0 :: "); test('0 0 0', '5 0 0');
print("5 0 0, 0 0 0 :: "); test('5 0 0', '0 0 0');
print("5 0 0, 5 0 0 :: "); test('5 0 0', '5 0 0');
print("Y & | B\n");
print("0 0 0, 0 0 0 :: "); test('0 0 0', '0 0 0');
print("0 0 0, 0 5 0 :: "); test('0 0 0', '0 5 0');
print("0 5 0, 0 0 0 :: "); test('0 5 0', '0 0 0');
print("0 5 0, 0 5 0 :: "); test('0 5 0', '0 5 0');
}

21
tests/defs.qh Normal file
View file

@ -0,0 +1,21 @@
// builtins for the standalone qcvm included with gmqcc
// in exec.c These should be updated to reflect the new
// builtins. I no event shall you even consider adding
// these individually per test.
void (string str, ...) print = #1;
string (float val) ftos = #2;
entity () spawn = #3;
void (entity ent) kill = #4;
string (vector vec) vtos = #5;
void (string str) error = #6;
float (vector vec) vlen = #7;
string (entity ent) etos = #8;
float (string str) stof = #9;
string (...) strcat = #10;
float (string str1, string str2) strcmp = #11;
vector (vector vec) normalize = #12;
float (float val) sqrt = #13;
float (float val) floor = #14;
float (float val1, float val2) pow = #15;
vector (string str) stov = #16;

27
tests/dots.qc Normal file
View file

@ -0,0 +1,27 @@
entity self;
.float f;
..float fp;
...float fpp;
void try(entity e, ...float pp) {
print("and: ", ftos( e.(e.(e.pp)) ), "\n");
}
typedef float Float;
void try2(entity e, ...Float pp) {
print("and: ", ftos( e.(e.(e.pp)) ), "\n");
}
// whereas the varargs are tested in vararg tests
void main() {
self = spawn();
self.f = 123;
self.fp = f;
self.fpp = fp;
print(ftos( self.(self.fp) ), "\n");
print(ftos( self.(self.(self.fpp)) ), "\n");
try(self, fpp);
try2(self, fpp);
}

8
tests/dots.tmpl Normal file
View file

@ -0,0 +1,8 @@
I: dots.qc
D: TOKEN_DOTS disambiguation
T: -execute
C: -std=fteqcc
M: 123
M: 123
M: and: 123
M: and: 123

68
tests/enum.qc Normal file
View file

@ -0,0 +1,68 @@
enum {
// this behaviour is confusing, but I like that
// we support it.
__ = (__ - 1),
A = (__ + 1),
B,
C
};
enum {
D = C + B,
E = C + C,
F = C + D,
};
enum {
G = (B + F), H = (C + F),
I = (D + F), J = (B + I)
};
enum {
K = A + B - C + D - E + F *
G - H + I - J + A - B -
J + A,
L,
M,
N
};
enum : flag {
F1, /* = 1 << 1 */
F2, /* = 1 << 2 */
F3 /* = 1 << 3 */
};
/* reversed enumeration */
enum : reverse {
R1, // 3
R2, // 2
R3, // 1
R4 // 0
};
void main() {
print(ftos(A), "\n");
print(ftos(B), "\n");
print(ftos(C), "\n");
print(ftos(D), "\n");
print(ftos(E), "\n");
print(ftos(F), "\n");
print(ftos(G), "\n");
print(ftos(H), "\n");
print(ftos(I), "\n");
print(ftos(J), "\n");
print(ftos(K), "\n");
print(ftos(L), "\n");
print(ftos(M), "\n");
print(ftos(N), "\n");
print(ftos(F1), "\n");
print(ftos(F2), "\n");
print(ftos(F3), "\n");
print(ftos(R1), "\n");
print(ftos(R2), "\n");
print(ftos(R3), "\n");
print(ftos(R4), "\n");
};

Some files were not shown because too many files have changed in this diff Show more