Fucking add scope file oh my god how could I miss this
This commit is contained in:
parent
a39bf40755
commit
b204860b2e
112
src/scope.c
Normal file
112
src/scope.c
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#include"scope.h"
|
||||||
|
|
||||||
|
#include"utils.h"
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<string.h>
|
||||||
|
#include<assert.h>
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
struct ReachingDefs *reachingdefs_push(struct ReachingDefs *this) {
|
||||||
|
struct ReachingDefs *ret = calloc(1, sizeof(*ret));
|
||||||
|
ret->parent = this;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ReachingDefs *reachingdefs_coalesce(struct ReachingDefs *this) {
|
||||||
|
struct ReachingDefs *parent = this->parent;
|
||||||
|
if(parent) {
|
||||||
|
parent->defs = realloc(parent->defs, sizeof(*parent->defs) * (parent->defCount + this->defCount));
|
||||||
|
memcpy(&parent->defs[parent->defCount], this->defs, sizeof(*this->defs) * this->defCount);
|
||||||
|
parent->defCount += this->defCount;
|
||||||
|
}
|
||||||
|
free(this->defs);
|
||||||
|
free(this);
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reachingdefs_set(struct ReachingDefs *this, union AST *def) {
|
||||||
|
this->defCount = 1;
|
||||||
|
this->defs = realloc(this->defs, sizeof(*this->defs) * this->defCount);
|
||||||
|
this->defs[0] = def;
|
||||||
|
this->excludeParent = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope *scope_new(Scope *parent) {
|
||||||
|
Scope *ret = calloc(1, sizeof(*ret));
|
||||||
|
ret->parent = parent;
|
||||||
|
ret->count = 0;
|
||||||
|
ret->names = NULL;
|
||||||
|
ret->data = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopeItem *scope_get(Scope *this, const char *name) {
|
||||||
|
for(size_t v = 0; v < this->count; v++) {
|
||||||
|
if(!strcmp(name, this->names[v])) return this->data[v];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopeItem *scope_find(Scope *this, const char *name) {
|
||||||
|
Scope *tbl = this;
|
||||||
|
while(tbl) {
|
||||||
|
ScopeItem *entry = scope_get(tbl, name);
|
||||||
|
if(entry) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
tbl = tbl->parent;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopeItem *scope_set(Scope *this, const char *name, ScopeItem *e) {
|
||||||
|
name = strdup(name);
|
||||||
|
|
||||||
|
this->names = realloc(this->names, sizeof(*this->names) * (this->count + 1));
|
||||||
|
this->data = realloc(this->data, sizeof(*this->data) * (this->count + 1));
|
||||||
|
this->names[this->count] = name;
|
||||||
|
this->data[this->count] = e;
|
||||||
|
this->count++;
|
||||||
|
if(e->kind == SCOPEITEM_VAR) e->data.var.name = name;
|
||||||
|
e->owner = this;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopeItem *scope_find_int(Scope *scope, intmax_t val, const char *suffix) {
|
||||||
|
char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "%li%s", val, suffix ? suffix : "");
|
||||||
|
|
||||||
|
return scope_find(scope, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope *scope_merge(Scope *child) {
|
||||||
|
Scope *parent = child->parent;
|
||||||
|
|
||||||
|
parent->names = realloc(parent->names, sizeof(*parent->names) * (parent->count + child->count));
|
||||||
|
parent->data = realloc(parent->data, sizeof(*parent->data) * (parent->count + child->count));
|
||||||
|
|
||||||
|
for(size_t i = 0; i < child->count; i++) {
|
||||||
|
child->data[i]->owner = parent;
|
||||||
|
|
||||||
|
parent->names[parent->count] = child->names[i];
|
||||||
|
parent->data[parent->count] = child->data[i];
|
||||||
|
|
||||||
|
parent->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//free(child->names);
|
||||||
|
//free(child->data);
|
||||||
|
//free(child);
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vte_precolor(ScopeItem *vte, int class, int color) {
|
||||||
|
assert(vte->kind == SCOPEITEM_VAR && "vte must be var");
|
||||||
|
assert(!vte->data.var.precolored && "already precolored");
|
||||||
|
|
||||||
|
vte->data.var.precolored = true;
|
||||||
|
vte->data.var.registerClass = class;
|
||||||
|
vte->data.var.color = color;
|
||||||
|
}
|
111
src/scope.h
Normal file
111
src/scope.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#ifndef NCTREF_VARTABLE_H
|
||||||
|
#define NCTREF_VARTABLE_H
|
||||||
|
|
||||||
|
#include"types.h"
|
||||||
|
#include<stdbool.h>
|
||||||
|
|
||||||
|
struct Token;
|
||||||
|
union AST;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SCOPEITEM_SYMBOL, SCOPEITEM_VAR, SCOPEITEM_TYPE, SCOPEITEM_CEXPR
|
||||||
|
} ScopeItemKind;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
int excludeParent;
|
||||||
|
struct ReachingDefs *parent;
|
||||||
|
} ReachingDefs;
|
||||||
|
struct ReachingDefs *reachingdefs_push(struct ReachingDefs*);
|
||||||
|
struct ReachingDefs *reachingdefs_coalesce(struct ReachingDefs*);
|
||||||
|
void reachingdefs_set(struct ReachingDefs*, union AST*);
|
||||||
|
|
||||||
|
struct Scope;
|
||||||
|
typedef struct ScopeItem {
|
||||||
|
Type *type;
|
||||||
|
|
||||||
|
struct Scope *owner;
|
||||||
|
|
||||||
|
ScopeItemKind kind;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char isLocal;
|
||||||
|
char isExternal;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct Scope *scope;
|
||||||
|
struct Token *rangeTokens;
|
||||||
|
size_t startTokI;
|
||||||
|
size_t endTokI;
|
||||||
|
} genfunc;
|
||||||
|
} 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. multipliers "should" be in eax)
|
||||||
|
uint8_t priority;
|
||||||
|
int16_t color, degree;
|
||||||
|
bool precolored, preclassed;
|
||||||
|
int registerClass;
|
||||||
|
|
||||||
|
// Used during parsing
|
||||||
|
|
||||||
|
ReachingDefs *reachingDefs;
|
||||||
|
|
||||||
|
// Optimizations
|
||||||
|
|
||||||
|
UseDef *usedefFirst;
|
||||||
|
UseDef *usedefLast;
|
||||||
|
} var;
|
||||||
|
struct {
|
||||||
|
Type *ptr;
|
||||||
|
} type;
|
||||||
|
struct {
|
||||||
|
// cexpr is used for expression parametization as opposed to type parametrization
|
||||||
|
// I don't like the idea of having a special ScopeItem kind for these, but all other places were worse
|
||||||
|
const char *paramName;
|
||||||
|
size_t paramIdx;
|
||||||
|
|
||||||
|
// If the cexpr has been parametrized (as opposed to just being a symbol), this field will be non-NULL
|
||||||
|
union AST *concrete;
|
||||||
|
} cexpr;
|
||||||
|
} data;
|
||||||
|
} ScopeItem;
|
||||||
|
|
||||||
|
typedef struct Scope {
|
||||||
|
struct Scope *parent;
|
||||||
|
|
||||||
|
size_t count;
|
||||||
|
const char **names;
|
||||||
|
ScopeItem **data;
|
||||||
|
} Scope;
|
||||||
|
|
||||||
|
Scope *scope_new(Scope*);
|
||||||
|
ScopeItem *scope_get(Scope*, const char*);
|
||||||
|
ScopeItem *scope_find(Scope*, const char*);
|
||||||
|
ScopeItem *scope_set(Scope*, const char*, ScopeItem*);
|
||||||
|
|
||||||
|
ScopeItem *scope_find_int(Scope*, intmax_t, const char*);
|
||||||
|
|
||||||
|
Scope *scope_merge(Scope *child);
|
||||||
|
|
||||||
|
void vte_precolor(ScopeItem *vte, int resclass, int color);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user