mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
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.
This commit is contained in:
parent
802e1981bb
commit
d76e2a8423
5 changed files with 96 additions and 3 deletions
|
@ -35,6 +35,10 @@
|
|||
*/
|
||||
//@{
|
||||
|
||||
struct dstring_s;
|
||||
struct flownode_s;
|
||||
struct sblock_s;
|
||||
|
||||
typedef struct daglabel_s {
|
||||
/// \name attached identifer linked list
|
||||
//@{
|
||||
|
@ -51,6 +55,7 @@ typedef struct dagnode_s {
|
|||
struct dagnode_s *next;
|
||||
int print_count; ///< used to avoid double printing nodes
|
||||
int is_child; ///< true if a child node
|
||||
int cost; ///< cost of this node in temp vars
|
||||
daglabel_t *label; ///< ident/const if leaf node, or operator
|
||||
/// \name child nodes
|
||||
/// All three child nodes will be null if this node is a leaf
|
||||
|
@ -69,9 +74,7 @@ typedef struct dagnode_s {
|
|||
} dagnode_t;
|
||||
|
||||
const char *daglabel_string (daglabel_t *label);
|
||||
struct dstring_s;
|
||||
void print_dag (struct dstring_s *dstr, dagnode_t *node);
|
||||
struct flownode_s;
|
||||
|
||||
/** Make a dag for a single basic block.
|
||||
|
||||
|
@ -80,7 +83,9 @@ struct flownode_s;
|
|||
variable information already computed.
|
||||
\return The dag representing the basic block.
|
||||
*/
|
||||
dagnode_t *dag_create (const struct flownode_s *node);
|
||||
dagnode_t *dag_create (const struct flownode_s *flownode);
|
||||
|
||||
void dag_generate (struct sblock_s *block, const struct flownode_s *flownode);
|
||||
|
||||
//@}
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ void flow_build_vars (struct function_s *func);
|
|||
flowgraph_t *flow_build_graph (struct sblock_s *func);
|
||||
void flow_del_graph (flowgraph_t *graph);
|
||||
void flow_data_flow (flowgraph_t *graph);
|
||||
struct sblock_s *flow_generate (flowgraph_t *graph);
|
||||
|
||||
void print_flowgraph (flowgraph_t *graph, const char *filename);
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/mathlib.h"
|
||||
|
||||
#include "dags.h"
|
||||
#include "diagnostic.h"
|
||||
|
@ -376,3 +377,60 @@ dag_create (const flownode_t *flownode)
|
|||
}
|
||||
return dagnodes;
|
||||
}
|
||||
|
||||
static void
|
||||
dag_calc_node_costs (dagnode_t *dagnode)
|
||||
{
|
||||
if ((!dagnode->a && (dagnode->b || dagnode->c))
|
||||
|| (dagnode->a && !dagnode->b && dagnode->c))
|
||||
internal_error (0, "bad dag node");
|
||||
|
||||
if (dagnode->a)
|
||||
dag_calc_node_costs (dagnode->a);
|
||||
if (dagnode->b)
|
||||
dag_calc_node_costs (dagnode->b);
|
||||
if (dagnode->c)
|
||||
dag_calc_node_costs (dagnode->c);
|
||||
|
||||
// if dagnode->a is null, then this is a leaf (as b and c are guaranted to
|
||||
// be null)
|
||||
if (!dagnode->a) {
|
||||
// Because qc vm statements don't mix source and destination operands,
|
||||
// leaves never need temporary variables.
|
||||
dagnode->cost = 0;
|
||||
} else {
|
||||
int different = 0;
|
||||
|
||||
// a non-leaf is guaranteed to have a valid "a"
|
||||
dagnode->cost = dagnode->a->cost;
|
||||
if (dagnode->b && dagnode->b->cost != dagnode->cost) {
|
||||
dagnode->cost = max (dagnode->cost, dagnode->b->cost);
|
||||
different = 1;
|
||||
}
|
||||
if (dagnode->c && (different || dagnode->c->cost != dagnode->cost)) {
|
||||
dagnode->cost = max (dagnode->cost, dagnode->c->cost);
|
||||
different = 1;
|
||||
}
|
||||
if (!different)
|
||||
dagnode->cost += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static operand_t *
|
||||
dag_gencode (sblock_t *block, const dagnode_t *dagnode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dag_generate (sblock_t *block, const flownode_t *flownode)
|
||||
{
|
||||
const dagnode_t *dag;
|
||||
|
||||
dag_calc_node_costs (flownode->dag);
|
||||
for (dag = flownode->dag; dag; dag = dag->next) {
|
||||
//if (!dag->a || (strcmp (dag->label->opcode, ".=") && !dag->identifiers))
|
||||
// continue;
|
||||
dag_gencode (block, dag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,6 +362,34 @@ flow_data_flow (flowgraph_t *graph)
|
|||
dump_dot ("flow", graph, dump_dot_flow);
|
||||
}
|
||||
|
||||
sblock_t *
|
||||
flow_generate (flowgraph_t *graph)
|
||||
{
|
||||
int i;
|
||||
sblock_t *code = 0;
|
||||
sblock_t **tail = &code;
|
||||
|
||||
for (i = 0; i < graph->num_nodes; i++) {
|
||||
ex_label_t *label;
|
||||
sblock_t *block;
|
||||
|
||||
flownode_t *node = graph->nodes[i];
|
||||
*tail = block = new_sblock ();
|
||||
tail = &(*tail)->next;
|
||||
// first, transfer any labels on the old node to the new
|
||||
while ((label = node->sblock->labels)) {
|
||||
node->sblock->labels = label->next;
|
||||
label->next = block->labels;
|
||||
block->labels = label;
|
||||
label->dest = block;
|
||||
}
|
||||
// generate new statements from the dag;
|
||||
dag_generate (block, node);
|
||||
}
|
||||
dump_dot ("post", code, dump_dot_sblock);
|
||||
return code;
|
||||
}
|
||||
|
||||
int
|
||||
flow_is_cond (statement_t *s)
|
||||
{
|
||||
|
|
|
@ -647,6 +647,7 @@ emit_function (function_t *f, expr_t *e)
|
|||
f->graph = flow_build_graph (f->sblock);
|
||||
f->graph->func = f;
|
||||
flow_data_flow (f->graph);
|
||||
f->sblock = flow_generate (f->graph);
|
||||
emit_statements (f->sblock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue