void BinOpNode::generateLvalue(AsmCode& code){ string value = token->Value; if (value == "+"){ SymbolType *type = left->getType(); if (dynamic_cast<ArraySymbol*>(type)) left->generateLvalue(code); else if (dynamic_cast<PointerSymbol*>(type)) left->generate(code); SymbolType *t = type->upType(); right->generate(code); code.add(_POP, _EAX) .add(_MOV, _EBX, to_string(t->byteSize())) .add(_IMUL, _EAX, _EBX) .add(_POP, _EBX) .add(_ADD, _EAX, _EBX) .add(_PUSH, _EAX); t = t->upType(); } else if (isAssing(token)){ generate(code); code.add(_POP, _EAX); left->generateLvalue(code); } else throw MyException("Compiler error"); }
void Block::generate(AsmCode &code){ for(int i = 0; i < size(); i++){ body[i]->generate(code); if(body[i]->isExpression()){ SymbolType *type = body[i]->getType(); if(type && type->byteSize()) code.add(_POP, _EAX); } } }
void CSubroutine::emitPUSHMn( const string &symbol, const bool &pushType ) { SymbolType symbolType = _symbolTable->getSymbol( getName( ), symbol, true ).getType( ); _body.writeln( string("push ") + symbol ); if (pushType) { _body.writeln( string("push_") + symbolType.toAsmType( ) ); } }
bool ExpressionValue::isCompatibleWidth(SymbolType& other) const { if(!matchesType(other.isPrimitive())) { return false; } else if(!matchesDimensions(other.dimensions())) { return false; } else if(!matchesPrimitiveType(other.primitiveType())) { return false; } return true; }
void Parser :: CheckReturn(FuncSymbol *func ){ ReturnStatement *ret = nullptr; SymbolType *real_type = func->value->getType(); int size = func->body->body.size(); for(int i = 0; i < size && !ret; i++) ret = dynamic_cast<ReturnStatement*>(func->body->body[i]); if(!ret || !ret->value ){ errorIf((func->name != "main" && real_type->name != "void") , "Wrong return type", scan.Get()); return; } SymbolType *a = ret->value->getType(); errorIf(!a->canConvertTo(real_type), "Wrong return type", scan.Get()); }
SymbolType* FuncCallNode::getType(){ if(nodeType) return nodeType; FuncSymbol* sym = dynamic_cast<FuncSymbol*>(symbol); int formalParametersCount = sym->params->size(); int realParametersCount = args.size(); if (formalParametersCount != realParametersCount) throw MyException("Incorrect parameters count", token); for (int i = 0; i < formalParametersCount; i++) { SymbolType* realParamType = args[i]->getType(); SymbolType* formalParamType = sym->params->sym_ptr[i]->getType(); if (!realParamType->canConvertTo(formalParamType)) throw MyException("Invalid type of parameter", args[i]->token); args[i] = makeTypeCoerce(args[i], realParamType, formalParamType); } return symbol->getType(); }
SymbolType *ArrNode::getType() { if(nodeType) return nodeType; ArraySymbol *sym = dynamic_cast<ArraySymbol*>(name->getType()); if(!sym) throw MyException("Expression must be a pointer type", token); SymbolType *type = sym; for(int i = 0; i < args.size(); i++){ type = type->upType(); if(type == 0) throw MyException("Expression must be a pointer type", args[i]->token); if(!args[i]->getType()->canConvertTo(IntType)) throw MyException("Expression must have integral type", args[i]->token); args[i] = makeTypeCoerce(args[i], args[i]->getType(), IntType); } nodeType = type; return type; }
void ArrNode::generateLvalue(AsmCode &code){ SymbolType *type = name->getType(); if(dynamic_cast<ArraySymbol*>(type)) name->generateLvalue(code); else if(dynamic_cast<PointerSymbol*>(type)) name->generate(code); SymbolType *t = type->upType(); for(int i = 0; i < args.size(); i++){ args[i]->generate(code); code.add(_POP, _EAX) .add(_MOV, _EBX, to_string(t->byteSize())) .add(_IMUL, _EAX, _EBX) .add(_POP, _EBX) .add(_ADD, _EAX, _EBX) .add(_PUSH, _EAX); t = t->upType(); } }
void SemanticEval::evaluateReturnCmd(ExpressionValue& ev, int line) { if(currentScope == SymbolTable::GlobalScope) { //tentando retornar no bloco principal ErrorHandler::self()->add("Bloco principal não deve ter retorno", line); } else { //currentScope eh o nome da funcao atual try { SymbolType sctype = stable.getSymbol(SymbolTable::GlobalScope, currentScope).type; if(!ev.isCompatibleWidth(sctype)) { stringstream msg; msg << "Expressão de retorno deve ser compatível com o tipo \"" << sctype.toString() << "\""; ErrorHandler::self()->add(msg.str(), line); } //else ok! } catch(SymbolTableException& e) { cerr << "Erro interno: SemanticEval::evaluateReturnCmd exception\n"; } } }
SymbolType *UnaryOpNode::getType(){ if(nodeType) return nodeType; SymbolType *type = operand->getType(); Values operation = token->value; switch(operation){ case factor: if(!dynamic_cast<PointerSymbol*>(type)) throw MyException("Type of unary operation is not a pointer", token); nodeType = dynamic_cast<PointerSymbol*>(type)->pointer; return nodeType; case b_and: if(!operand->isLvalue()) throw MyException("Expression must be a modifiable lvalue", token->line, token->start); nodeType = new PointerSymbol(type); return nodeType; case b_not: operand = makeTypeCoerce(operand, type, IntType); break; case l_not: if(dynamic_cast<StructSymbol*>(type)) throw MyException("No operator \"!\" matches these operands operand types are: !" + type->name, token); break; case incr: case decr: if(!operand->isModifiableLvalue()) throw MyException("Expression must be a modifiable lvalue", token); break; case Values::minus: if(!type->canConvertTo(FloatType)) throw MyException("Expression must have arithmetical type", token); } nodeType = type; return type; }
ExprNode* Parser :: ParseMember(ExprNode* left){ SymbolType *type = left->getType(); if ( dynamic_cast<TypedefSymbol*>(type)) type = type->getType(); StructSymbol *struct_type = 0; if(dynamic_cast<PointerSymbol*>(type)) struct_type = dynamic_cast<StructSymbol*>(dynamic_cast<PointerSymbol*>(type)->pointer); else struct_type = dynamic_cast<StructSymbol*>(type); errorIf(!struct_type, "Left operand of . or -> must be a structure", scan.Get()); Token* opTok = scan.Get(); Token* token =scan.GetNext(); errorIf(token->Type != _IDENTIFIER , "Right operand of . or -> must be a identifier", token); string fieldName = token->Value; if (!struct_type->m_fields->exists(fieldName)) fieldName = '%' + fieldName; errorIf(!struct_type->m_fields->exists(fieldName), "Undefined field in structure",token); scan.Next(); ExprNode* right = new IdentifierNode(token, dynamic_cast<VarSymbol*>(struct_type->m_fields->find_symbol(fieldName))); return new BinOpNode(opTok, left, right); }
bool ArrNode::isModifiableLvalue() const { SymbolType *type = name->getType(); for(int i = 0; i < args.size(); i++) type = type->upType(); return type->isModifiableLvalue(); }
SymbolType *BinaryOpNode::getType(){ if(nodeType) return nodeType; SymbolType *leftType = left->getType(); SymbolType *rightType = right->getType(); if(rightType == VoidType) throw MyException("Type casting error", token); Values operation = token->value; SymbolType *maxType = 0; if(operationTypeOperands.count(operation)) maxType = operationTypeOperands[operation]; else maxType = typePriority[leftType] > typePriority[rightType] ? leftType : rightType; PointerSymbol *l_pointer = dynamic_cast<PointerSymbol*>(leftType); PointerSymbol *r_pointer= dynamic_cast<PointerSymbol*>(rightType); ArraySymbol *l_array = dynamic_cast<ArraySymbol*>(leftType); ArraySymbol *r_array = dynamic_cast<ArraySymbol*>(rightType); switch(operation){ case per_eql: case or_eql: case and_eql: case xor_eql: case sr_eql: case sl_eql: if(!leftType->canConvertTo(IntType) || !rightType->canConvertTo(IntType)) throw MyException("Expression must have integral type", token); case assign: if(leftType->isStruct() && *leftType == rightType){ nodeType = leftType; return leftType; } case pl_eql: case mn_eql: case fct_eql: case div_eql: if(!left->isModifiableLvalue()) throw MyException("Expression must be a modifiable lvalue", token); right = makeTypeCoerce(right, rightType, leftType); nodeType = rightType; return rightType; case point: if(!dynamic_cast<StructSymbol*>(leftType)) throw MyException("Left operand of . must be a structure", token); nodeType = rightType; return rightType; case arrow: if(!l_pointer || !dynamic_cast<StructSymbol*>(l_pointer->upType())) throw MyException("Left operand of -> must be of pointer-to-structure type", left->token); nodeType = rightType; return rightType; case Values::minus: if(l_pointer && r_pointer || l_array && r_array){ if( l_pointer && r_pointer && (*l_pointer->pointer != r_pointer->pointer) || l_array && r_array && (*l_array->type != r_array->type)) throw MyException("Operand types are incompatible", token); nodeType = IntType; return IntType; } case Values::plus: if(l_pointer && r_pointer || l_array && r_array) throw MyException("Can't add two pointers"); if(l_pointer || r_pointer) return l_pointer == 0 ? r_pointer : l_pointer; if(l_array || r_array){ nodeType = new PointerSymbol(l_array == 0 ? r_array->type : l_array->type); return nodeType; } default: if(leftType->isStruct() || rightType->isStruct()) throw MyException("Can't perform operation over two structures", token); if(typePriority[maxType] < max(typePriority[leftType], typePriority[rightType])) throw MyException("Invalid type of operands", token); left = makeTypeCoerce(left, leftType, maxType); right = makeTypeCoerce(right, rightType, maxType); if (operationReturningType.count(operation)){ nodeType = operationReturningType[operation]; return nodeType; } else{ nodeType = maxType; return maxType; } } }
void BinOpNode::generate(AsmCode & code) { SymbolType * leftType = left->getType(); SymbolType * rightType = right->getType(); ArraySymbol* leftTypeArray = dynamic_cast<ArraySymbol *>(leftType); ArraySymbol* rightTypeArray = dynamic_cast<ArraySymbol *>(rightType); PointerSymbol* leftTypePointer = dynamic_cast<PointerSymbol *>(leftType); PointerSymbol* rightTypePointer = dynamic_cast<PointerSymbol *>(rightType); if (isAssing(token)) { left->generateLvalue(code); right->generate(code); } else { left->generate(code); right->generate(code); } if (token->Value == "+"){ if (leftTypePointer || rightTypeArray || leftTypeArray || rightTypePointer) { int shift; if (leftTypeArray) shift = leftTypeArray->getType()->offset; if (rightTypeArray) shift = rightTypeArray->getType()->offset; if (leftTypePointer) shift = leftTypePointer->getType()->offset; if (rightTypePointer) shift = rightTypePointer->getType()->offset; if (leftTypePointer) generateOperationPointer(code, _ADD, shift, false); else generateOperationPointer(code, _ADD, shift, true); } generateOperation(code, _ADD); } else if (token->Value == "-"){ if (leftTypePointer || rightTypeArray || leftTypeArray || rightTypePointer) { int shift; if (leftTypeArray) shift = leftTypeArray->getType()->offset; if (rightTypeArray) shift = rightTypeArray->getType()->offset; if (leftTypePointer) shift = leftTypePointer->getType()->offset; if (rightTypePointer) shift = rightTypePointer->getType()->offset; if (leftTypePointer && !rightTypePointer) generateOperationPointer(code, _SUB, shift, false); } generateOperation(code, _SUB); } else if (token->Value == "*"){ generateOperation(code, _IMUL); } else if (token->Value == "/"){ generateOperation(code, _IDIV); } else if (token->Value == "%"){ generateOperation(code, _IDIV, _EDX); } else if (token->Value == "&"){ generateOperation(code, _AND); } else if (token->Value == "|"){ generateOperation(code, _OR); } else if (token->Value == "^"){ generateOperation(code, _XOR); } else if (token->Value == "<<"){ generateOperationShift(code, _SHL); } else if (token->Value == ">>"){ generateOperationShift(code, _SHR); } else if (token->Value == "=="){ generateCmp(code, _SETE); } else if (token->Value == ">="){ generateCmp(code, _SETGE); } else if (token->Value == "<="){ generateCmp(code, _SETLE); } else if (token->Value == "!="){ generateCmp(code, _SETNE); } else if (token->Value == ">"){ generateCmp(code, _SETG); } else if (token->Value == "<"){ generateCmp(code, _SETL); } else if (token->Value == "&&"){ generateOperationLogic(code, _AND); } else if (token->Value == "||"){ generateOperationLogic(code, _OR); } else if (token->Value == "="){ code.add(_POP, _EBX) .add(_POP, _EAX); if (!(leftTypePointer || leftTypeArray) && leftType->getType() == CharType) { code.add(_MOV, new AsmIndirectArg(_EAX), new AsmRegArg(_BL)) .add(_XOR, _EBX, _EBX) .add(_MOV, new AsmRegArg(_BL), new AsmIndirectArg(_EAX)) .add(_PUSH, new AsmRegArg(_EAX)); } else { code.add(_MOV, new AsmIndirectArg(_EAX), new AsmRegArg(_EBX)); } code.add(_PUSH, _EBX); } else if (token->Value == "+="){ if ((leftTypePointer || leftTypeArray)) { int shift; if (leftTypeArray) shift = leftTypeArray->getType()->offset; if (rightTypeArray) shift = rightTypeArray->getType()->offset; if (leftTypePointer) shift = leftTypePointer->getType()->offset; if (rightTypePointer) shift = rightTypePointer->getType()->offset; generateOperationPointer(code, _ADD, shift, false); } generateOperationAssing(leftType, code, _ADD); } else if (token->Value == "-="){ generateOperationAssing(leftType, code, _SUB); } else if (token->Value == "*="){ generateOperationAssing(leftType, code, _IMUL); } else if (token->Value == "/="){ generateOperationAssing(leftType, code, _IDIV); } else if (token->Value == "%="){ generateOperationAssing(leftType, code, _IDIV, _EDX); } else if (token->Value == "&="){ generateOperationAssing(leftType, code, _AND); } else if (token->Value == "|="){ generateOperationAssing(leftType, code, _OR); } else if (token->Value == "^="){ generateOperationAssing(leftType, code, _XOR); } else if (token->Value == ","){ code.add(_POP, _EAX) .add(_POP, _EBX) .add(_PUSH, _EAX); } }
void ExpressionValue::set(SymbolType& s) { _isPrimitive = s.isPrimitive(); _primitiveType = s.primitiveType(); _dimensions = s.dimensions(); }