#ifndef NCTREF_VARTABLE_H #define NCTREF_VARTABLE_H #include"types.h" typedef enum { VARTABLEENTRY_SYMBOL, VARTABLEENTRY_TYPE, VARTABLEENTRY_VAR } VarTableEntryKind; union AST; typedef struct UseDef { union AST *def; // assign stmt union AST *use; // corresponding AST_EXPR_VAR union AST *stmt; // whole using stmt struct UseDef *next; } UseDef; // Stack, necessary for "possible reaching defs" such as from if statements typedef struct ReachingDefs { size_t defCount; union AST **defs; struct ReachingDefs *parent; } ReachingDefs; struct ReachingDefs *reachingdefs_push(struct ReachingDefs*); struct ReachingDefs *reachingdefs_coalesce(struct ReachingDefs*); void reachingdefs_set(struct ReachingDefs*, union AST*); typedef struct VarTableEntry { Type *type; VarTableEntryKind kind; struct { union { struct { char isLocal; char isExternal; const char *name; } symbol; struct { // For debugging const char *name; // Register allocation // vars in loops have higher priority // a more advanced approach would be to use weights for different colors (e.g. vars for mul "should" be in eax) uint8_t priority; uint16_t color, degree; // Used during parsing ReachingDefs *reachingDefs; // Optimizations UseDef *usedefFirst; UseDef *usedefLast; } var; }; } data; } VarTableEntry; typedef struct VarTable { struct VarTable *parent; size_t count; const char **names; VarTableEntry **data; } VarTable; VarTable *vartable_new(VarTable*); VarTableEntry *vartable_get(VarTable*, const char*); VarTableEntry *vartable_find(VarTable*, const char*); VarTableEntry *vartable_set(VarTable*, const char*, VarTableEntry*); void vartable_new_reachingdefs_for_all_vars(VarTable*); void vartable_coalesce_reachingdefs_for_all_vars(VarTable*); #endif