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