Commit graph

73 commits

Author SHA1 Message Date
Bill Currie
75be251d65 Create and use def_visit_all.
Even though it turned out there were only two copies of the def alias
handling code, I got tired of writing it. The code is easier to read, too
:)
2012-12-12 12:01:31 +09:00
Bill Currie
7607c7d649 Resurrect alias operands.
It turns out they are necessary for the code output from dags. This fixes
the ice for *to = *from++;
2012-12-11 15:52:37 +09:00
Bill Currie
50b0bd0b95 Use define from temp aliases as well to kill uninit defines.
Finally, the uninitialized temp warnings are fixed.
2012-12-11 13:04:06 +09:00
Bill Currie
5083679fcc Don't mask out the dummy defines from temp kills. 2012-12-11 12:58:16 +09:00
Bill Currie
28c37b367d Fix the dummy definitions of temp vars.
I forgot to add func->num_statements :P. Fixes the weirdness where only
some alias temps were being (bogusly) detected as uninitialized. Now they
all are.
2012-12-11 12:27:23 +09:00
Bill Currie
8582e9de63 Make it possible to dump statement blocks in a flow graph.
Much nicer looking with proper back edges :). Not actually enabled, though.
2012-12-11 11:31:55 +09:00
Bill Currie
3aa3a0945a Scan the statements in a node with suspect var usage.
When the naive uninitialized variable detection finds a node with possible
uses of uninitialized variables, the statements in the node are scanned one
at a time checking each usage and removing uninitialized definitions as
appropriate. vectest.r now compiles without warnings. As an added bonus,
accurate line number information is reported for uninitialized variables.

Unfortunately, there is still a problem with uninitialized temps in
switch.r, but that might just be poor handling of temp op aliases.
2012-12-10 20:49:08 +09:00
Bill Currie
426363cd0d Don't kill aliased definitions in the entry dummy block.
Only definitions for the def used in the current statement (whether an
alias or not) are suitable for killing. Doing otherwise defeats the purpose
of this work :P

Fixes the false negatives found in a modified quattest.r (commented out the
"tq.s = 0;" line).
2012-12-10 19:42:31 +09:00
Bill Currie
aa97979d98 Rewrite flow_uninitialized() to use reaching defs.
Nicely, the use sets from live_variable analysis can be used too, though
there are some problems with the naive implementation. For:

vector foo (float x, float y, float z)
{
	vector v;
	v.x = x;
	v.y = y;
	v.z = z;
	return v;
}

qfcc thinks v is uninitialized, but if "if (x) return nil;" (or any other
basic-block splitter) is put just before the return v; qfcc correctly
detects that v is initialized. The reason is that the inits are in the same
basic block as the return, and thus aren't affecting the reaching
definitions, which are stored per-block.

The naive implementation should be good for a fast-cull before doing a
per-statement check.
2012-12-10 15:58:51 +09:00
Bill Currie
c47cb697de Create dummy uses for global variables
The exit dummy block is setup to provide dummy uses of global variables to
the live variable analysis doesn't miss global variables. Much cleaner than
the previous code :) There may be some issues with aliases, though.
2012-12-10 15:27:07 +09:00
Bill Currie
2e105f17f2 Enable live var flow dumps. 2012-12-10 15:27:07 +09:00
Bill Currie
d2f2fdc28e Create dummy definitions for local variables.
The entry dummy block is setup to provide dummy definitions of local
variables so the reaching definitions analysis can be used to detect
uninitialized variables (not implemented yet). Fake statement numbers
(func->num_statements + X) are used to represent the definitions. Local
variables (ie, not temp ops) use their offsets (ie, the offset range they
cover) for X. Temp ops use their flowvar number + the size of the
function's defspace for X. flow_kill_aliases() should take care of temp op
aliasing, while the use of the actual offsets spanned by the variable's def
should take care of any wild aliasing so structures and unions should
become a non-issue.
2012-12-10 15:26:47 +09:00
Bill Currie
d717a0b3f2 Add dummy nodes at the beginning and end of the graph.
The dummy nodes are for detectining uninitialized variables (entry dummy)
and making globals live at function exit (exit dummy). The reaching defs
and live vars code currently seg because neither node has had its sets
initialized.
2012-12-10 13:56:26 +09:00
Bill Currie
f30741c875 Add fixed aliases to a statement's kill set.
Fixed aliases are those that will never change through the life of the
code. They are generated from structure accesses and thus what they alias
is always known.
2012-12-10 13:25:06 +09:00
Bill Currie
fa45ab842f Make the reaching defs dot dump optional. 2012-12-10 12:17:20 +09:00
Bill Currie
e4dd86c36b Calculate reaching defs. 2012-12-09 22:37:59 +09:00
Bill Currie
f3adb70ee4 Move the var def/use calculation into flow_build_vars(). 2012-12-09 21:22:57 +09:00
Bill Currie
2bc3a36126 Split out the statement array building. 2012-12-09 21:12:53 +09:00
Bill Currie
17a2f86a22 Correct some comments. 2012-12-09 21:12:33 +09:00
Bill Currie
1c99cf50da Clean up the flow api a little. 2012-12-09 20:50:53 +09:00
Bill Currie
e0c92b6089 Rename set_iter_t's member to value.
Makes more sense now that the membership of the value depends on the
inversion of the set.
2012-12-06 21:11:38 +09:00
Bill Currie
eb8fd55677 Move set.c into libQFutil.
Also move the ALLOC/FREE macros from qfcc.h to QF/alloc.h (needed to for
set.c).

