return (node->left.val.f);
}
+/*
+ * store backup values for var versions, restore at the end of block
+ * popping a join node processes phis as stores propagating phis to outer join nodes
+ * multiple assignments in blocks update a single var entry.
+*/
+
+static size_t phi_add(Parser* p, SsaVar var)
+{
+ Symbol* sym = symbol_getbyid(p, var.symid);
+ printf("phi_add()\n");
+
+ printf(" %s.%lu\n", sym->name, sym->version);
+
+ /* first, append the phi function to the list */
+ SsaPhi** phis = &(p->curr_join->phis);
+ for (; *phis; phis = &((*phis)->next))
+ {
+ if ((*phis)->symid == var.symid)
+ {
+ break;
+ }
+ }
+ if (!*phis)
+ {
+ puts("new phi()");
+ *phis = calloc(1, sizeof(SsaPhi));
+ (*phis)->symid = var.symid;
+ (*phis)->backup_ver = sym->version;
+ }
+ else if ((*phis)->latest_ver > sym->version)
+ {
+ sym->version = (*phis)->latest_ver;
+ printf(" setting to latest: %s.%lu\n", sym->name, sym->version);
+ }
+
+ /* now add or update the variable entry */
+ SsaPhiVar** vars = &((*phis)->vars);
+ for (; *vars; vars = &((*vars)->next))
+ {
+ if ((*vars)->block == p->curr_block->id)
+ {
+ break;
+ }
+ }
+ if (!*vars)
+ {
+ *vars = calloc(1, sizeof(SsaPhiVar));
+ (*vars)->block = p->curr_block->id;
+ printf(" new var %s from block %lu\n", sym->name, p->curr_block->id);
+ }
+
+ sym->version++;
+ (*vars)->version = sym->version;
+ (*phis)->latest_ver = (*vars)->version;
+
+ printf(" %s.%lu\n", sym->name, sym->version);
+
+ return sym->version;
+}
+
+
+void ssa_reset_vars(Parser* p)
+{
+ puts("ssa_reset_vars");
+ for (SsaPhi* phi = p->curr_join->phis; phi; phi = phi->next)
+ {
+ Symbol* s = symbol_getbyid(p, phi->symid);
+ s->version = phi->backup_ver;
+ }
+}
+
+void ssa_join(Parser* p)
+{
+ puts("ssa_join");
+ ssa_reset_vars(p);
+
+ /* pop the join node off the list since we're done with it */
+ SsaBlock* block = p->curr_join;
+ p->curr_block = p->curr_join;
+ p->curr_join = p->curr_join->next;
+
+ /* update variable versions based on phi functions */
+ for (SsaPhi* phi = block->phis; phi; phi = phi->next)
+ {
+ Symbol* s = symbol_getbyid(p, phi->symid);
+ s->version = phi->latest_ver;
+ phi->latest_ver++;
+ printf("block %lu: %s.%lu\n", block->id, s->name, s->version);
+
+ if (p->curr_join)
+ {
+ s->version = phi_add(p, (SsaVar){
+ .symid = phi->symid,
+ .symver = s->version
+ });
+ }
+
+ printf("block %lu: %s.%lu\n", block->id, s->name, s->version);
+ }
+}
+
+
static SsaNode* ssa_node(int code, int mode)
{
SsaNode* node = calloc(1, sizeof(SsaNode));
: unop(p, op, left);
}
-static void phi_add(Parser* p, SsaVar var)
-{
- /* for all enclosing join nodes */
- for (SsaBlock* join = p->curr_join; join; join = join->next)
- {
- /* first, append the phi function to the list */
- SsaPhi** phis = &(join->phis);
- for (; *phis; phis = &((*phis)->next))
- {
- if ((*phis)->symid == var.symid)
- {
- break;
- }
- }
- if (!*phis)
- {
- *phis = calloc(1, sizeof(SsaPhi));
- (*phis)->symid = var.symid;
- }
-
- /* now add or update the variable entry */
- SsaPhiVar** vars = &((*phis)->vars);
- for (; *vars; vars = &((*vars)->next))
- {
- if ((*vars)->block == p->curr_block->id)
- {
- (*vars)->version = var.symver;
- break;
- }
- }
- if (!*vars)
- {
- *vars = calloc(1, sizeof(SsaPhiVar));
- (*vars)->block = p->curr_block->id;
- (*vars)->version = var.symver;
- }
- }
-}
-
SsaNode* ssa_store(Parser* p, SsaNode* dest, SsaNode* value)
{
load(p, value);
-// load(p, dest);
SsaNode* node = ssa_node('=', MODE_VAR);
node->type = dest->type;
node->dest = dest->left.var;
node->left.var = value->dest;
-
- Symbol* sym = symbol_getbyid(p, node->dest.symid);
- sym->version++;
- node->dest.symver = sym->version;
- phi_add(p, node->dest);
-
+ node->dest.symver = phi_add(p, node->dest);
ssa_block_add(p->curr_block, node);
node->loaded = 1;
return node;
for (SsaPhi* phi = block->phis; phi; phi = phi->next)
{
Symbol* s = symbol_getbyid(p, phi->symid);
- s->version++;
printf(" %s.%lu = phi(", s->name, s->version);
for (SsaPhiVar* var = phi->vars; var; var = var->next)
{
void ssa_print_graph(Parser* p, SsaBlock* block)
{
- /* perform a topological sort of the nodes */
- SsaBlock* sorted = NULL;
- Bitset* set = bitset_new(p->blockid);
- topsort(set, &sorted, block);
-
-
- /* now let's print the plantuml representation */
- printf("@startuml\n");
- printf("[*] --> block%lu\n", block->id);
- for (SsaBlock* curr = sorted; curr; curr = curr->next)
- {
-
- /* print the phis */
- for (SsaPhi* phi = curr->phis; phi; phi = phi->next)
- {
- Symbol* s = symbol_getbyid(p, phi->symid);
- s->version++;
- printf("block%lu: %s.%lu = phi(", curr->id, s->name, s->version);
- for (SsaPhiVar* var = phi->vars; var; var = var->next)
- {
- printf("%s.%lu", s->name, var->version);
- if (var->next)
- {
- printf(", ");
- }
- }
- puts(")");
- }
-
- /* print the instructions */
- for (SsaNode* node = curr->head; node; node = node->next)
- {
- printf("block%lu : ", curr->id);
- print_dest(p, node);
- ssa_print(p, node);
- puts("");
- }
-
- /* print the links */
- if (curr->links[1])
- {
- printf("block%lu --> block%lu\n", curr->id, curr->links[1]->id);
- }
- if (curr->links[0])
- {
- printf("block%lu --> block%lu\n", curr->id, curr->links[0]->id);
- }
-
- puts("");
- }
- printf("@enduml\n\n");
+// /* perform a topological sort of the nodes */
+// SsaBlock* sorted = NULL;
+// Bitset* set = bitset_new(p->blockid);
+// topsort(set, &sorted, block);
+//
+//
+// /* now let's print the plantuml representation */
+// printf("@startuml\n");
+// printf("[*] --> block%lu\n", block->id);
+// for (SsaBlock* curr = sorted; curr; curr = curr->next)
+// {
+// /* print the phis */
+// for (SsaPhi* phi = curr->phis; phi; phi = phi->next)
+// {
+// Symbol* s = symbol_getbyid(p, phi->symid);
+// printf("block%lu: %s.%lu = phi(", curr->id, s->name, s->version);
+// for (SsaPhiVar* var = phi->vars; var; var = var->next)
+// {
+// printf("%s.%lu", s->name, var->version);
+// if (var->next)
+// {
+// printf(", ");
+// }
+// }
+// puts(")");
+// }
+//
+// /* print the instructions */
+// for (SsaNode* node = curr->head; node; node = node->next)
+// {
+// printf("block%lu : ", curr->id);
+// print_dest(p, node);
+// ssa_print(p, node);
+// puts("");
+// }
+//
+// /* print the links */
+// if (curr->links[1])
+// {
+// printf("block%lu --> block%lu\n", curr->id, curr->links[1]->id);
+// }
+// if (curr->links[0])
+// {
+// printf("block%lu --> block%lu\n", curr->id, curr->links[0]->id);
+// }
+//
+// puts("");
+// }
+// printf("@enduml\n\n");
}
for (SsaPhi* phi = curr->phis; phi; phi = phi->next)
{
Symbol* s = symbol_getbyid(p, phi->symid);
- s->version++;
- printf(" %s.%lu = phi(", s->name, s->version);
+ printf(" %s.%lu = phi(", s->name, phi->latest_ver);
for (SsaPhiVar* var = phi->vars; var; var = var->next)
{
printf("%s.%lu", s->name, var->version);
/* print the instructions */
for (SsaNode* node = curr->head; node; node = node->next)
{
-// printf("block%lu : ", curr->id);
printf(" ");
print_dest(p, node);
ssa_print(p, node);