#include "varnode.hpp" #include "codegen.hpp" #include "environ.hpp" #include "exprnode.hpp" #include "type.hpp" ////////////////////////////////// // Common get/set for variables // ////////////////////////////////// TNode* VarNode::load(Codegen* g) { TNode* t = translate(g); if (sem_type == Type::string_type) return call("__bbStrLoad", t); return mem(t); } TNode* VarNode::store(Codegen* g, TNode* n) { TNode* t = translate(g); if (sem_type->structType()) return call("__bbObjStore", t, n); if (sem_type == Type::string_type) return call("__bbStrStore", t, n); return move(n, mem(t)); } bool VarNode::isObjParam() { return false; } DeclVarNode::DeclVarNode(Decl* d) : sem_decl(d) { if (d) sem_type = d->type; } ////////////////// // Declared var // ////////////////// void DeclVarNode::semant(Environ* e) {} TNode* DeclVarNode::translate(Codegen* g) { if (sem_decl->kind == DECL_GLOBAL) return global("_v" + sem_decl->name); return local(sem_decl->offset); } TNode* DeclVarNode::store(Codegen* g, TNode* n) { if (isObjParam()) { TNode* t = translate(g); return move(n, mem(t)); } return VarNode::store(g, n); } bool DeclVarNode::isObjParam() { return sem_type->structType() && sem_decl->kind == DECL_PARAM; } IdentVarNode::IdentVarNode(const std::string& i, const std::string& t) : ident(i), tag(t) {} /////////////// // Ident var // /////////////// void IdentVarNode::semant(Environ* e) { if (sem_decl) return; Type* t = tagType(tag, e); if (!t) t = Type::int_type; if (sem_decl = e->findDecl(ident)) { if (!(sem_decl->kind & (DECL_GLOBAL | DECL_LOCAL | DECL_PARAM))) { ex("Identifier '" + sem_decl->name + "' may not be used like this"); } Type* ty = sem_decl->type; if (ty->constType()) ty = ty->constType()->valueType; if (tag.size() && t != ty) ex("Variable type mismatch"); } else { //ugly auto decl! sem_decl = e->decls->insertDecl(ident, t, DECL_LOCAL); } sem_type = sem_decl->type; } ///////////////// // Indexed Var // ///////////////// void ArrayVarNode::semant(Environ* e) { exprs->semant(e); exprs->castTo(Type::int_type, e); Type* t = e->findType(tag); sem_decl = e->findDecl(ident); if (!sem_decl || !(sem_decl->kind & DECL_ARRAY)) ex("Array not found"); ArrayType* a = sem_decl->type->arrayType(); if (t && t != a->type) ex("array type mismtach"); if (a->size != exprs->size()) ex("incorrect number of dimensions"); sem_type = a->type; } TNode* ArrayVarNode::translate(Codegen* g) { TNode* t = 0; for (int k = 0; k < exprs->size(); ++k) { TNode* e = exprs->exprs[k]->translate(g); if (k) { TNode* s = mem(add(global("_a" + ident), iconst(k * 4 + 8))); e = add(t, mul(e, s)); } if (g->debug) { TNode* s = mem(add(global("_a" + ident), iconst(k * 4 + 12))); t = jumpge(e, s, "__bbArrayBoundsEx"); } else t = e; } t = add(mem(global("_a" + ident)), mul(t, iconst(4))); return t; } /////////////// // Field var // /////////////// void FieldVarNode::semant(Environ* e) { expr = expr->semant(e); StructType* s = expr->sem_type->structType(); if (!s) ex("Variable must be a Type"); sem_field = s->fields->findDecl(ident); if (!sem_field) ex("Type field not found"); sem_type = sem_field->type; } TNode* FieldVarNode::translate(Codegen* g) { TNode* t = expr->translate(g); if (g->debug) t = jumpf(t, "__bbNullObjEx"); t = mem(t); if (g->debug) t = jumpf(t, "__bbNullObjEx"); return add(t, iconst(sem_field->offset)); } VectorVarNode::VectorVarNode(ExprNode* e, ExprSeqNode* es) : expr(e), exprs(es) {} VectorVarNode::~VectorVarNode() { delete expr; delete exprs; } //////////////// // Vector var // //////////////// void VectorVarNode::semant(Environ* e) { expr = expr->semant(e); vec_type = expr->sem_type->vectorType(); if (!vec_type) ex("Variable must be a Blitz array"); if (vec_type->sizes.size() != exprs->size()) ex("Incorrect number of subscripts"); exprs->semant(e); exprs->castTo(Type::int_type, e); for (int k = 0; k < exprs->size(); ++k) { if (ConstNode* t = exprs->exprs[k]->constNode()) { if (t->intValue() >= vec_type->sizes[k]) { ex("Blitz array subscript out of range"); } } } sem_type = vec_type->elementType; } TNode* VectorVarNode::translate(Codegen* g) { int sz = 4; TNode* t = 0; for (int k = 0; k < exprs->size(); ++k) { TNode* p; ExprNode* e = exprs->exprs[k]; if (ConstNode* t = e->constNode()) { p = iconst(t->intValue() * sz); } else { p = e->translate(g); if (g->debug) { p = jumpge(p, iconst(vec_type->sizes[k]), "__bbVecBoundsEx"); } p = mul(p, iconst(sz)); } sz = sz * vec_type->sizes[k]; t = t ? add(t, p) : p; } return add(t, expr->translate(g)); } ArrayVarNode::ArrayVarNode(const std::string& i, const std::string& t, ExprSeqNode* e) : ident(i), tag(t), exprs(e) {} ArrayVarNode::~ArrayVarNode() { delete exprs; } FieldVarNode::FieldVarNode(ExprNode* e, const std::string& i, const std::string& t) : expr(e), ident(i), tag(t) {} FieldVarNode::~FieldVarNode() { delete expr; }