Both modules are more generally useful than just for qfcc (eg, set
builtins for ruamoko).
2012-12-06 20:52:53 +09:00
Bill Currie
08b27efe33 Nuke the return type flow calculations.
They've proven to be unnecessary with the recent symbol/def changes.
2012-12-05 19:56:10 +09:00
Bill Currie
3f3b501c58 Move flowvar/deflabel from symbol_t to def_t.
With the need to handle aliasing in the optimizer, it has become apparent
that having the flow data attached to symbols is not nearly as useful as
having it attached to defs (which are views of the actual variables).

This also involves a bit of a cleanup of operand types: op_pointer and
op_alias are gone (this seems to greatly simplify the optimizer)

There is a bit of a problem with enums in switch statements, but this might
actually be a sign that something is not quite right in the switch code
(other than enums not being recognized as ints for jump table
optimization).
2012-12-05 19:47:22 +09:00
Bill Currie
98a0afa38f Add and use FREE() to complement ALLOC().
Now it will be easy to test memory access with valgrind (just compile with
DEBUG_QFCC_MEMORY defined).
2012-12-04 13:23:31 +09:00
Bill Currie
5725c5124c Rename the storage_class_t enum values.
With the intoduction of the statement type enum came a prefix clash. As
"st" makes sense for "statement type", I decided that "storage class"
should be "sc". Although there haven't been any problems as of yet, I
decided it would be a good idea to clean up the clash now. It also helps
avoid confusion (I was a bit surprised after working with st_assign etc to
be reminded of st_extern etc).
2012-12-02 10:11:30 +09:00
Bill Currie
848493379d Support calls through function temps.
I had forgotten function vars stored in ents and objects would use a temp
when calling the function.
2012-12-01 11:10:47 +09:00
Bill Currie
df66669a87 Handle back edges in return type flow.
Turns out the flow loop needs to be repeated until there are no changes.
2012-11-30 18:25:47 +09:00
Bill Currie
9e4fb3d3e7 Fix the return type flow.
Uninitialized variable :P
So far, basic tests seem to be good.
2012-11-30 17:24:39 +09:00
Bill Currie
554b2e4710 Add flow analysis to determin the type of .return.
It doesn't quite work yet, but...

