Skip to content
Snippets Groups Projects
cfg_print.c 16.2 KiB
Newer Older
#include <stdio.h>
#include<assert.h>

#include "mcc/dynamic_array.h"
#include "mcc/symbol_table.h"
#include "mcc/symbol_table_print.h"
#include "mcc/tac.h"
#include "mcc/tac_print.h"

#define LABEL_SIZE 64


krf41037's avatar
krf41037 committed
void print_dot_begin(FILE *out)
{
	assert(out);

	fprintf(out, "digraph \"CFG\" {\n"
			"\tnodesep=0.6\n");
}

krf41037's avatar
krf41037 committed
void print_dot_end(FILE *out)
{
	assert(out);

	fprintf(out, "}\n");
}

krf41037's avatar
krf41037 committed
void print_dot_node(FILE *out, const void *node, const char *label)
{
	assert(out);
	assert(node);
	assert(label);

	fprintf(out, "\t\"%p\" [shape=box, label=\"%s\"];\n", node, label);
}

krf41037's avatar
krf41037 committed
void print_dot_edge(FILE *out, const void *src_node, const void *dst_node, const char *label)
{
	assert(out);
	assert(src_node);
	assert(dst_node);
	assert(label);

	fprintf(out, "\t\"%p\" -> \"%p\" [label=\"%s\"];\n", src_node, dst_node, label);
}


krf41037's avatar
krf41037 committed
void print_dot_node_diamond(FILE *out, const void *node, const char *label)
{
    assert(out);
    assert(node);
    assert(label);

    fprintf(out, "\t\"%p\" [shape=diamond, label=\"%s\"];\n", node, label);
}

