//===================================================================================================================== void visitAssignment(Assignment *p) { fprintf(m_outputfile, "#### ASSIGN\n"); // Visit the children p->visit_children(this); // Look up variable offset in offset table OffsetTable* table = currMethodOffset; bool inClass = false; const char* name = dynamic_cast<VariableIDImpl*>(p->m_variableid)->m_symname->spelling(); if(!table->exist(name)) {table = currClassOffset; inClass = true;} assert(table->exist(name)); int offset = table->get_offset(name); // Pop from stack and save to either stack or heap if(!inClass) { fprintf(m_outputfile, " popl %%eax\n"); fprintf(m_outputfile, " movl %%eax, %i(%%ebp)\n", offset); } else { fprintf(m_outputfile, " popl %%eax\n"); fprintf(m_outputfile, " movl 8(%%ebp), %%ebx\n"); fprintf(m_outputfile, " movl %%eax, %i(%%ebx)\n", offset); } fprintf(m_outputfile, "####\n"); }
//===================================================================================================================== void visitMethodImpl(MethodImpl *p) { inMethod = true; fprintf(m_outputfile, "######## METHOD\n"); // Create function label from class name and method name const char* funcname = dynamic_cast<MethodIDImpl*>(p->m_methodid)->m_symname->spelling(); fprintf(m_outputfile, "%s_%s:\n", currClassName, funcname); // Prologue - Push old ebp to stack, update ebp to current stack pointer fprintf(m_outputfile, " pushl %%ebp\n"); fprintf(m_outputfile, " movl %%esp, %%ebp\n"); // Set offset tables assert(m_classtable->exist(currClassName)); ClassNode* node = m_classtable->lookup(currClassName); currClassOffset = node->offset; currMethodOffset = new OffsetTable(); currMethodOffset->setTotalSize(4); // make space in table for %ebp // Add function to classnode's scope node->scope->insert(funcname, new Symbol()); assert(node->scope->exist(funcname)); // Iterate through parameters, saving to offset table list<Parameter_ptr> *l = p->m_parameter_list; list<Parameter_ptr>::iterator it; OffsetTable* table = currMethodOffset; ParameterImpl* param; Parameter_ptr ptr; int varSize = 4; int curroffset = 12; // leave space for return address and the 'this object' pointer for(it=l->begin(); it!=l->end(); ++it) { ptr = (Parameter_ptr)*it; param = dynamic_cast<ParameterImpl*> (ptr); table->insert(dynamic_cast<VariableIDImpl*>(param->m_variableid)->m_symname->spelling(), curroffset, varSize, param->m_type->m_attribute.m_type.classType); curroffset += varSize; } // Visit the children p->visit_children(this); // Epilogue - deallocate locals, set ebp to old ebp, return curroffset = currMethodOffset->getTotalSize(); fprintf(m_outputfile, " addl $%i, %%esp\n", curroffset-4); // everything but old ebp fprintf( m_outputfile," leave\n"); fprintf( m_outputfile," ret\n"); fprintf(m_outputfile, "########\n"); // Dereference the local offset table currMethodOffset == NULL; inMethod = false; }
//===================================================================================================================== void visitDeclarationImpl(DeclarationImpl *p) { fprintf(m_outputfile, "#### DECLARATION\n"); // Visit the children p->visit_children(this); // Get type and decide on allocated size Basetype type = p->m_type->m_attribute.m_type.baseType; assert(type == bt_boolean || type == bt_integer || type == bt_object); int varSize = 4; // Iterate through list of variables, allocating and inserting into offset table list<VariableID_ptr> *l = p->m_variableid_list; list<VariableID_ptr>::iterator it; OffsetTable* table; bool isClassDec; int offsetDir; if(inMethod) { table = currMethodOffset; isClassDec = false; offsetDir = -1; } else{ table = currClassOffset; isClassDec = true; offsetDir = 1; } VariableIDImpl* var; VariableID_ptr ptr; int curroffset; for(it=l->begin(); it!=l->end(); ++it) { ptr = (VariableID_ptr)*it; var = dynamic_cast<VariableIDImpl*> (ptr); // Allocate space in stack/heap if not a class declaration if(type == bt_object && !isClassDec) { const char* c = p->m_type->m_attribute.m_type.classType.classID; assert(c != ""); assert(m_classtable->exist(c)); ClassNode* node = m_classtable->lookup(c); fprintf( m_outputfile, " pushl %s\n",heapTop); // push current heap top to stack as pointer to obj fprintf( m_outputfile, " addl $%d, %s\n",node->offset->getTotalSize(),heapTop); // allocate in heap } else if(!isClassDec) { fprintf(m_outputfile, " subl $%i, %%esp\n", varSize); } // Insert into and update offset table curroffset = table->getTotalSize(); table->insert(var->m_symname->spelling(), offsetDir*curroffset, varSize, p->m_type->m_attribute.m_type.classType); //fprintf( m_outputfile, "%i, %i, %i, %i\n", inMethod, offsetDir, curroffset, varSize); table->setTotalSize(offsetDir*(offsetDir*curroffset+offsetDir*varSize)); } fprintf(m_outputfile, "####\n"); }
void visitVariable(Variable *p) { //get value put in eax and push VariableIDImpl * VarId = dynamic_cast<VariableIDImpl*>(p->m_variableid); char * varName = strdup(VarId->m_symname->spelling()); fprintf( m_outputfile, " movl %d(%%ebp) , %%eax\n",currMethodOffset->get_offset(varName)); fprintf( m_outputfile, " pushl %%eax\n"); p->visit_children(this); // WRITEME }
//===================================================================================================================== void visitMethodCall(MethodCall *p) { fprintf(m_outputfile, "#### METHC\n"); // Visit variable and method name p->m_methodid->accept(this); p->m_variableid->accept(this); // Grab variable's classname (for jump label) from offset table OffsetTable* table = currMethodOffset; bool inClass=false; const char* varname = dynamic_cast<VariableIDImpl*>(p->m_variableid)->m_symname->spelling(); if(!table->exist(varname)) {table = currClassOffset; inClass=true;} assert(table->exist(varname)); CompoundType type = table->get_type(varname); const char* name; name = type.classID; // Visit parameters in reverse order, so their results will end up on the stack in x86 convention order int numparams = 0; list<Expression_ptr> *l = p->m_expression_list; list<Expression_ptr>::iterator it; Expression* exp; Expression_ptr ptr; for(it=l->end(); it!=l->begin();) { --it; ptr = (Expression_ptr)*it; exp = dynamic_cast<Expression*> (ptr); exp->accept(this); numparams++; } // Push referenced object's pointer to stack as final parameter if(!inClass) { fprintf( m_outputfile, " pushl %i(%%ebp)\n", table->get_offset(varname)); } else { fprintf( m_outputfile, " movl 8(%%ebp), %%ebx\n"); fprintf( m_outputfile, " pushl %i(%%ebx)\n", table->get_offset(varname)); } numparams++; // Find class/superclass that contains the function const char* funcname = dynamic_cast<MethodIDImpl*>(p->m_methodid)->m_symname->spelling(); ClassNode* node = m_classtable->lookup(name); assert(node!=NULL); while(!(node->scope->exist(funcname))) { assert(node->superClass != NULL); node = m_classtable->lookup(node->superClass); } // Call the function fprintf(m_outputfile, " call %s_%s\n", node->name->spelling(), funcname); // Clean up parameters fprintf(m_outputfile, " addl $%i, %%esp\n", numparams*4); // Push return value fprintf(m_outputfile, " pushl %%ebx\n"); fprintf(m_outputfile, "####\n"); }
//===================================================================================================================== void visitVariable(Variable *p) { fprintf(m_outputfile, "## VAR\n"); // Visit the children p->visit_children(this); // Look up variable offset and type in offset table OffsetTable* table = currMethodOffset; bool inClass=false; const char* name = dynamic_cast<VariableIDImpl*>(p->m_variableid)->m_symname->spelling(); if(!table->exist(name)) {table = currClassOffset; inClass=true;} assert(table->exist(name)); int offset = table->get_offset(name); // Push from either stack or heap, depending on where variable is located if(!inClass) fprintf(m_outputfile, " pushl %i(%%ebp)\n", offset); else { fprintf(m_outputfile, " mov 8(%%ebp), %%eax\n", offset); fprintf(m_outputfile, " pushl %i(%%eax)\n", offset); } fprintf(m_outputfile, "##\n"); }
void visitAssignment(Assignment *p) { fprintf( m_outputfile, "#### ASSIGNMENT\n"); // cout<<"Before assignment@@@@@@@@@@@@@@@@@@@@@@ "<<endl; p->visit_children(this); // cout<<"AFTER assignment$$$$$$$$$$$$$$$$$$$$$$$$ "<<endl; VariableIDImpl * VarId = dynamic_cast<VariableIDImpl*>(p->m_variableid); char * varName = strdup(VarId->m_symname->spelling()); // fprintf( m_outputfile, " popl %%eax\n"); fprintf( m_outputfile, " movl %%eax , %d(%%ebp)\n",currMethodOffset->get_offset(varName)); // WRITEME }
void visitMethodImpl(MethodImpl *p) { fprintf( m_outputfile, "#### METHOD IMPLEMENTATION\n"); int localSpace, args, mem; int j=0; int methMem = 0; CompoundType info; currMethodOffset = new OffsetTable(); // cout<<"before my childen"<<endl; //this is to make the label name Symbol * symbP; SymScope * sync; MethodIDImpl * MethIdP = dynamic_cast<MethodIDImpl*>(p->m_methodid); char * funcName = strdup(MethIdP->m_symname->spelling()); sync = m_symboltable->get_current_scope(); symbP = sync->lookup((const char *)"xxx"); char * classMethName = strdup(symbP->classType.classID); strcat(classMethName,"_"); strcat(classMethName,funcName); fprintf( m_outputfile, "_%s:\n",classMethName); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ fprintf( m_outputfile, " pushl %%ebp\n"); fprintf( m_outputfile, " movl %%esp , %%ebp\n"); MethodBodyImpl * MethBodP = dynamic_cast<MethodBodyImpl*>(p->m_methodbody); localSpace = (p->m_parameter_list->size() + MethBodP->m_declaration_list->size()); localSpace = localSpace * wordsize; // currMethodOffset->insert(classMethName, localSpace, 4,symbP->classType); currMethodOffset->setTotalSize(localSpace); currMethodOffset->setParamSize(p->m_parameter_list->size() * wordsize); //### inserting paramaters into the offset table ########### for (std::list<Parameter_ptr>::iterator it = p->m_parameter_list->begin() ; it != p->m_parameter_list->end(); ++it){ ParameterImpl * param = dynamic_cast<ParameterImpl*>(*it); VariableIDImpl * VarId = dynamic_cast<VariableIDImpl*>(param->m_variableid); info.baseType = param->m_type->m_attribute.m_type.baseType; if(info.baseType == 8){ info.classID = param->m_type->m_attribute.m_type.classType.classID; } else{ info.classID = "NO CLASS"; } methMem -= 4; // cout<<"Offset-> symname: "<<VarId->m_symname->spelling()<<" offset: "<<methMem<<" class type: " <<info.baseType<<endl; currMethodOffset->insert(VarId->m_symname->spelling(), methMem, 4,info); } //################################ //<><>Diving into Declaration <><><><>><><><><><><><><><><><>><><><><><>< typename std::list<Declaration_ptr>::iterator it = MethBodP->m_declaration_list->begin(); for( ; it != MethBodP->m_declaration_list->end(); ++it) { DeclarationImpl * DeclaP = dynamic_cast<DeclarationImpl *> (*it); typename std::list<VariableID_ptr>::iterator it = DeclaP->m_variableid_list->begin(); for( ; it != DeclaP->m_variableid_list->end(); ++it) { methMem -= 4; // need to move to the next offset VariableIDImpl * VarIdP = dynamic_cast<VariableIDImpl*>(*it); char * var = strdup(VarIdP->m_symname->spelling()); // cout<<"Offset-> symname: "<<var<<" Offset: "<<methMem<<" Class type: " <<endl; info.baseType = DeclaP->m_type->m_attribute.m_type.baseType; if(info.baseType == 8){ info.classID = DeclaP->m_type->m_attribute.m_type.classType.classID; } else{ info.classID = "NO CLASS"; } currMethodOffset->insert(var, methMem, 4,info); } } //<><><><><><><><><><><><><><><><><>><><><><><>< //~~~~ allocating space on the stack and moves parameters into local ~~~~~~ // cout<<"param size: "<<currMethodOffset->getParamSize()<<endl; // cout<<" LocalSpace: "<< -(methMem)<<endl; fprintf( m_outputfile, " subl $%d, %%esp\n",-(methMem)); mem = -4; for(int i = currMethodOffset->getParamSize() + 4; i>= 8; i = i-4){ fprintf( m_outputfile, " movl %d(%%ebp) , %%eax\n",i); fprintf( m_outputfile, " movl %%eax , %d(%%ebp)\n",mem); mem -= 4; // symbP->methodType.argsType[j].baseType; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ p->visit_children(this); // cout<<"after the children"<<endl; fprintf( m_outputfile, " leave\n"); fprintf( m_outputfile, " ret\n"); // WRITEME }
TEST_F(OffsetTableUnittest, Checksum) { // Assert that checksum computation is correct const double data[4] = { 3.14, 456.1, 25.3, 0.000012 }; const std::string checksum = computeChecksum(data, 4*sizeof(double)); const std::string checksum_ref = "39DA3F5AEE8A68A8B5083E9BCBB252069EFE223BFCA28AEE7CD3BC49F8379C7"; ASSERT_EQ(checksum_ref, checksum); // Define some savepoints Savepoint sp0, sp1; sp0.Init("FastWavesUnittest.Divergence-in"); sp0.AddMetainfo("LargeTimeStep", 1); sp0.AddMetainfo("RKStageNumber", 2); sp0.AddMetainfo("ldyn_bbc", false); sp1.Init("DycoreUnittest.DoStep-out"); sp1.AddMetainfo("LargeTimeStep", 2); sp1.AddMetainfo("hd", (Real).5); // Test that offset table recognizes checksums OffsetTable table; table.AddNewSavepoint(sp0, 0); table.AddNewSavepoint(sp1, 1); int offset; ASSERT_EQ(-1, offset = table.AlreadySerialized("Field1", computeChecksum(data, 4))); ASSERT_NO_THROW(table.AddFieldRecord(0, "Field1", 0, computeChecksum(data, 4))); ASSERT_EQ(-1, offset = table.AlreadySerialized("Field1", computeChecksum(data, 8))); ASSERT_NO_THROW(table.AddFieldRecord(1, "Field1", 100, computeChecksum(data, 8))); ASSERT_EQ(-1, offset = table.AlreadySerialized("Field2", computeChecksum(data, 8))); ASSERT_NO_THROW(table.AddFieldRecord(0, "Field2", 200, computeChecksum(data, 8))); ASSERT_EQ( 0, table.AlreadySerialized("Field1", computeChecksum(data,4))); ASSERT_EQ(100, table.AlreadySerialized("Field1", computeChecksum(data,8))); ASSERT_EQ(200, table.AlreadySerialized("Field2", computeChecksum(data,8))); ASSERT_NO_THROW(table.AddFieldRecord(1, "Field2", 200, computeChecksum(data, 8))); ASSERT_EQ( 0, table.GetOffset(sp0, "Field1")); ASSERT_EQ(100, table.GetOffset(sp1, "Field1")); ASSERT_EQ(200, table.GetOffset(sp0, "Field2")); ASSERT_EQ(200, table.GetOffset(sp1, "Field2")); }
TEST_F(OffsetTableUnittest, TableToJSON) { Savepoint sp0, sp1; sp0.Init("FastWavesUnittest.Divergence-in"); sp0.AddMetainfo("LargeTimeStep", 1); sp0.AddMetainfo("RKStageNumber", 2); sp0.AddMetainfo("ldyn_bbc", false); sp1.Init("DycoreUnittest.DoStep-out"); sp1.AddMetainfo("LargeTimeStep", 2); sp1.AddMetainfo("hd", (Real).5); // Just for the sake of getting some valid checksums double somedata[] = { 1.1, 2.2, 3.3, 4.4 }; // Fill table OffsetTable table; ASSERT_NO_THROW(table.AddNewSavepoint(sp0, 0)); ASSERT_NO_THROW(table.AddNewSavepoint(sp1, 1)); ASSERT_NO_THROW(table.AddFieldRecord(sp0, "Field1", 0, computeChecksum(somedata, 4))); ASSERT_NO_THROW(table.AddFieldRecord( 0, "Field2", 0, computeChecksum(somedata, 8))); ASSERT_NO_THROW(table.AddFieldRecord( 1, "Field1", 100, computeChecksum(somedata, 12))); ASSERT_NO_THROW(table.AddFieldRecord(sp1, "Field2", 100, computeChecksum(somedata, 16))); //Generate table JSON JSONNode tableNode = table.TableToJSON(); ASSERT_EQ(JSON_ARRAY, tableNode.type()); ASSERT_EQ(2, tableNode.size()); // Check first savepoint ASSERT_EQ(std::string("FastWavesUnittest.Divergence-in"), tableNode[0]["__name"].as_string()); ASSERT_EQ(0, tableNode[0]["__id"].as_int()); ASSERT_EQ(1, tableNode[0]["LargeTimeStep"].as_int()); ASSERT_EQ(2, tableNode[0]["RKStageNumber"].as_int()); ASSERT_FALSE(tableNode[0]["ldyn_bbc"].as_bool()); ASSERT_EQ((int)JSON_ARRAY, (int)tableNode[0]["__offsets"][0].type()); ASSERT_EQ(std::string("Field1"), tableNode[0]["__offsets"][0].name()); ASSERT_EQ(0, tableNode[0]["__offsets"][0][0].as_int()); ASSERT_EQ(computeChecksum(somedata, 4), tableNode[0]["__offsets"][0][1].as_string()); ASSERT_EQ(0, tableNode[0]["__offsets"][1][0].as_int()); ASSERT_EQ(computeChecksum(somedata, 8), tableNode[0]["__offsets"][1][1].as_string()); // Check second savepoint ASSERT_EQ(std::string("DycoreUnittest.DoStep-out"), tableNode[1]["__name"].as_string()); ASSERT_EQ(1, tableNode[1]["__id"].as_int()); ASSERT_EQ(2, tableNode[1]["LargeTimeStep"].as_int()); ASSERT_EQ(0.5, tableNode[1]["hd"].as_float()); ASSERT_EQ((int)JSON_ARRAY, (int)tableNode[1]["__offsets"][0].type()); ASSERT_EQ(std::string("Field1"), tableNode[1]["__offsets"][0].name()); ASSERT_EQ(100, tableNode[1]["__offsets"][0][0].as_int()); ASSERT_EQ(computeChecksum(somedata, 12), tableNode[1]["__offsets"][0][1].as_string()); ASSERT_EQ(100, tableNode[1]["__offsets"][1][0].as_int()); ASSERT_EQ(computeChecksum(somedata, 16), tableNode[1]["__offsets"][1][1].as_string()); // Interpret JSON for table OffsetTable table2; table2.TableFromJSON(tableNode); // Check savepoints std::vector<Savepoint> const & sp = GetSavepoints(table2); ASSERT_EQ(2, sp.size()); ASSERT_EQ(sp0, sp[0]); ASSERT_EQ(sp1, sp[1]); ASSERT_EQ(0, table2.GetSavepointID(sp[0])); ASSERT_EQ(1, table2.GetSavepointID(sp[1])); // Check methods ASSERT_EQ( 0, table2.GetOffset(sp0, "Field1")); ASSERT_EQ( 0, table2.GetOffset(sp0, "Field2")); ASSERT_EQ(100, table2.GetOffset(sp1, "Field1")); ASSERT_EQ(100, table2.GetOffset(sp1, "Field2")); ASSERT_EQ( 0, table2.AlreadySerialized("Field1", computeChecksum(somedata, 4))); ASSERT_EQ(100, table2.AlreadySerialized("Field1", computeChecksum(somedata, 12))); ASSERT_EQ( 0, table2.AlreadySerialized("Field2", computeChecksum(somedata, 8))); ASSERT_EQ(100, table2.AlreadySerialized("Field2", computeChecksum(somedata, 16))); ASSERT_EQ( -1, table2.AlreadySerialized("Field1", computeChecksum(somedata, 8))); ASSERT_EQ( -1, table2.AlreadySerialized("Field2", computeChecksum(somedata, 4))); }