It has proven necessary to know what type .return has at any point in the
function. The segfault in ctf is caused by the return statement added to
the end of the void function messing with the expr pointer stored in the
daglabel for .return. While this is actually by design (though the
statement really should have a valid expr pointer rather than), it actually
highlights a bigger problem: there's no stable knowledge of the current
type of .return. This is not a problem in expression statements as the
dagnodes for expression statements store the desired types of all operands.
However, when assigning from .return to attached variables in a leaf node,
the type of .return is not stored anywhere but the expression last
accessing .return.
2012-11-30 17:15:05 +09:00
Bill Currie
388247791d Re-enable the dags specific flow graph dump. 2012-11-30 16:56:25 +09:00
Bill Currie
71d1804e22 Clean up flow diagrams.
Now information like dags or live variables are dumped separately, and the
live variable information replaces the flow node in the diagram (like dags
have recently).
2012-11-30 16:52:22 +09:00
Bill Currie
93f53605ed Move and rename statement related flow_is_* and flow_get_*
They really should have been in statements.[ch] in the first place
(actually, they sort of were: is_goto etc, so some redundant code has been
removed, too).
2012-11-30 14:06:52 +09:00
Bill Currie
d0e56c91cc Detect non-initial nodes with no predecessors.
Such nodes are unreachable code (ie, dead blocks), but the dead block
removal code failed to remove them (current known cause: miscounted label
userrs). As such blocks cause problems for data flow analysis, ignoring
them is not a good idea. Thus make them an internal error.
2012-11-24 21:39:02 +09:00
Bill Currie
4c1dc568e0 Cop out on uninitialized large variables.
vectors, quaternions and structs are a little tricky. I need to think about
how to get them working, but I also want qfcc to get through as much code
as possible.
2012-11-24 16:49:46 +09:00
Bill Currie
40c97f9570 Tread immediate move statements similarly to assignments.
They're used for structure assignment in near data space. This fixes the
bogus uninitialized warnings on fully initialized structs.
2012-11-24 16:47:44 +09:00
Bill Currie
dbbca47a3b Mark initialized struct/array defs as initalized.
Also, use the initialized flag for setting up the initalized var set in
flow_uninitialized().
2012-11-24 15:26:27 +09:00
Bill Currie
0583dc82d3 Treat uninitialized temps as a bug.
It really should be impossible, but I'm not sure where the bug is yet
(though there are uninitialized variables that are false positives that
most definitely are initialized, might be related)
2012-11-21 10:26:41 +09:00
Bill Currie
686937123c Ensure flowvars always point to the var itself.
Pointing to aliases of the var causes all sorts of problems, but this time
it was causing the uninitialized variable detector to miss certain
parameters.
2012-11-21 09:43:59 +09:00
Bill Currie
0dc306c4b7 Fix the initialized var data flow.
Now most false positives have been fixed. Just some problems with aliased
vars (next) and then the usual false positives caused by branches.
2012-11-21 09:42:02 +09:00
Bill Currie
547ea78ad7 Implement uninitialized variable checking.
It currently gets a lot of false positives (globals and parameters?), but
the initial tests for just local vars worked.
2012-11-20 21:49:47 +09:00
Bill Currie
56103f9a38 Treat global variables as live at the end of a function.
.return and .param_N are not classed as global variables for data flow
analysis. .return is taken care of by return statements, and .param_N by
call statements.

With this, the menus work up to attempting to load the menu plist.
Something is corrupting zmalloc's blocks.
2012-11-19 17:21:35 +09:00
Bill Currie
1e72e3eb20 Make the post-optimization sblocks dump optional. 2012-11-19 15:24:09 +09:00
Bill Currie
0c3aeb30aa Reuse tempary variables.
Now that I've got nice code, it was worth doing. Unfortunatly, bsearch
style switch statements have problems.
switch.r:14: BUG: temp users went negative: <tmp 0x21b6840:-1>
switch.r:14: BUG: temp users went negative: <tmp 0x21b6840:-2>
switch.r:14: BUG: temp users went negative: <tmp 0x21b6840:-3>
switch.r:14: BUG: temp users went negative: <tmp 0x21b67d0:-1>
2012-11-18 19:10:18 +09:00
Bill Currie
12133bc02f Rewrite dags to use sets.
While things are quite broken now (very incorrect code is being generated),
the dag is much easier to work with. The dag is now stored in an array of
nodes (the children pointers are still used for dagnode operands), and sets
are used for marking node parents, attached identifiers and (when done,
extra edges).
2012-11-17 21:14:42 +09:00
Bill Currie
872b13616d Ensure return's operand gets set properly.
Yay for coding and designing at the same time, not :P
2012-11-16 21:50:27 +09:00
Bill Currie
1100efba54 Nuke find_operands in favor of flow_analyze_statement.
flow_analyze_statement uses the statement type to quickly determin which
operands are inputs and which are outputs. It takes (optional) sets for
used variables, defined variables and killed variables (only partially
working, but I don't actually use kill sets yet). It also takes an optional
array for storing the operands: index 0 is the output, 1-3 are the inputs.
flow_analyze_statement clears any given sets on entry.

Live variable analysis now uses the sets rather than individual vars. Much
cleaner code :).

Dags are completely broken.
2012-11-16 19:33:37 +09:00
Bill Currie
69543cf85b Fix an uninitialized variable.
It was never a propblem until an attempt to dump empty sblocks was made.
2012-11-15 13:44:09 +09:00
Bill Currie
d76e2a8423 Make a start on regenerating code from dags.
Some parts are a lot messier than I thought, so the actual codegen in the
dags code is just a minimal stub for now.
2012-11-15 13:44:09 +09:00
Bill Currie
2b2ea5c9b3 Compute dags as part of data flow analysis.
I want to use the live variable information when building the dags.
2012-11-15 13:44:08 +09:00