static inline void DumpScopeWithDeps(BlockScopeRawPtr scope) { assert(scope->is(BlockScope::FunctionScope) || scope->is(BlockScope::ClassScope)); DumpScope(scope, ""); const BlockScopeRawPtrFlagsVec &ordered = scope->getOrderedUsers(); for (BlockScopeRawPtrFlagsVec::const_iterator it = ordered.begin(), end = ordered.end(); it != end; ++it) { BlockScopeRawPtrFlagsVec::value_type pf = *it; auto prefix = folly::to<string>(" (", pf->second, ") "); DumpScope(pf->first, prefix.c_str()); } }
void DumpScopeInfo( // DUMP INFORMATION FOR SCOPE SCOPE scope ) // - starting scope { DumpScope( scope ); RingWalk( ScopeFriends( scope ), &dumpFriend ); RingWalk( ScopeInherits( scope ), &dumpBaseClass ); }
void DumpScope(SymbolScope *scope, std::ofstream &dump) { char buffer[100]; for(std::map<std::string, Symbol *>::iterator it = scope->GetSymbolTable()->begin(); it != scope->GetSymbolTable()->end(); ++it) { Symbol *symbol = it->second; if (typeid(*(symbol->DeclType)) == typeid(FunctionType) || scope->GetScopeKind() == SymbolScope::Global) { sprintf(buffer, "%0llX\t%s", (long long)symbol->Address, symbol->Name.c_str()); dump << buffer << std::endl; } } for(std::vector<SymbolScope *>::iterator it = scope->GetChildScopes()->begin(); it != scope->GetChildScopes()->end(); ++it) { SymbolScope *cs = *it; DumpScope(cs, dump); } }
static void dump_scope_defn( // DUMP SCOPE, GIVEN A SCOPE_DEFN void *_defn ) // - scope definition { SCOPE_DEFN *defn = _defn; DumpScope( defn->defn ); }
void AnalysisResult::processScopesParallel(const char *id, void *context /* = NULL */) { BlockScopeRawPtrQueue scopes; getScopesSet(scopes); #ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL std::cout << "processScopesParallel(" << id << "): " << scopes.size() << " scopes" << std::endl; #endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */ DepthFirstVisitor<When, OptVisitor> dfv( OptVisitor<When>(shared_from_this(), scopes.size())); bool first = true; bool again; dfv.data().start(); do { #ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL std::cout << "-----------------------------------" << std::endl; AnalysisResult::s_NumDoJobCalls = 0; AnalysisResult::s_NumForceRerunGlobal = 0; AnalysisResult::s_NumReactivateGlobal = 0; AnalysisResult::s_NumForceRerunUseKinds = 0; AnalysisResult::s_NumReactivateUseKinds = 0; AnalysisResult::s_DoJobUniqueScopes.clear(); #endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */ #ifdef HPHP_INSTRUMENT_TYPE_INF assert(RescheduleException::s_NumReschedules == 0); assert(RescheduleException::s_NumForceRerunSelfCaller == 0); assert(RescheduleException::s_NumRetTypesChanged == 0); assert(BaseTryLock::s_LockProfileMap.empty()); #endif /* HPHP_INSTRUMENT_TYPE_INF */ BlockScopeRawPtrQueue enqueued; again = dfv.visitParallel(scopes, first, enqueued); preWaitCallback<When>(first, scopes, context); #ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL { std::cout << "Enqueued " << enqueued.size() << " scopes in visitParallel()" << std::endl; if (enqueued.size() < 100) { for (BlockScopeRawPtrQueue::const_iterator it = enqueued.begin(); it != enqueued.end(); ++it) { DumpScopeWithDeps(*it); } } Timer timer(Timer::WallTime, "dfv.wait()"); dfv.data().wait(); } #else dfv.data().wait(); #endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */ assert(!dfv.data().getQueuedJobs()); assert(!dfv.data().getActiveWorker()); #ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL std::cout << "Number of doJob() calls: " << AnalysisResult::s_NumDoJobCalls << std::endl; std::cout << "Number of scopes which got doJob() called: " << AnalysisResult::s_DoJobUniqueScopes.size() << std::endl; std::vector<BIPair> v( AnalysisResult::s_DoJobUniqueScopes.begin(), AnalysisResult::s_DoJobUniqueScopes.end()); if (!v.empty()) { sort(v.begin(), v.end(), BIPairCmp()); std::vector<BIPair>::const_iterator end = v.size() > 20 ? v.begin() + 20 : v.end(); for (std::vector<BIPair>::const_iterator it = v.begin(); it != end; ++it) { auto prefix = folly::to<string>((*it).second, " times: "); DumpScope((*it).first, prefix.c_str()); } std::cout << "Number of global force reruns: " << AnalysisResult::s_NumForceRerunGlobal << std::endl; std::cout << "Number of global reactivates: " << AnalysisResult::s_NumReactivateGlobal << std::endl; std::cout << "Number of use kind force reruns: " << AnalysisResult::s_NumForceRerunUseKinds << std::endl; std::cout << "Number of use kind reactivates: " << AnalysisResult::s_NumReactivateUseKinds << std::endl; } int numWaiting = CountScopesWaiting(scopes); std::cout << "Number of waiting scopes: " << numWaiting << std::endl; #endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */ again = postWaitCallback<When>(first, again, scopes, context); first = false; } while (again); dfv.data().stop(); for (BlockScopeRawPtrQueue::iterator it = scopes.begin(), end = scopes.end(); it != end; ++it) { assert((*it)->getMark() == BlockScope::MarkProcessed); assert((*it)->getNumDepsToWaitFor() == 0); assert(!(*it)->needsReschedule()); assert((*it)->rescheduleFlags() == 0); } }
int main(int argc, char **argv) { bool codeTypeDefined = false; CompilationContext *context = CompilationContext::GetInstance(); context->TextStart = 0x400000000; context->DataStart = 0x400004000; context->RDataStart = 0x400008000; //NOTE: Currently, all global variables are put in the bss section and are NOT initialized with zeros, the data/rdata is not used. context->BssStart = 0x440000000; // NOTE: default targe code type // Only CODE_TYPE_I0 is supported CompilationContext::GetInstance()->CodeType = CODE_TYPE_I0; codeTypeDefined = true; for(int i = 1; i < argc; i++) { if(strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output") == 0) { if (argv[i + 1] != NULL && *argv[i + 1] != '-') { CompilationContext::GetInstance()->OutputFile = argv[++i]; } else { CompilationContext::GetInstance()->OutputFile = "a.bin"; } } else if( (strcmp(argv[i], "--debug") == 0) || (strcmp(argv[i], "-g") == 0) ) { CompilationContext::GetInstance()->Debug = true; } /* else if (strcmp(argv[i], "--i0") == 0) { if (codeTypeDefined) { printf("--i0 and --disa can not be used at the same time.\n" "Specify one code type only.\n"); return -1; } CompilationContext::GetInstance()->CodeType = CODE_TYPE_I0; codeTypeDefined = true; } else if (strcmp(argv[i], "--disa") == 0) { if (codeTypeDefined) { printf("--i0 and --disa can not be used at the same time.\n" "Specify one code type only.\n"); return -11; } CompilationContext::GetInstance()->CodeType = CODE_TYPE_DISA; codeTypeDefined = true; } */ else if ( (strcmp(argv[i], "--help") == 0) || strcmp(argv[i], "-h") == 0 ) { print_usage(argv[0]); return 0; } else { CompilationContext::GetInstance()->InputFiles.push_back(argv[i]); } } ILProgram *il = NULL; std::vector<std::string> &inputFiles = CompilationContext::GetInstance()->InputFiles; if(inputFiles.size() == 0) { print_usage(argv[0]); return 0; } else if(inputFiles.size() != 1) { //FIXME: Multiple input files assert("Not implemented: multiple input files."); } for(std::vector<std::string>::iterator it = inputFiles.begin(); it != inputFiles.end(); ++it) { std::string inputFile = CompilationContext::GetInstance()->InputFiles.front(); std::string fileExt = inputFile.substr(inputFile.find_last_of(".") + 1); if(fileExt == "c") { char tmpFileName[255]; sprintf(tmpFileName, "%s.tmp", inputFile.c_str()); // tmpnam(tmpFileName); printf("temp file is: %s\n", tmpFileName); context->CurrentFileName = inputFile; std::string cmdline = "gcc -E " + inputFile + " -o " + tmpFileName; if(system(cmdline.c_str()) != 0) { return -1; } if(CompilationContext::GetInstance()->Debug) { printf("--------------------------------------\n"); printf("parsing...\n"); } CSourceParser *frontend = new CSourceParser(); frontend->Parse(tmpFileName); // Note: leave tmpFile for user to check // remove(tmpFileName); if(CompilationContext::GetInstance()->Debug) { printf("--------------------------------------\n"); printf("ConstantPropagation...\n"); } ConstantPropagation *constantPropagation = new ConstantPropagation(); context->CodeDom->Accept(constantPropagation); if(CompilationContext::GetInstance()->Debug) { printf("--------------------------------------\n"); printf("ConstantPropagation...\n"); } TypeDeduction *typeDeduction = new TypeDeduction(); context->CodeDom->Accept(typeDeduction); if(CompilationContext::GetInstance()->Debug) { printf("--------------------------------------\n"); printf("codeDom Dump:\n"); ExpressionTreeDumper *codeDomDump = new ExpressionTreeDumper(); context->CodeDom->Accept(codeDomDump); } ILGenerator *ilgen = new ILGenerator(); context->CodeDom->Accept(ilgen); il = ilgen->GetILProgram(); } } if(il == NULL) { return -1; } if(CompilationContext::GetInstance()->Debug && il != NULL) { std::string baseFileName = CompilationContext::GetInstance()->OutputFile; int pos = baseFileName.find_last_of("."); if(pos != -1) { baseFileName = baseFileName.substr(0, pos) + ".il"; } std::ofstream ildump(baseFileName.c_str()); for(std::vector<ILClass *>::iterator cit = il->Claases.begin(); cit != il->Claases.end(); ++cit) { ILClass *c = *cit; ildump << "class " << c->ClassSymbol->Name << std::endl << "{" << std::endl; for(std::vector<ILFunction *>::iterator fit = c->Functions.begin(); fit != c->Functions.end(); ++fit) { ILFunction *f = *fit; ildump << " function " << f->FunctionSymbol->Name << std::endl << " {" << std::endl; for(std::vector<IL>::iterator iit = f->Body.begin(); iit != f->Body.end(); ++iit) { IL &il = *iit; if(il.Opcode == IL::Label) { ildump << " " << il.ToString() << std::endl; } else { ildump << " " << il.ToString() << std::endl; } } ildump << " }" << std::endl; } ildump << "}" << std::endl; } ildump.close(); } context->IL = il; // TODO: Optimize the IL ILOptimizer *ilopt = NULL; ilopt = new ILOptimizer(); context->IL = ilopt->Optimize(il); // print optimized IL il = context->IL; if(CompilationContext::GetInstance()->Debug && il != NULL) { printf("--------------------------------------\n"); printf("Optimized IL:\n"); std::string baseFileName = CompilationContext::GetInstance()->OutputFile; int pos = baseFileName.find_last_of("."); if(pos != -1) { baseFileName = baseFileName.substr(0, pos) + ".opt.il"; } std::ofstream ildump(baseFileName.c_str()); for(std::vector<ILClass *>::iterator cit = il->Claases.begin(); cit != il->Claases.end(); ++cit) { ILClass *c = *cit; ildump << "class " << c->ClassSymbol->Name << std::endl << "{" << std::endl; for(std::vector<ILFunction *>::iterator fit = c->Functions.begin(); fit != c->Functions.end(); ++fit) { ILFunction *f = *fit; ildump << " function " << f->FunctionSymbol->Name << std::endl << " {" << std::endl; for(std::vector<IL>::iterator iit = f->Body.begin(); iit != f->Body.end(); ++iit) { IL &il = *iit; if(il.Opcode == IL::Label) { ildump << " " << il.ToString() << std::endl; } else { ildump << " " << il.ToString() << std::endl; } } ildump << " }" << std::endl; } ildump << "}" << std::endl; } ildump.close(); } CodeGenerator *codegen = NULL; //Generate assembly code from IL /* if (CompilationContext::GetInstance()->CodeType == CODE_TYPE_DISA) { //Generate DISA assembly code from IL codegen = new DisaCodeGenerator(); } else */ if (CompilationContext::GetInstance()->CodeType == CODE_TYPE_I0) { codegen = new I0CodeGenerator(); } else { printf("Error: unsupported CodeType.\n"); return -1; } codegen->Generate(context->IL); for(std::vector<std::string>::iterator it = inputFiles.begin(); it != inputFiles.end(); ++it) { std::string inputFile = context->InputFiles.front(); std::string fileExt = inputFile.substr(inputFile.find_last_of(".") + 1); if(fileExt == "s") { SourceParser *parser = NULL; /* if (CompilationContext::GetInstance()->CodeType == CODE_TYPE_DISA) { parser = new DisaAssemblyParser(); } else */ { // TODO: support i0 assembly printf(".s file is not supported for i0.\n"); return -1; } parser->Parse(inputFile); } } if(context->Debug) { std::string baseFileName = CompilationContext::GetInstance()->OutputFile; std::string dumpFileName, mapFileName; int pos = baseFileName.find_last_of("."); if(pos != -1) { baseFileName = baseFileName.substr(0, pos); } dumpFileName = baseFileName + ".objdump"; mapFileName = baseFileName + ".map"; std::ofstream objdump(dumpFileName.c_str()); int64_t currentText = context->TextStart; for(std::vector<TargetInstruction *>::iterator iit = context->Target->Code.begin(); iit != context->Target->Code.end(); ++iit) { TargetInstruction *inst = *iit; char buffer[32]; sprintf(buffer, "%0llX> \t", (long long)currentText); objdump << buffer << inst->ToString().c_str() << std::endl; currentText += inst->GetLength(); } objdump.close(); std::ofstream mapdump(mapFileName.c_str()); DumpScope(SymbolScope::GetRootScope(), mapdump); } printf("Maximum stack frame size: 0x%llX\n", (long long )(context->MaxStackFrame)); // TODO: Optimize the assembly code TargetOptimizer *targetOpt = NULL; char *textBuf = new char[0x100000]; int64_t textSize = 0; for(std::vector<TargetInstruction *>::iterator it = context->Target->Code.begin(); it != context->Target->Code.end(); ++it) { TargetInstruction *inst = *it; inst->Encode(&textBuf[textSize]); textSize += inst->GetLength(); } // Write the binary into file std::string outputFile = CompilationContext::GetInstance()->OutputFile; BinaryWriter *binwt = new FlatFileWriter(); std::vector<SectionInfo> sections; SectionInfo textSection; textSection.Name = ".text"; textSection.RawData = textBuf; textSection.RawDataSize = textSize; textSection.VirtualBase = context->TextStart; textSection.VirtualSize = textSize; sections.push_back(textSection); binwt->WriteBinaryFile(context->OutputFile, §ions, context->TextStart); return 0; }