diff --git a/src/Code Generator/AsmGenerator.cpp b/src/Code Generator/AsmGenerator.cpp index 0f4062e..5905ba0 100644 --- a/src/Code Generator/AsmGenerator.cpp +++ b/src/Code Generator/AsmGenerator.cpp @@ -559,7 +559,12 @@ void AsmGenerator::f_greater_or_equal_operation(string dest_reg,string reg1,stri void AsmGenerator::add_instruction(string instruction) { instruction += "\n"; - (current_stream == MAIN_STREAM) ? main_stream << instruction: functions_stream << instruction; + if (current_stream == MAIN_STREAM) + main_stream << instruction; + if (current_stream == FUNCUTION_STREAM) + functions_stream << instruction; + if (current_stream == TEMP_STEARM) + temp_stream << instruction; } void AsmGenerator::add_data(string data_instruction) @@ -583,7 +588,12 @@ void AsmGenerator::comment(string comment_message) void AsmGenerator::system_call(int system_call_code) { AsmGenerator::li("v0",system_call_code); - (current_stream == MAIN_STREAM) ? main_stream << "syscall\n" : functions_stream << "syscall\n"; + if (current_stream == MAIN_STREAM) + main_stream << "syscall\n"; + if (current_stream == FUNCUTION_STREAM) + functions_stream << "syscall\n"; + if (current_stream == TEMP_STEARM) + temp_stream << "syscall\n"; } void AsmGenerator::sbrk (string amount_reg,string returned_address_memory) @@ -643,26 +653,30 @@ void AsmGenerator::f_move(string dest_reg,string source_reg) void AsmGenerator::function_prologue (int frame_size) { AsmGenerator::comment("Callee Prologue:"); - AsmGenerator::add_instruction("\tsubu $sp, $sp, 8"); + AsmGenerator::add_instruction("\tsubu $sp, $sp, 12"); AsmGenerator::add_instruction("\tsw $fp, 0($sp)"); AsmGenerator::add_instruction("\tsw $ra, 4($sp)"); - AsmGenerator::add_instruction("\taddi $fp, $sp, 8"); + AsmGenerator::add_instruction("\tsw $a3, 8($sp)"); + AsmGenerator::add_instruction("\taddi $fp, $sp, 12"); if (frame_size > 0 ) { AsmGenerator::comment("# Reserve space (" + to_string(frame_size) + "b) for function local vars."); AsmGenerator::add_instruction("\tsubu $sp, $sp, " + to_string(frame_size)); } AsmGenerator::add_instruction(""); + + AsmGenerator::functions_stream << AsmGenerator::temp_stream.rdbuf(); } void AsmGenerator::function_epilogue(int frame_size) { AsmGenerator::comment("Callee Epilogue:"); if (frame_size > 0) { - AsmGenerator::add_instruction("\taddu $fp, $sp, "+to_string(frame_size)); + AsmGenerator::add_instruction("\taddu $sp, $sp, "+to_string(frame_size)); } + AsmGenerator::add_instruction("\tlw $a3, 8($sp)"); AsmGenerator::add_instruction("\tlw $ra, 4($sp)"); AsmGenerator::add_instruction("\tlw $fp, 0($sp)"); - AsmGenerator::add_instruction("\taddu $sp, $sp, 8" ); + AsmGenerator::add_instruction("\taddu $sp, $sp, 12" ); AsmGenerator::add_instruction(""); } @@ -790,6 +804,7 @@ void AsmGenerator::strcpy() ofstream AsmGenerator::assembly_code_file; stringstream AsmGenerator::data_stream; stringstream AsmGenerator::main_stream; +stringstream AsmGenerator::temp_stream; stringstream AsmGenerator::functions_stream; map AsmGenerator::strings_map; diff --git a/src/Code Generator/AsmGenerator.h b/src/Code Generator/AsmGenerator.h index 8f3309f..c9aa45a 100644 --- a/src/Code Generator/AsmGenerator.h +++ b/src/Code Generator/AsmGenerator.h @@ -10,14 +10,16 @@ #define MAIN_STREAM 0 #define FUNCUTION_STREAM 1 +#define TEMP_STEARM 2 //used when generate code for function body (becase we need to know to mush local variables) using namespace std; class AsmGenerator{ -private: +public: static ofstream assembly_code_file; static stringstream data_stream; static stringstream main_stream; + static stringstream temp_stream; static stringstream functions_stream; static int current_stream; diff --git a/src/Code Generator/CodeGeneratorVistor.cpp b/src/Code Generator/CodeGeneratorVistor.cpp index d8a1b73..a0c43ad 100644 --- a/src/Code Generator/CodeGeneratorVistor.cpp +++ b/src/Code Generator/CodeGeneratorVistor.cpp @@ -46,7 +46,8 @@ void CodeGneratorVistor::visit(AssignmentNode *assignmentNode) AsmGenerator::sw(s1,variableAddress); // Store value from rhs in the addresss }else - if (ClassCallNode *classCallNode = dynamic_cast(assignmentNode->lhs)){ + if (ClassCallNode *classCallNode = dynamic_cast(assignmentNode->lhs)) + { string probertyAddress = getClassMemberAddress(classCallNode,s0); AsmGenerator::sw(s1,probertyAddress); }else{ @@ -772,7 +773,7 @@ void CodeGneratorVistor::visit(FunctionDefineNode *functionDefineNode) FunctionFrame* functionFrame = dynamic_cast(currentFrame); - AsmGenerator::function_prologue(functionFrame->stackSize); + AsmGenerator::current_stream = TEMP_STEARM; for(auto &node : functionDefineNode->paramsList->nodes) { @@ -785,6 +786,10 @@ void CodeGneratorVistor::visit(FunctionDefineNode *functionDefineNode) if (functionDefineNode->bodySts) functionDefineNode->bodySts->generate_code(this); + AsmGenerator::current_stream = FUNCUTION_STREAM; + + AsmGenerator::function_prologue(functionFrame->stackSize); + AsmGenerator::add_label(returnLabel); if (functionType->getReturnTypeExpression()->getTypeId() != VOID_TYPE_ID) { @@ -856,162 +861,186 @@ void CodeGneratorVistor::visit(ReturnNode *returnNode) void CodeGneratorVistor::visit(ClassDefineNode *classDefineNode) { - AsmGenerator::comment("(currentFrame); - objectsFrames[classDefineNode->classSymbol->getName()] = objectFrame; - classDefineNode->body->generate_code(this); + TypeClass *typeClass = dynamic_cast(classDefineNode->getNodeType()); + currentFrame = new ObjectFrame(currentFrame,typeClass); - AsmGenerator::comment("ClassDefineNode/>"); + ObjectFrame* objectFrame = dynamic_cast(currentFrame); + + //TODO getName() ?? + objectsFrames[typeClass->getName()] = objectFrame; + + if (classDefineNode->body) + classDefineNode->body->generate_code(this); currentFrame = objectFrame->parentFrame; + + AsmGenerator::comment("Class Define Node/>"); } void CodeGneratorVistor::visit(ClassMemNode *classMemNode) { - ObjectFrame* objectFrame = dynamic_cast(currentFrame); - if (objectFrame != nullptr) - { - objectFrame->addLocal(classMemNode); - }else{ - cout << "CurrentFrame Should be objectFrame" << endl; - } + //TODO generate code for inilizeing string memberName = classMemNode->getMemSymbol()->getName(); AsmGenerator::comment(""); } void CodeGneratorVistor::visit(ClassMethodNode *classMethodNode) { - AsmGenerator::comment("(currentFrame); - if (objectFrame != nullptr){ - objectFrame->addFunction(classMethodNode); + AsmGenerator::comment("(classMethodNode->getNodeType()); - Method *methodSymbol = classMethodNode->methodSym; + Method *methodSymbol = classMethodNode->methodSym; - string methodName = methodSymbol->getName(); - string prevReturnLabel = returnLabel; - returnLabel = methodName+"_ret"; + string methodName = methodSymbol->getLabel(); + string prevReturnLabel = returnLabel; + returnLabel = methodName+"_ret"; - AsmGenerator::comment("Look below to see method "+methodName); + AsmGenerator::comment("Look below to see method "+methodName); - AsmGenerator::initialize_function(methodName); + AsmGenerator::initialize_function(methodName); - currentFrame = new FunctionFrame(currentFrame,nullptr); + currentFrame = new FunctionFrame(currentFrame,classMethodNode->paramsList); + FunctionFrame* methodFrame = dynamic_cast(currentFrame); + + AsmGenerator::current_stream = TEMP_STEARM; - FunctionFrame* functionFrame = dynamic_cast(currentFrame); - AsmGenerator::function_prologue(functionFrame->stackSize); - //TODO - /*for(auto &node : ) - { - ParameterNode* paramterNode = dynamic_cast(node); - if (paramterNode == nullptr) - cout << "DAMN this shoudn't happen" << endl; + for(auto &node : classMethodNode->paramsList->nodes) + { + ParameterNode* paramterNode = dynamic_cast(node); + if (!paramterNode) + cout << "DAMN this shoudn't happen" << endl; + paramterNode->generate_code(this); + } - paramterNode->generate_code(this); - }*/ + if (classMethodNode->bodySts) + classMethodNode->bodySts->generate_code(this); + AsmGenerator::current_stream = FUNCUTION_STREAM; + AsmGenerator::function_prologue(methodFrame->stackSize); - returnLabel = prevReturnLabel; - }else{ - cout << "CurrentFrame Should be objectFrame" << endl; + AsmGenerator::add_label(returnLabel); + + if (functionType->getReturnTypeExpression()->getTypeId() != VOID_TYPE_ID) { + AsmGenerator::comment("Returning Value"); + if (functionType->getReturnTypeExpression()->getTypeId() == FLOAT_TYPE_ID) + AsmGenerator::f_pop("f1"); + else + AsmGenerator::pop("v1"); } - AsmGenerator::comment("ClassMethodNode/>"); + + + AsmGenerator::function_epilogue(methodFrame->stackSize); + + AsmGenerator::write_function(); + + currentFrame = methodFrame->parentFrame; + returnLabel = prevReturnLabel; + + AsmGenerator::comment("Class Method Node/>"); } void CodeGneratorVistor::visit(ClassCallNode *classCallNode) { - AsmGenerator::comment("isMethodCall){ - TypeClass* classType = dynamic_cast(classCallNode->object->getNodeType()); - int propertyTypeID = classType->lookupMembers(classCallNode->propertyString)->getTypeExpr()->getTypeId(); + AsmGenerator::comment("member->getTypeExpr()->getTypeId(); if (propertyTypeID == INTEGER_TYPE_ID || propertyTypeID == BOOLEAN_TYPE_ID){ - AsmGenerator::lw(s0,probertyAddress); - AsmGenerator::push(s0); + AsmGenerator::lw(s1,probertyAddress); + AsmGenerator::push(s1); } if (propertyTypeID == STRING_TYPE_ID){ - AsmGenerator::lw(s0,probertyAddress); - AsmGenerator::push(s0); - + AsmGenerator::lw(s1,probertyAddress); + AsmGenerator::push(s1); } if (propertyTypeID == FLOAT_TYPE_ID){ AsmGenerator::ls("f0",probertyAddress); - AsmGenerator::f_push("f0"); + AsmGenerator::f_push("f0"); } - if (propertyTypeID == CLASS_TYPE_ID){ - AsmGenerator::lw(s0,probertyAddress); - AsmGenerator::push(s0); - } - }else{ - - - } - - AsmGenerator::comment("ClassCallNode/>"); -} - -void CodeGneratorVistor::visit(NewNode *newNode) -{ - AsmGenerator::comment("className) != objectsFrames.end()) { - ObjectFrame *objectsFrame = objectsFrames[newNode->className]; - int objectSize = objectsFrame->membersOffset; - string s0 = "s0",s1 = "s1"; - AsmGenerator::li(s0,objectSize); - AsmGenerator::sbrk(s0,s1); - AsmGenerator::push(s1); + if (propertyTypeID == CLASS_TYPE_ID){ + AsmGenerator::lw(s1,probertyAddress); + AsmGenerator::push(s1); + } + AsmGenerator::comment("Member Property/>"); }else{ - cout << "UnDeclared Class" << endl; - } - AsmGenerator::comment("NewNode/>"); - - -} -string CodeGneratorVistor::getClassMemberAddress(ClassCallNode *classCallNode,string reg) -{ - TypeClass* classType = dynamic_cast(classCallNode->object->getNodeType()); - - if (classType != nullptr){ - string className = classType->getName(); - if (objectsFrames.find(className) != objectsFrames.end()){ - ObjectFrame* objectFrame = objectsFrames[className]; + AsmGenerator::comment("(classCallNode->member->getTypeExpr()); - string propertyOffset = objectFrame->getAddress(classCallNode->propertyString); - string objectAddress = currentFrame->getAddress(classCallNode->object->variable->getNameWithout()); + AsmGenerator::comment("argumentsList) + classCallNode->argumentsList->generate_code(this); + AsmGenerator::comment("ArgumentList/>"); + int arguemtnsSize = classCallNode->argumentsList->nodes.size(); + int parameterSize = functionType->getParamsTEs().size(); + int diffSize = parameterSize - arguemtnsSize; // number of enabeld default parameters - AsmGenerator::lw(reg,objectAddress); //load the addrees of object - string probertyAddress = propertyOffset+"($"+reg+")"; + //Make some space for enabeld default parameters + for(int i = 0 ; i < diffSize ; i++){ + string t0 = "t0"; + //we will store special value -1005 (maybe special) to know that this parameter is default and it's value should be + //taken from function decleration + AsmGenerator::li(t0,-1005); + AsmGenerator::push(t0); + } + string thisReg = "s0"; + string probertyAddress = getClassMemberAddress(classCallNode,thisReg); + AsmGenerator::move("a3",thisReg); + AsmGenerator::lw(s1,probertyAddress); + AsmGenerator::add_instruction("jalr $"+s1); + + if (classCallNode->argumentsList){ + AsmGenerator::comment("argumentsList->nodes){ + //TODO replace fixed size with size from type System + int argSize = 4; + argumentsSize+= argSize; + } + AsmGenerator::add_instruction("addi $sp, $sp, " + to_string(argumentsSize)); + AsmGenerator::comment("Clear Arguments/>"); + } - return probertyAddress; - }else{ - cout << "UnDeclared Class" << endl; - return nullptr; + + if (functionType->getReturnTypeExpression()->getTypeId() != VOID_TYPE_ID){ + if (functionType->getReturnTypeExpression()->getTypeId() == FLOAT_TYPE_ID){ + AsmGenerator::f_push("f1"); + } + else{ + AsmGenerator::push("v1"); + } } - }else{ - cout << "UnDeclared Class" << endl; - return nullptr; + + AsmGenerator::comment("Method Property/>"); } + AsmGenerator::comment("Class Call Node/>"); +} +void CodeGneratorVistor::visit(NewNode *newNode) +{ + AsmGenerator::comment("className]; + objectFrame->newObject(); + AsmGenerator::comment("NewNode/>"); } void CodeGneratorVistor::visit(BreakNode *breakNode) @@ -1026,4 +1055,17 @@ void CodeGneratorVistor::visit(ContinueNode *continueNode) AsmGenerator::comment(""); +} + +string CodeGneratorVistor::getClassMemberAddress(ClassCallNode* classCallNode,string thisReg) +{ + TypeClass *typeClass = dynamic_cast(classCallNode->object->getNodeType()); + + string objectAddress = currentFrame->getAddress(classCallNode->object->variable->getNameWithout()); + + AsmGenerator::lw(thisReg,objectAddress); + + ObjectFrame* objectFrame = objectsFrames[typeClass->getName()]; + objectFrame->thisReg = thisReg; + return objectFrame->getAddress(classCallNode->propertyString); } \ No newline at end of file diff --git a/src/Code Generator/CodeGeneratorVistor.hpp b/src/Code Generator/CodeGeneratorVistor.hpp index 28f6fcc..588a85d 100644 --- a/src/Code Generator/CodeGeneratorVistor.hpp +++ b/src/Code Generator/CodeGeneratorVistor.hpp @@ -19,6 +19,7 @@ class CodeGneratorVistor virtual void generate(ListNode *ast); map objectsFrames; + public: virtual void visit(AssignmentNode *assignmentNode); virtual void visit(BinaryOperationNode *binaryOperationNode); @@ -44,7 +45,6 @@ class CodeGneratorVistor virtual void visit(BreakNode *breakNode); virtual void visit(ContinueNode *continueNode); - - //Helper Method - string getClassMemberAddress(ClassCallNode *,string); + //Helper Methods + string getClassMemberAddress(ClassCallNode*,string); }; diff --git a/src/Code Generator/FunctionFame.cpp b/src/Code Generator/FunctionFame.cpp index 9673e36..454f996 100644 --- a/src/Code Generator/FunctionFame.cpp +++ b/src/Code Generator/FunctionFame.cpp @@ -75,8 +75,8 @@ FunctionFrame::FunctionFrame(GlobalFrame *parent,ListNode *parametersNodes) { paramtersOffset = 0; stackSize = 0; - initialFrameSize = 2*4; // 4 for $fp and 4 for $ra - this->parentFrame = parent; + initialFrameSize = 3*4; // 4 for $fp and 4 for $ra and $a0 + this->parentFrame = parent; if (parametersNodes){ for(auto &node : parametersNodes->nodes) { @@ -97,10 +97,9 @@ void FunctionFrame::addLocal(Node *node) { DeclarationNode* variableDeclarationNode = dynamic_cast(node); int varSize = node->getNodeType()->getSize(); - int variableOffset = -stackSize - initialFrameSize; // offset from frame pointer stackSize += varSize; - locals[variableDeclarationNode->variable->getNameWithout()] = variableOffset; - AsmGenerator::comment(variableDeclarationNode->variable->getNameWithout() + " in function scoop address "+to_string(variableOffset)+" from fp"); + locals[variableDeclarationNode->variable->getNameWithout()] = -stackSize; + AsmGenerator::comment(variableDeclarationNode->variable->getNameWithout() + " in function scoop address "+to_string(-stackSize - initialFrameSize)+" from fp"); } string FunctionFrame::getAddress(string name) @@ -108,7 +107,7 @@ string FunctionFrame::getAddress(string name) if (locals.find(name) != locals.end()) { int offset = locals[name]; - return to_string(offset)+"($fp)"; + return to_string(offset - initialFrameSize)+"($fp)"; } if (arguments.find(name) != arguments.end()) { @@ -126,38 +125,41 @@ string FunctionFrame::getAddress(string name) ObjectFrame::ObjectFrame() { GlobalFrame(); - membersOffset = 0; + this->classType = nullptr; + this->parentFrame = nullptr; + objectsCount = 0; } -ObjectFrame::ObjectFrame(GlobalFrame *parent,ClassDefineNode *cdn) +ObjectFrame::ObjectFrame(GlobalFrame *parent,TypeClass *classType) { GlobalFrame(); - this->parentFrame = parent; - membersOffset = 0; + this->classType = classType; + this->parentFrame = parent; + objectsCount = 0; + classTagAddress = AsmGenerator::store_string_literal(classType->getName()); + fillFrame(classType); } void ObjectFrame::addLocal(Node *node) { - ClassMemNode* classMemNode = dynamic_cast(node); - Variable* variable = classMemNode->getMemSymbol(); - int classMemSize = classMemNode->getNodeType()->getSize(); - locals[variable->getNameWithout()] = membersOffset; - membersOffset += classMemSize; + //ClassMemNode* classMemNode = dynamic_cast(node); + //Variable* variable = classMemNode->getMemSymbol(); + //int classMemSize = classMemNode->getNodeType()->getSize(); + //locals[variable->getNameWithout()] = objectOffset; + //objectOffset = objectOffset + classMemSize; } string ObjectFrame::getAddress(string name) { - if (locals.find(name) != locals.end()) { int offset = locals[name]; - return to_string(offset); - } - if (functions.find(name) != functions.end()) { - int offset = functions[name]; - return to_string(offset); - } + if (thisReg.empty()){ // we are in function + return to_string(offset) + "($a3)"; + } + return to_string(offset) + "($" + thisReg + ")"; + } if (parentFrame) { return parentFrame->getAddress(name); @@ -170,8 +172,71 @@ string ObjectFrame::getAddress(string name) void ObjectFrame::addFunction(Node *node) { - ClassMethodNode* classMethodNode = dynamic_cast(node); - Function* function = classMethodNode->methodSym; - functions[function->getName()] = membersOffset; - membersOffset += 4; + //ClassMethodNode* classMethodNode = dynamic_cast(node); + //Function* function = classMethodNode->methodSym; + //locals[function->getName()] = objectOffset; + //objectOffset = objectOffset + 4; } + +void ObjectFrame::newObject() +{ + string s0 = "s0",s1 = "s1",s2 = "s2"; + + // load the size of oject in $s0 + AsmGenerator::li(s0,classType->getSize()); + + //syscall to allocate space for object, the address of new allocated memory $s1 (address of object) + AsmGenerator::sbrk(s0,s1); + + // push the address into stack + AsmGenerator::push(s1); + + AsmGenerator::comment("getMembers()) + { + if (memberWrapper->getWrapperType() == MemberWrapper::PROPERTY_WRAPPER) + { + PropertyWrapper* propertyWrapper = dynamic_cast(memberWrapper); + } + + if (memberWrapper->getWrapperType() == MemberWrapper::METHOD_WRAPPER){ + MethodWrapper* methodWrapper = dynamic_cast(memberWrapper); + + int methodOffset = locals[methodWrapper->getName()]; + string methodLabel = methodWrapper->getLabel(); + string methodAddress = to_string(methodOffset)+"($" + s1 + ")"; // address in object + + AsmGenerator::la(s2,methodLabel); //load the address of method + AsmGenerator::sw(s2,methodAddress); //store the address of method in object + } + } + AsmGenerator::comment("Fill Functions Table/>"); +} + + +void ObjectFrame::fillFrame(TypeClass* typeClass) +{ + int memberOffset = 0; + for(auto &memberWrapper :classType->getMembers()) + { + if (memberWrapper->getWrapperType() == MemberWrapper::PROPERTY_WRAPPER) + { + PropertyWrapper* propertyWrapper = dynamic_cast(memberWrapper); + + string propertyName = propertyWrapper->getUniqueName(); // TODO replace getUniqueName with !! + int propertySize = propertyWrapper->getSize(); + locals[propertyName] = memberOffset; + memberOffset = memberOffset + propertySize; + } + + if (memberWrapper->getWrapperType() == MemberWrapper::METHOD_WRAPPER) + { + MethodWrapper* methodWrapper = dynamic_cast(memberWrapper); + + string propertyName = methodWrapper->getName(); + locals[propertyName] = memberOffset; + memberOffset = memberOffset + 4; + + } + } +} \ No newline at end of file diff --git a/src/Code Generator/FunctionFrame.hpp b/src/Code Generator/FunctionFrame.hpp index 8a134d9..8346cea 100644 --- a/src/Code Generator/FunctionFrame.hpp +++ b/src/Code Generator/FunctionFrame.hpp @@ -6,6 +6,7 @@ #include "../AST/ClassDefineNode.hpp" #include "../SymbolTable/Symbol.h" #include "../AST/FunctionDefineNode.hpp" +#include "../TypeSystem/TypeClass.hpp" class GlobalFrame { @@ -49,7 +50,7 @@ class ObjectFrame : public GlobalFrame public: ObjectFrame(); - ObjectFrame(GlobalFrame *,ClassDefineNode *); + ObjectFrame(GlobalFrame *,TypeClass *); virtual void addLocal(Node *); @@ -57,9 +58,17 @@ class ObjectFrame : public GlobalFrame virtual string getAddress(string); - map functions; + virtual void newObject(); - int membersOffset; + virtual void fillFrame(TypeClass*); + + int objectsCount; + + string classTagAddress; + + TypeClass *classType; + + string thisReg; }; diff --git a/src/main.cpp b/src/main.cpp index aea8675..83c5bf6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "Code Generator/AsmGenerator.h" #include "Code Generator\CodeGeneratorVistor.hpp" #include "Code Generator\OptimizationVistor.hpp" +#include "TypeSystem\TypesTable.h" #include #include @@ -58,6 +59,8 @@ int main(int argc, char** argv) { symbolsParser->printSymbolTables(); cout << "printSymbolTables\n"; errorRec.printErrQueue(); cout << "printErrQueue\n"; + TypesTable::buildObjectClass(); + //Check AST types tree->type_checking(); cout << "TypeChecking Pass\n"; @@ -81,14 +84,7 @@ int main(int argc, char** argv) { system("QtSpim.exe -a ./src/\"Code Generator\"/mips1.asm"); } - - cout << "compilation done" << endl; - - - Node *node = nullptr; - - return 0; }