Files
BlitzNext/compiler/declnode.cpp
T
2017-04-09 05:35:18 +02:00

289 lines
7.6 KiB
C++

#include "std.h"
#include "nodes.h"
//////////////////////////////
// Sequence of declarations //
//////////////////////////////
void DeclSeqNode::proto(DeclSeq *d, Environ *e) {
for (size_t k = 0; k < decls.size(); ++k) {
try { decls[k]->proto(d, e); } catch (Ex &x) {
if (x.pos < 0) x.pos = decls[k]->pos;
if (!x.file.size()) x.file = decls[k]->file;
throw;
}
}
}
void DeclSeqNode::semant(Environ *e) {
for (size_t k = 0; k < decls.size(); ++k) {
try { decls[k]->semant(e); } catch (Ex &x) {
if (x.pos < 0) x.pos = decls[k]->pos;
if (!x.file.size()) x.file = decls[k]->file;
throw;
}
}
}
void DeclSeqNode::translate(Codegen *g) {
for (size_t k = 0; k < decls.size(); ++k) {
try { decls[k]->translate(g); } catch (Ex &x) {
if (x.pos < 0) x.pos = decls[k]->pos;
if (!x.file.size()) x.file = decls[k]->file;
throw;
}
}
}
void DeclSeqNode::transdata(Codegen *g) {
for (size_t k = 0; k < decls.size(); ++k) {
try { decls[k]->transdata(g); } catch (Ex &x) {
if (x.pos < 0) x.pos = decls[k]->pos;
if (!x.file.size()) x.file = decls[k]->file;
throw;
}
}
}
////////////////////////////
// Simple var declaration //
////////////////////////////
void VarDeclNode::proto(DeclSeq *d, Environ *e) {
Type *ty = tagType(tag, e);
if (!ty) ty = Type::int_type;
ConstType *defType = 0;
if (expr != nullptr) {
expr->semant(e);
if (expr == nullptr) {
ex("Internal Error: expr turned into nullptr (1)");
}
expr = expr->castTo(ty, e);
if (expr == nullptr) {
ex("Internal Error: expr turned into nullptr (2)");
}
if (constant || (kind & DECL_PARAM)) {
ConstNode *c = static_cast<ConstNode*>(expr);//->constNode();
if (!c) ex("Expression must be constant");
if (ty == Type::int_type) ty = new ConstType(c->intValue());
else if (ty == Type::float_type) ty = new ConstType(c->floatValue());
else ty = new ConstType(c->stringValue());
e->types.push_back(ty);
delete expr; expr = 0;
}
if (expr == nullptr) {
ex("Internal Error: expr turned into nullptr (3)");
}
if (kind & DECL_PARAM) { // Heap corruption, this being replaced again?
defType = ty->constType(); ty = defType->valueType;
}
} else if (constant) ex("Constants must be initialized");
Decl *decl = d->insertDecl(ident, ty, kind, defType);
if (!decl) ex("Duplicate variable name");
if (expr) sem_var = new DeclVarNode(decl);
}
void VarDeclNode::semant(Environ *e) {}
void VarDeclNode::translate(Codegen *g) {
if (kind & DECL_GLOBAL) {
g->align_data(4);
g->i_data(0, "_v" + ident);
}
if (expr) g->code(sem_var->store(g, expr->translate(g)));
}
//////////////////////////
// Function Declaration //
//////////////////////////
void FuncDeclNode::proto(DeclSeq *d, Environ *e) {
Type *t = tagType(tag, e); if (!t) t = Type::int_type;
a_ptr<DeclSeq> decls(new DeclSeq());
params->proto(decls, e);
sem_type = new FuncType(t, decls.release(), false, false);
if (!d->insertDecl(ident, sem_type, DECL_FUNC)) {
delete sem_type; ex("duplicate identifier");
}
e->types.push_back(sem_type);
}
void FuncDeclNode::semant(Environ *e) {
sem_env = new Environ(genLabel(), sem_type->returnType, 1, e);
DeclSeq *decls = sem_env->decls;
int k;
for (k = 0; k < sem_type->params->size(); ++k) {
Decl *d = sem_type->params->decls[k];
if (!decls->insertDecl(d->name, d->type, d->kind)) ex("duplicate identifier");
}
stmts->semant(sem_env);
}
void FuncDeclNode::translate(Codegen *g) {
//var offsets
int size = enumVars(sem_env);
//enter function
g->enter("_f" + ident, size);
//initialize locals
TNode *t = createVars(sem_env);
if (t) g->code(t);
if (g->debug) {
string t = genLabel();
g->s_data(ident, t);
g->code(call("__bbDebugEnter", local(0), iconst((int)sem_env), global(t)));
}
//translate statements
stmts->translate(g);
for (size_t k = 0; k < sem_env->labels.size(); ++k) {
if (sem_env->labels[k]->def < 0) ex("Undefined label", sem_env->labels[k]->ref);
}
//leave the function
g->label(sem_env->funcLabel + "_leave");
t = deleteVars(sem_env);
if (g->debug) t = new TNode(IR_SEQ, call("__bbDebugLeave"), t);
g->leave(t, sem_type->params->size() * 4);
}
//////////////////////
// Type Declaration //
//////////////////////
void StructDeclNode::proto(DeclSeq *d, Environ *e) {
sem_type = new StructType(ident, new DeclSeq());
if (!d->insertDecl(ident, sem_type, DECL_STRUCT)) {
delete sem_type; ex("Duplicate identifier");
}
e->types.push_back(sem_type);
}
void StructDeclNode::semant(Environ *e) {
fields->proto(sem_type->fields, e);
for (int k = 0; k < sem_type->fields->size(); ++k) sem_type->fields->decls[k]->offset = k * 4;
}
void StructDeclNode::translate(Codegen *g) {
//translate fields
fields->translate(g);
//type ID
g->align_data(4);
g->i_data(5, "_t" + ident);
//used and free lists for type
int k;
for (k = 0; k < 2; ++k) {
string lab = genLabel();
g->i_data(0, lab); //fields
g->p_data(lab); //next
g->p_data(lab); //prev
g->i_data(0); //type
g->i_data(-1); //ref_cnt
}
//number of fields
g->i_data(sem_type->fields->size());
//type of each field
for (k = 0; k < sem_type->fields->size(); ++k) {
Decl *field = sem_type->fields->decls[k];
Type *type = field->type;
string t;
if (type == Type::int_type) t = "__bbIntType";
else if (type == Type::float_type) t = "__bbFltType";
else if (type == Type::string_type) t = "__bbStrType";
else if (StructType *s = type->structType()) t = "_t" + s->ident;
else if (VectorType *v = type->vectorType()) t = v->label;
g->p_data(t);
}
}
//////////////////////
// Data declaration //
//////////////////////
void DataDeclNode::proto(DeclSeq *d, Environ *e) {
expr = expr->semant(e);
ConstNode *c = expr->constNode();
if (!c) ex("Data expression must be constant");
if (expr->sem_type == Type::string_type) str_label = genLabel();
}
void DataDeclNode::semant(Environ *e) {}
void DataDeclNode::translate(Codegen *g) {
if (expr->sem_type != Type::string_type) return;
ConstNode *c = expr->constNode();
g->s_data(c->stringValue(), str_label);
}
void DataDeclNode::transdata(Codegen *g) {
ConstNode *c = expr->constNode();
if (expr->sem_type == Type::int_type) {
g->i_data(1); g->i_data(c->intValue());
} else if (expr->sem_type == Type::float_type) {
float n = c->floatValue();
g->i_data(2); g->i_data(*(int*)&n);
} else {
g->i_data(4); g->p_data(str_label);
}
}
////////////////////////
// Vector declaration //
////////////////////////
void VectorDeclNode::proto(DeclSeq *d, Environ *env) {
Type *ty = tagType(tag, env); if (!ty) ty = Type::int_type;
vector<int> sizes;
for (int k = 0; k < exprs->size(); ++k) {
ExprNode *e = exprs->exprs[k] = exprs->exprs[k]->semant(env);
ConstNode *c = e->constNode();
if (!c) ex("Blitz array sizes must be constant");
int n = c->intValue();
if (n < 0) ex("Blitz array sizes must not be negative");
sizes.push_back(n + 1);
}
string label = genLabel();
sem_type = new VectorType(label, ty, sizes);
if (!d->insertDecl(ident, sem_type, kind)) {
delete sem_type; ex("Duplicate identifier");
}
env->types.push_back(sem_type);
}
void VectorDeclNode::translate(Codegen *g) {
//type tag!
g->align_data(4);
VectorType *v = sem_type->vectorType();
g->i_data(6, v->label);
int sz = 1;
for (size_t k = 0; k < v->sizes.size(); ++k) sz *= v->sizes[k];
g->i_data(sz);
string t;
Type *type = v->elementType;
if (type == Type::int_type) t = "__bbIntType";
else if (type == Type::float_type) t = "__bbFltType";
else if (type == Type::string_type) t = "__bbStrType";
else if (StructType *s = type->structType()) t = "_t" + s->ident;
else if (VectorType *v = type->vectorType()) t = v->label;
g->p_data(t);
if (kind == DECL_GLOBAL) g->i_data(0, "_v" + ident);
}