string CBackendx86::Operand(const CTac *op) { string operand; // TODO // return a string representing op // hint: take special care of references (op of type CTacReference) std::stringstream buffer ; buffer << op ; CScope *cs = GetScope(); CSymtab *st = cs->GetSymbolTable(); vector<CSymbol*> slist = st->GetSymbols(); vector< CSymbol * > symbols = st->GetSymbols() ; //CTacName if (st->FindSymbol(buffer.str()) != NULL){ operand = buffer.str() ; } //CTacConstant else if (buffer.str()[0] > 47 && buffer.str()[0] < 58){ operand = Imm(atoi(buffer.str().c_str())) ; } //CTacReference else { } return operand ; }
CAstDesignator* CParser::ident(CAstScope *s) { // // ident ::= letter { letter | digit }. // CToken t; Consume(tIdent, &t); CSymtab *symtab = s->GetSymbolTable(); const CSymbol *symbol = symtab->FindSymbol(t.GetValue(), sLocal); if (!symbol) symbol = symtab->FindSymbol(t.GetValue(), sGlobal); if (!symbol) SetError(t, "undeclared variable \"" + t.GetValue() + "\""); return new CAstDesignator(t, symbol); }
CAstStatCall* CParser::subroutineCall(CAstScope *s, CToken ident) { // // subroutineCall ::= ident "(" [ expression {"," expression} ] ")". // CToken t; Consume(tLBrak); CSymtab *symtab = s->GetSymbolTable(); CAstFunctionCall *call = NULL; // Check undefined procedure/function call. if(symtab->FindSymbol(ident.GetValue(), sLocal) == NULL && symtab->FindSymbol(ident.GetValue(), sGlobal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(ident.GetValue(), sGlobal)) == NULL) SetError(ident, "invalid procedure/function identifier."); call = new CAstFunctionCall(ident, dynamic_cast<const CSymProc *>(symtab->FindSymbol(ident.GetValue(), sGlobal))); } else if(symtab->FindSymbol(ident.GetValue(), sLocal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(ident.GetValue(), sLocal)) == NULL) SetError(ident, "invalid procedure/function identifier."); call = new CAstFunctionCall(ident, dynamic_cast<const CSymProc *>(symtab->FindSymbol(ident.GetValue(), sLocal))); } else SetError(ident, "undefined identifier."); // Add expressions. if(isExpr(_scanner->Peek())) { CAstExpression *expr = expression(s); assert(expr != NULL); // Arrays are addressed. if(expr->GetType()->IsArray()) expr = new CAstSpecialOp(expr->GetToken(), opAddress, expr, NULL); call->AddArg(expr); while(_scanner->Peek().GetType() == tComma) { Consume(tComma); expr = expression(s); assert(expr != NULL); // Arrays are addressed. if(expr->GetType()->IsArray()) expr = new CAstSpecialOp(expr->GetToken(), opAddress, expr, NULL); call->AddArg(expr); } } Consume(tRBrak); return new CAstStatCall(ident, call); }
void CBackendx86::EmitLocalData(CScope *scope) // initializes array's meta-data { assert(scope != NULL); CSymtab* symtab = scope->GetSymbolTable(); vector<CSymbol*> slist = symtab->GetSymbols(); vector<CSymbol*>::iterator it; for(it = slist.begin(); it != slist.end(); it++) { const CArrayType* typ = dynamic_cast<const CArrayType*>((*it)->GetDataType()); if(typ != NULL && (*it)->GetSymbolType() == stLocal && (dynamic_cast<CSymParam*>(*it) == NULL)) { // just initialize the arrays that are local and are not param int offset = (*it)->GetOffset(); string base = (*it)->GetBaseRegister(); int dim = typ->GetNDim(); stringstream ss, ss2; ss << "$" << dim << "," << offset << "(" << base << ")"; ss2 << "local array '" << (*it)->GetName() << "': " << dim << " dimensions"; EmitInstruction("movl", ss.str(), ss2.str()); // store the dimension meta-data int dimcount = 1; while(typ != NULL) { stringstream ss, ss2; offset += 4; int n = typ->GetNElem(); ss << "$" << n << "," << offset << "(" << base << ")"; ss2 << " dimension " << dimcount << ": " << n << " elements"; EmitInstruction("movl", ss.str(), ss2.str()); // store the meta-data of length of each dimension typ = dynamic_cast<const CArrayType*>(typ->GetInnerType()); dim++; dimcount++; } } } }
void CBackendx86::EmitGlobalData(CScope *scope) { assert(scope != NULL); // emit the globals for the current scope CSymtab *st = scope->GetSymbolTable(); assert(st != NULL); bool header = false; vector<CSymbol*> slist = st->GetSymbols(); _out << dec; size_t size = 0; for (size_t i=0; i<slist.size(); i++) { CSymbol *s = slist[i]; const CType *t = s->GetDataType(); if (s->GetSymbolType() == stGlobal) { if (!header) { _out << _ind << "# scope: " << scope->GetName() << endl; header = true; } // insert alignment only when necessary if ((t->GetAlign() > 1) && (size % t->GetAlign() != 0)) { size += t->GetAlign() - size % t->GetAlign(); _out << setw(4) << " " << ".align " << right << setw(3) << t->GetAlign() << endl; } _out << left << setw(36) << s->GetName() + ":" << "# " << t << endl; if (t->IsArray()) { const CArrayType *a = dynamic_cast<const CArrayType*>(t); assert(a != NULL); int dim = a->GetNDim(); _out << setw(4) << " " << ".long " << right << setw(4) << dim << endl; for (int d=0; d<dim; d++) { assert(a != NULL); _out << setw(4) << " " << ".long " << right << setw(4) << a->GetNElem() << endl; a = dynamic_cast<const CArrayType*>(a->GetInnerType()); } } const CDataInitializer *di = s->GetData(); if (di != NULL) { const CDataInitString *sdi = dynamic_cast<const CDataInitString*>(di); assert(sdi != NULL); // only support string data initializers for now _out << left << setw(4) << " " << ".asciz " << '"' << sdi->GetData() << '"' << endl; } else { _out << left << setw(4) << " " << ".skip " << dec << right << setw(4) << t->GetDataSize() << endl; } size += t->GetSize(); } } _out << endl; // emit globals in subscopes (necessary if we support static local variables) vector<CScope*>::const_iterator sit = scope->GetSubscopes().begin(); while (sit != scope->GetSubscopes().end()) EmitGlobalData(*sit++); }
CAstStatAssign* CParser::assignment(CAstScope *s, CToken ident) { // // assignment ::= qualident ":=" expression. // qualident ::= ident { "[" expression "]" }. // CToken t; CAstDesignator *lhs = NULL; CSymtab *symtab = s->GetSymbolTable(); if(_scanner->Peek().GetType() == tAssign) { // non-array case. const CSymbol *tmpsym = symtab->FindSymbol(ident.GetValue(), sLocal); if(tmpsym == NULL && symtab->FindSymbol(ident.GetValue(), sGlobal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(ident.GetValue(), sGlobal)) != NULL) { SetError(ident, "designator expected."); } lhs = new CAstDesignator(ident, symtab->FindSymbol(ident.GetValue(), sGlobal)); } else if(tmpsym != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(tmpsym) != NULL) { SetError(ident, "designator expected."); } lhs = new CAstDesignator(ident, symtab->FindSymbol(ident.GetValue(), sLocal)); } else SetError(ident, "undefined identifier."); assert(lhs != NULL); } else if(_scanner->Peek().GetType() == tLSBrak) { // array case. const CSymbol *tmpsym = symtab->FindSymbol(ident.GetValue(), sLocal); CAstArrayDesignator *arraylhs; if(tmpsym == NULL && symtab->FindSymbol(ident.GetValue(), sGlobal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(ident.GetValue(), sGlobal)) != NULL) { SetError(ident, "designator expected."); } arraylhs = new CAstArrayDesignator(ident, symtab->FindSymbol(ident.GetValue(), sGlobal)); } else if(tmpsym != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(tmpsym) != NULL) { SetError(ident, "designator expected."); } arraylhs = new CAstArrayDesignator(ident, symtab->FindSymbol(ident.GetValue(), sLocal)); } else SetError(ident, "undefined identifier."); // multiple index. while(_scanner->Peek().GetType() == tLSBrak) { Consume(tLSBrak); CAstExpression *expr = expression(s); assert(expr != NULL); arraylhs->AddIndex(expr); Consume(tRSBrak); } arraylhs->IndicesComplete(); lhs = dynamic_cast<CAstDesignator *>(arraylhs); assert(lhs != NULL); } CToken k; Consume(tAssign, &k); CAstExpression *rhs = expression(s); assert(rhs != NULL); return new CAstStatAssign(k, lhs, rhs); }
CAstExpression* CParser::factor(CAstScope *s) { // // factor ::= qualident | number | boolean | char | string | "(" expression ")" | subroutineCall | "!" factor. // FIRST(factor) = { tIdent, tNumber, tTrue, tFalse, tCharacter, tString, tLBrak, tEMark }. // CToken t; EToken tt = _scanner->Peek().GetType(); CTypeManager *tm = CTypeManager::Get(); CAstExpression *n = NULL; CSymtab *symtab = s->GetSymbolTable(); switch(tt) { case tTrue: Consume(tTrue, &t); n = new CAstConstant(t, tm->GetBool(), 1); break; case tFalse: Consume(tFalse, &t); n = new CAstConstant(t, tm->GetBool(), 0); break; case tNumber: { Consume(tNumber, &t); errno = 0; long long v = strtoll(t.GetValue().c_str(), NULL, 10); if (errno != 0) SetError(t, "invalid number."); // integer range validation check. if(v > 2147483648) SetError(t, "integer constant outside valid range."); n = new CAstConstant(t, tm->GetInt(), v); break; } case tIdent: { Consume(tIdent, &t); if(_scanner->Peek().GetType() == tLBrak) { // subroutineCall Consume(tLBrak); CAstFunctionCall *f; // If subroutineCall calls undefined procedure/function, then set error. if(symtab->FindSymbol(t.GetValue(),sLocal) == NULL && symtab->FindSymbol(t.GetValue(), sGlobal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal)) == NULL) SetError(t, "invalid procedure/function identifier."); f = new CAstFunctionCall(t, dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal))); } else if(symtab->FindSymbol(t.GetValue(), sLocal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal)) == NULL) SetError(t, "invalid procedure/function identifier."); f = new CAstFunctionCall(t, dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal))); } else SetError(t, "undefined identifier."); assert(f != NULL); if(isExpr(_scanner->Peek())) { CAstExpression *expr = expression(s); assert(expr != NULL); // If array, then addressed. if(expr->GetType()->IsArray()) expr = new CAstSpecialOp(expr->GetToken(), opAddress, expr, NULL); f->AddArg(expr); while(_scanner->Peek().GetType() == tComma) { Consume(tComma); expr = expression(s); assert(expr != NULL); // If array, then addressed. if(expr->GetType()->IsArray()) expr = new CAstSpecialOp(expr->GetToken(), opAddress, expr, NULL); f->AddArg(expr); } } Consume(tRBrak); n = f; } else { // qualident if(_scanner->Peek().GetType() == tLSBrak) { // It means array CAstArrayDesignator *f; if(symtab->FindSymbol(t.GetValue(), sLocal) == NULL && symtab->FindSymbol(t.GetValue(), sGlobal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal)) != NULL) SetError(t, "designator expected."); f = new CAstArrayDesignator(t, symtab->FindSymbol(t.GetValue(), sGlobal)); } else if(symtab->FindSymbol(t.GetValue(), sLocal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal)) != NULL) SetError(t, "designator expected"); f = new CAstArrayDesignator(t, symtab->FindSymbol(t.GetValue(), sLocal)); } else { SetError(t, "undefined identifier."); } while(_scanner->Peek().GetType() == tLSBrak) { Consume(tLSBrak); CAstExpression *expr = expression(s); assert(expr != NULL); f->AddIndex(expr); Consume(tRSBrak); } f->IndicesComplete(); n = f; } // non-array case. else { if(symtab->FindSymbol(t.GetValue(), sLocal) == NULL && symtab->FindSymbol(t.GetValue(), sGlobal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal)) != NULL) { SetError(t, "designator expected."); } n = new CAstDesignator(t, symtab->FindSymbol(t.GetValue(), sGlobal)); } else if(symtab->FindSymbol(t.GetValue(), sLocal) != NULL) { // Check if symbol is procedure. if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal)) != NULL) { SetError(t, "designator expected."); } n = new CAstDesignator(t, symtab->FindSymbol(t.GetValue(), sLocal)); } else SetError(t, "undefined identifier."); } } break; } case tString: Consume(tString, &t); n = new CAstStringConstant(t, t.GetValue(), s); break; case tCharacter: { Consume(tCharacter, &t); char res; // If character length is 0, it means character is '\0' because invalid character cases are handled in scanner. if(t.GetValue().length() == 0) res = '\0'; else if(t.GetValue().length() == 1) { if(t.GetValue().at(0) != '\\') res = t.GetValue().at(0); else SetError(t, "wrong character"); } // unescape. else if(t.GetValue().length() == 2) { if(t.GetValue().at(0) == '\\') { if(t.GetValue().at(1) == 'n') { res = '\n'; } else if(t.GetValue().at(1) == 't') { res = '\t'; } else if(t.GetValue().at(1) == '"') { res = '"'; } else if(t.GetValue().at(1) == '\'') { res = '\''; } else if(t.GetValue().at(1) == '\\') { res = '\\'; } else if(t.GetValue().at(1) == '0') { res = '\0'; } else SetError(t, "wrong character"); } } else SetError(t, "wrong character"); n = new CAstConstant(t, tm->GetChar(), (long long)res); break; } case tLBrak: Consume(tLBrak); n = expression(s); Consume(tRBrak); break; case tEMark: Consume(tEMark, &t); n = new CAstUnaryOp(t, opNot, factor(s)); break; default: // cout << "got " << _scanner->Peek() << endl; SetError(_scanner->Peek(), "factor expected."); break; } return n; }