FlorianKrull's avatar
FlorianKrull committed
void print_dot_node_label(FILE *out, char *label)
{
    assert(out);
    assert(label);

FlorianKrull's avatar
FlorianKrull committed
    fprintf(out, "\t\"Label%s\" [shape=box, label=\"Label%s\"];\n", label,label);
krf41037's avatar
krf41037 committed
void print_dot_edge_from_label(FILE *out,
                           const void *dst_node, int label)
{
    assert(out);
    assert(dst_node);
    assert(label);

    fprintf(out, "\t\"Label%d\" -> \"%p\" [label=\"%s\"];\n", label, dst_node,
            "");
}

krf41037's avatar
krf41037 committed
void print_dot_edge_label(FILE *out, const void *src_node,
FlorianKrull's avatar
FlorianKrull committed
                           char *label, bool if_else)
{
    assert(out);
    assert(src_node);
    assert(label);
    if(if_else==true){
FlorianKrull's avatar
FlorianKrull committed
        fprintf(out, "\t\"%p\" -> \"Label%s\" [label=\"%s\"];\n", src_node, label,"YES");
    }else{
FlorianKrull's avatar
FlorianKrull committed
        fprintf(out, "\t\"%p\" -> \"Label%s\" [label=\"%s\"];\n", src_node, label,"");
krf41037's avatar
krf41037 committed
void check_dot_edge(FILE *out,struct mcc_tac_entry *entry,
                         struct mcc_tac_entry *next_entry,const char *label)
{
    if(next_entry!=NULL){
        print_dot_edge(out,entry,next_entry,label);
    }
}


void mcc_print_cfg_dot(struct mcc_tac *tac, FILE *out)
{
    // fprintf(out,"------------------------------\n");
    // fprintf(out,"- CFG DOT  -\n");
    // fprintf(out,"------------------------------\n");

    for(int i = 0; i < tac-> tac_entries->size; i++)
    {
        struct mcc_tac_entry *entry = tac->tac_entries->arr[i];
        struct mcc_tac_entry *next_entry = tac->tac_entries->arr[i+1];
        const char *op_type = tac_type(entry->tac_op);
        char label[LABEL_SIZE] = { 0 };
        switch (entry->tac_op)
        {
            case MCC_TAC_BOOL:
            case MCC_TAC_IDENTIFIER_BOOL:
            case MCC_TAC_BOOL_LITERAL:
            case MCC_TAC_INT:
            case MCC_TAC_IDENTIFIER_INT:
            case MCC_TAC_INT_LITERAL:
            case MCC_TAC_FLOAT:
            case MCC_TAC_IDENTIFIER_FLOAT:
            case MCC_TAC_FLOAT_LITERAL:
            case MCC_TAC_STRING:
            case MCC_TAC_IDENTIFIER_STRING:
            case MCC_TAC_STRING_LITERAL:
            /*
            * have to do this otherwise 'label can only be part of
            * a statement and a declaration is not a statement' error
            */
                
                snprintf(label, sizeof(label),"%s = %s (%s)\n", entry->result, entry->arg1, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
                
            // Unary
            case MCC_TAC_MINUS_INT_UN:
            case MCC_TAC_MINUS_FLOAT_UN:
                snprintf(label, sizeof(label),"%s = -%s (%s)\n", entry->result, entry->arg1, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_NOT:
                snprintf(label, sizeof(label),"%s = !%s (%s)\n", entry->result, entry->arg1, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            
             // Binary
            case MCC_TAC_PLUS_INT:
            case MCC_TAC_PLUS_FLOAT:
                snprintf(label, sizeof(label),"%s = %s + %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_MINUS_INT_BIN:
            case MCC_TAC_MINUS_FLOAT_BIN:
                snprintf(label, sizeof(label),"%s = %s - %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_MUL_INT:
            case MCC_TAC_MUL_FLOAT:
                snprintf(label, sizeof(label),"%s = %s * %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_DIV_INT:
            case MCC_TAC_DIV_FLOAT:
               snprintf(label, sizeof(label),"%s = %s / %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_LT:
            case MCC_TAC_LT_FLOAT:
                snprintf(label, sizeof(label),"%s = %s < %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_GT:
            case MCC_TAC_GT_FLOAT:
                snprintf(label, sizeof(label),"%s = %s > %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_LTEQ:
            case MCC_TAC_LTEQ_FLOAT:
                snprintf(label, sizeof(label),"%s = %s <= %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_GTEQ:
            case MCC_TAC_GTEQ_FLOAT:
                snprintf(label, sizeof(label),"%s = %s >= %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_AND:
                snprintf(label, sizeof(label),"%s = %s && %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_OR:
                snprintf(label, sizeof(label),"%s = %s || %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_EQ:
            case MCC_TAC_EQ_FLOAT:
            case MCC_TAC_EQ_BOOL:
                snprintf(label, sizeof(label),"%s = %s == %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_NEQ:
            case MCC_TAC_NEQ_FLOAT:
            case MCC_TAC_NEQ_BOOL:
                snprintf(label, sizeof(label),"%s = %s != %s (%s)\n", entry->result, entry->arg1,
                       entry->arg2, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;

            // params
            case MCC_TAC_PARAM_BOOL:
            case MCC_TAC_PARAM_INT:
            case MCC_TAC_PARAM_FLOAT:
            case MCC_TAC_PARAM_STRING:
                snprintf(label, sizeof(label),"param_push %s (%s)\n", entry->arg1, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;

            case MCC_TAC_PARAM_POP_BOOL:
            case MCC_TAC_PARAM_POP_INT:
            case MCC_TAC_PARAM_POP_FLOAT:
            case MCC_TAC_PARAM_POP_STRING:
                snprintf(label, sizeof(label),"param_pop %s (%s)\n", entry->arg1, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            
             // load
            case MCC_TAC_LOAD_BOOL:
            case MCC_TAC_LOAD_INT:
            case MCC_TAC_LOAD_FLOAT:
            case MCC_TAC_LOAD_STRING:
                snprintf(label, sizeof(label),"load %s[%s] %s (%s)\n", entry->arg1, entry->arg2,
                       entry->result, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            
             // store
            case MCC_TAC_STORE_BOOL:
            case MCC_TAC_STORE_INT:
            case MCC_TAC_STORE_FLOAT:
            case MCC_TAC_STORE_STRING:
                snprintf(label, sizeof(label),"store %s[%s] %s (%s)\n", entry->result, entry->arg2,
                       entry->arg1, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            
            // IR operations
            case MCC_TAC_JMP:
                snprintf(label, sizeof(label),"jump %s (%s)\n", entry->result, op_type);
                print_dot_node(out,entry,label);       
                print_dot_edge_label(out,entry,next_entry->result,false);   
                break;
            case MCC_TAC_JMP_FALSE:
                snprintf(label, sizeof(label),"jumpfalse %s %s (%s)\n", entry->arg1, entry->result,
                       op_type);
                print_dot_node_diamond(out,entry,label);
                check_dot_edge(out,entry,next_entry,label);
                print_dot_edge_label(out,entry,entry->result,false);
                break;
            case MCC_TAC_LABEL:
                print_dot_node_label(out,entry->result);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }
                break;
			case MCC_TAC_VARIABLE_DECLARATION:
                snprintf(label, sizeof(label),"declaration %s\n", entry->arg1);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
				break;
            case MCC_TAC_CALL:
                snprintf(label, sizeof(label),"call %s %s (%s)\n", entry->result, entry->arg1, op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_RETURN:
                snprintf(label, sizeof(label),"return (%s)\n", op_type);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;
            case MCC_TAC_FUNCTION_END:
                snprintf(label, sizeof(label),"return (%s)\n", op_type);
                print_dot_node(out,entry,label);
FlorianKrull's avatar
FlorianKrull committed
                // if(next_entry->tac_op == MCC_TAC_LABEL){
                //     print_dot_edge_label(out,entry,next_entry->result,false);
                // }
                print_dot_end(out);
                break;
            case MCC_TAC_FUNCTION_START:
                print_dot_begin(out);
                snprintf(label, sizeof(label),"\n\nfunction %s start  \n", entry -> arg1);
                print_dot_node(out,entry,label);
                if(next_entry->tac_op == MCC_TAC_LABEL){
                    print_dot_edge_label(out,entry,next_entry->result,false);
                }else{
                    check_dot_edge(out,entry,next_entry,"");
                }
                break;

        
FlorianKrull's avatar
FlorianKrull committed
            default: fprintf(out, "error %s\n", op_type);