mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-05-31 00:30:57 +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 {
|
typedef struct daglabel_s {
|
||||||
/// \name attached identifer linked list
|
/// \name attached identifer linked list
|
||||||
//@{
|
//@{
|
||||||
|
@ -51,6 +55,7 @@ typedef struct dagnode_s {
|
||||||
struct dagnode_s *next;
|
struct dagnode_s *next;
|
||||||
int print_count; ///< used to avoid double printing nodes
|
int print_count; ///< used to avoid double printing nodes
|
||||||
int is_child; ///< true if a child node
|
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
|
daglabel_t *label; ///< ident/const if leaf node, or operator
|
||||||
/// \name child nodes
|
/// \name child nodes
|
||||||
/// All three child nodes will be null if this node is a leaf
|
/// All three child nodes will be null if this node is a leaf
|
||||||
|
@ -69,9 +74,7 @@ typedef struct dagnode_s {
|
||||||
} dagnode_t;
|
} dagnode_t;
|
||||||
|
|
||||||
const char *daglabel_string (daglabel_t *label);
|
const char *daglabel_string (daglabel_t *label);
|
||||||
struct dstring_s;
|
|
||||||
void print_dag (struct dstring_s *dstr, dagnode_t *node);
|
void print_dag (struct dstring_s *dstr, dagnode_t *node);
|
||||||
struct flownode_s;
|
|
||||||
|
|
||||||
/** Make a dag for a single basic block.
|
/** Make a dag for a single basic block.
|
||||||
|
|
||||||
|
@ -80,7 +83,9 @@ struct flownode_s;
|
||||||
variable information already computed.
|
variable information already computed.
|
||||||
\return The dag representing the basic block.
|
\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);
|
flowgraph_t *flow_build_graph (struct sblock_s *func);
|
||||||
void flow_del_graph (flowgraph_t *graph);
|
void flow_del_graph (flowgraph_t *graph);
|
||||||
void flow_data_flow (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);
|
void print_flowgraph (flowgraph_t *graph, const char *filename);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "QF/dstring.h"
|
#include "QF/dstring.h"
|
||||||
|
#include "QF/mathlib.h"
|
||||||
|
|
||||||
#include "dags.h"
|
#include "dags.h"
|
||||||
#include "diagnostic.h"
|
#include "diagnostic.h"
|
||||||
|
@ -376,3 +377,60 @@ dag_create (const flownode_t *flownode)
|
||||||
}
|
}
|
||||||
return dagnodes;
|
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);
|
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
|
int
|
||||||
flow_is_cond (statement_t *s)
|
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 = flow_build_graph (f->sblock);
|
||||||
f->graph->func = f;
|
f->graph->func = f;
|
||||||
flow_data_flow (f->graph);
|
flow_data_flow (f->graph);
|
||||||
|
f->sblock = flow_generate (f->graph);
|
||||||
emit_statements (f->sblock);
|
emit_statements (f->sblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue