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 ;
}
Exemple #2
0
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);
}
Exemple #3
0
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);
}
Exemple #4
0
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++;
      }
    }
  }
}
Exemple #5
0
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++);
}
Exemple #6
0
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);
}
Exemple #7
0
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;
}