bool AndroidExporter::ExportMainFile(gd::Project& project, gd::String outputDir) { gd::String layoutFunctionDeclarations; gd::String functionAssignmentCode; for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) { auto layout = project.GetLayout(i); gd::String layoutFunctionName = "GDSceneEvents" + gd::SceneNameMangler::GetMangledSceneName(layout.GetName()); gd::EventsCodeGenerator codeGenerator(project, layout, CppPlatform::Get()); layoutFunctionDeclarations += "extern \"C\" int " + layoutFunctionName + "(RuntimeContext * runtimeContext);\n"; functionAssignmentCode += "\t\tif (scene.GetName() == \"" + codeGenerator.ConvertToString(layout.GetName()) + "\") function = &" + layoutFunctionName + ";\n"; } gd::String mainFile = fs.ReadFile(GetAndroidProjectPath() + "/jni/main.cpp") .FindAndReplace("/* GDCPP_EVENTS_DECLARATIONS */", layoutFunctionDeclarations) .FindAndReplace("/* GDCPP_EVENTS_ASSIGNMENTS */", functionAssignmentCode); return fs.WriteToFile(outputDir + "/jni/main.cpp", mainFile); }
/* ***************************************************************************************************************** * startGeneration: * root : The ASTNode* generated after creating AST. * This function initializes the link list of three address code which is to be generated. * Calls codeGenerator function which does rest of the job. ***************************************************************************************************************** */ void startGeneration(ASTNode* root){ CODE_HEAD = NULL; CODE_TAIL = NULL; FunctionNode* funInfo = (FunctionNode*)malloc(sizeof(FunctionNode)); FunctionNode* freeFunInfo = funInfo; funInfo->funTok = root->child->token; funInfo = (FunctionNode*)get(FUNCTION_TABLE.hashTable,funInfo); Label* currLabel = (Label*)malloc(sizeof(Label)); currLabel->labelType = 1; currLabel->labelNum = 0; codeGenerator(root->child,funInfo,currLabel,0); }
bool generateOutput(const string& fileContents, const string& outputBitCodeName) { // Parse the source file //cout << "Parsing..." << endl; base_expr_node rootAst; if (!parse(fileContents, rootAst)) { cerr << "Failed to parse source file!" << endl; return false; } // Generate the code //cout << "Generating code..." << endl; LLVMContext &context = getGlobalContext(); unique_ptr<Module> module(new Module("", context)); IRBuilder<> builder(getGlobalContext()); ast_codegen codeGenerator(module.get(), builder); // Generate code for each expression at the root level const base_expr* expr = boost::get<base_expr>(&rootAst); for (auto& itr : expr->children) { boost::apply_visitor(codeGenerator, itr); } // Perform an LLVM verify as a sanity check string errorInfo; raw_string_ostream errorOut(errorInfo); if (verifyModule(*module, &errorOut)) { cerr << "Failed to generate LLVM IR: " << errorInfo << endl; module->print(errorOut, nullptr); cerr << "Module:" << endl << errorInfo << endl; return false; } // Dump the LLVM IR to a file llvm::raw_fd_ostream outStream(outputBitCodeName.c_str(), errorInfo, llvm::sys::fs::F_None); llvm::WriteBitcodeToFile(module.get(), outStream); return true; }
/* ***************************************************************************************************************** * codeGenerator: * child : The ASTNode for which the code has to be generated. * funInfo : This has the FunctionNode(see astDef.h for details) for the function * which has the 'child'. * currLabel : Possible label which can be assigned to the current instruction. * parentLabel : The label of the parent node in AST. * This function simply does the post order traversal of a function and generates code for that function. * In our case it works only for the main function. ***************************************************************************************************************** */ void codeGenerator(ASTNode* child,FunctionNode* funInfo,Label* currLabel, int parentLabel){ if(child==NULL){ return; } int tempCount = funInfo->width; int tempLabel = currLabel->labelNum; InstructionList* funLabel = NULL; ASTNode* ifChild = NULL; int ifFlag=0; TokenName tokenName = child->token->tokenName; switch(tokenName){ case TK_MAIN: funLabel = createLabel(1,0); strcpy(funLabel->label,"main"); generate(funLabel); createCallStack(child); break; case TK_ASSIGNOP: generateArithmeticExpression(child,funInfo->funTok,&tempCount); break; case TK_IF: currLabel->labelNum += 2; generateBooleanExpression(child->child,funInfo->funTok,addLabel(1,tempLabel),addLabel(0,tempLabel),currLabel,&tempCount); generate(createLabel(1,tempLabel)); break; case TK_ELSE: generate(createInstruction(JMP,-1,-1,parentLabel+1,1,0)); generate(createLabel(0,parentLabel)); break; case TK_READ: generateScanf(child->child,funInfo); break; case TK_WRITE: generatePrintf(child->child,funInfo); break; case TK_WHILE: generate(createLabel(1,currLabel->labelNum)); currLabel->labelNum += 2; generateBooleanExpression(child->child,funInfo->funTok,addLabel(1,tempLabel+1),addLabel(0,tempLabel),currLabel,&tempCount); generate(createLabel(1,tempLabel+1)); break; } if(tokenName==TK_IF) codeGenerator(child->child,funInfo,currLabel, tempLabel); else codeGenerator(child->child,funInfo,currLabel, parentLabel); switch(tokenName){ case TK_MAIN: generate(createInstruction(ADD,RSP,IMM,0,0,funInfo->width+funInfo->tempCount)); generate(createInstruction(RET,-1,-1,-1,-1,-1)); break; case TK_WHILE: generate(createInstruction(JMP,-1,-1,tempLabel,1,0)); generate(createLabel(0,tempLabel)); break; case TK_IF: generate(createLabel(1,tempLabel+1)); ifChild = child->child; while(ifChild!=NULL){ if(ifChild->token->tokenName==TK_ELSE){ ifFlag = 1; break; } ifChild = ifChild->next; } if(!ifFlag) generate(createLabel(0,tempLabel)); break; } codeGenerator(child->next,funInfo,currLabel, parentLabel); }
uint8_t * compileMethodFromDetails( OMR_VMThread *omrVMThread, TR::IlGeneratorMethodDetails & details, TR_Hotness hotness, int32_t &rc) { uint64_t translationStartTime = TR::Compiler->vm.getUSecClock(); OMR::FrontEnd &fe = OMR::FrontEnd::singleton(); auto jitConfig = fe.jitConfig(); TR::RawAllocator rawAllocator; TR::SystemSegmentProvider defaultSegmentProvider(1 << 16, rawAllocator); TR::DebugSegmentProvider debugSegmentProvider(1 << 16, rawAllocator); TR::SegmentAllocator &scratchSegmentProvider = TR::Options::getCmdLineOptions()->getOption(TR_EnableScratchMemoryDebugging) ? static_cast<TR::SegmentAllocator &>(debugSegmentProvider) : static_cast<TR::SegmentAllocator &>(defaultSegmentProvider); TR::Region dispatchRegion(scratchSegmentProvider, rawAllocator); TR_Memory trMemory(*fe.persistentMemory(), dispatchRegion); TR_ResolvedMethod & compilee = *((TR_ResolvedMethod *)details.getMethod()); TR::CompileIlGenRequest request(details); // initialize return code before compilation starts rc = COMPILATION_REQUESTED; uint8_t *startPC = 0; TR_FilterBST *filterInfo = 0; TR_OptimizationPlan *plan = 0; if (!methodCanBeCompiled(&fe, compilee, filterInfo, &trMemory)) { if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileExclude)) { TR_VerboseLog::write("<JIT: %s cannot be translated>\n", compilee.signature(&trMemory)); } return 0; } if (0 == (plan = TR_OptimizationPlan::alloc(hotness, false, false))) { // FIXME: maybe it would be better to allocate the plan on the stack // so that we don't have to deal with OOM ugliness below if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileExclude)) { TR_VerboseLog::write("<JIT: %s out-of-memory allocating optimization plan>\n", compilee.signature(&trMemory)); } return 0; } int32_t optionSetIndex = filterInfo ? filterInfo->getOptionSet() : 0; int32_t lineNumber = filterInfo ? filterInfo->getLineNumber() : 0; TR::Options options( &trMemory, optionSetIndex, lineNumber, &compilee, 0, plan, false); // FIXME: once we can do recompilation , we need to pass in the old start PC -----------------------^ // FIXME: what happens if we can't allocate memory at the new above? // FIXME: perhaps use stack memory instead TR_ASSERT(TR::comp() == NULL, "there seems to be a current TLS TR::Compilation object %p for this thread. At this point there should be no current TR::Compilation object", TR::comp()); TR::Compilation compiler(0, omrVMThread, &fe, &compilee, request, options, dispatchRegion, &trMemory, plan); TR_ASSERT(TR::comp() == &compiler, "the TLS TR::Compilation object %p for this thread does not match the one %p just created.", TR::comp(), &compiler); try { //fprintf(stderr,"loading JIT debug\n"); if (TR::Options::requiresDebugObject() || options.getLogFileName() || options.enableDebugCounters()) { compiler.setDebug(createDebugObject(&compiler)); } compiler.setIlVerifier(details.getIlVerifier()); if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileStart)) { const char *signature = compilee.signature(&trMemory); TR_VerboseLog::writeLineLocked(TR_Vlog_COMPSTART,"compiling %s", signature); } if (compiler.getOutFile() != NULL && compiler.getOption(TR_TraceAll)) { const char *signature = compilee.signature(&trMemory); traceMsg((&compiler), "<compile hotness=\"%s\" method=\"%s\">\n", compiler.getHotnessName(compiler.getMethodHotness()), signature); } compiler.getJittedMethodSymbol()->setLinkage(TR_System); // -------------------------------------------------------------------- // Compile the method // rc = compiler.compile(); if (rc == COMPILATION_SUCCEEDED) // success! { // not ready yet... //OMR::MethodMetaDataPOD *metaData = fe.createMethodMetaData(&compiler); startPC = compiler.cg()->getCodeStart(); uint64_t translationTime = TR::Compiler->vm.getUSecClock() - translationStartTime; if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance)) { const char *signature = compilee.signature(&trMemory); TR_VerboseLog::vlogAcquire(); TR_VerboseLog::writeLine(TR_Vlog_COMP,"(%s) %s @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT, compiler.getHotnessName(compiler.getMethodHotness()), signature, startPC, compiler.cg()->getCodeEnd()); if (TR::Options::getVerboseOption(TR_VerbosePerformance)) { TR_VerboseLog::write( " time=%llu mem=%lluKB", translationTime, static_cast<unsigned long long>(scratchSegmentProvider.bytesAllocated()) / 1024 ); } TR_VerboseLog::vlogRelease(); trfflush(jitConfig->options.vLogFile); } if ( TR::Options::getCmdLineOptions()->getOption(TR_PerfTool) || TR::Options::getCmdLineOptions()->getOption(TR_EmitExecutableELFFile) || TR::Options::getCmdLineOptions()->getOption(TR_EmitRelocatableELFFile) ) { TR::CodeCacheManager &codeCacheManager(fe.codeCacheManager()); TR::CodeGenerator &codeGenerator(*compiler.cg()); codeCacheManager.registerCompiledMethod(compiler.externalName(), startPC, codeGenerator.getCodeLength()); if (TR::Options::getCmdLineOptions()->getOption(TR_EmitRelocatableELFFile)) { auto &relocations = codeGenerator.getStaticRelocations(); for (auto it = relocations.begin(); it != relocations.end(); ++it) { codeCacheManager.registerStaticRelocation(*it); } } if (TR::Options::getCmdLineOptions()->getOption(TR_PerfTool)) { generatePerfToolEntry(startPC, codeGenerator.getCodeEnd(), compiler.signature(), compiler.getHotnessName(compiler.getMethodHotness())); } } if (compiler.getOutFile() != NULL && compiler.getOption(TR_TraceAll)) traceMsg((&compiler), "<result success=\"true\" startPC=\"%#p\" time=\"%lld.%lldms\"/>\n", startPC, translationTime/1000, translationTime%1000); } else /* of rc == COMPILATION_SUCCEEDED */ { TR_ASSERT(false, "compiler error code %d returned\n", rc); } if (compiler.getOption(TR_BreakAfterCompile)) { TR::Compiler->debug.breakPoint(); } } catch (const TR::ILValidationFailure &exception) { rc = COMPILATION_IL_VALIDATION_FAILURE; #if defined(J9ZOS390) // Compiling with -Wc,lp64 results in a crash on z/OS when trying // to call the what() virtual method of the exception. printCompFailureInfo(jitConfig, &compiler, ""); #else printCompFailureInfo(jitConfig, &compiler, exception.what()); #endif } catch (const std::exception &exception) { // failed! :-( #if defined(J9ZOS390) // Compiling with -Wc,lp64 results in a crash on z/OS when trying // to call the what() virtual method of the exception. printCompFailureInfo(jitConfig, &compiler, ""); #else printCompFailureInfo(jitConfig, &compiler, exception.what()); #endif } // A better place to do this would have been the destructor for // TR::Compilation. We'll need exceptions working instead of setjmp // before we can get working, and we need to make sure the other // frontends are properly calling the destructor TR::CodeCacheManager::instance()->unreserveCodeCache(compiler.getCurrentCodeCache()); TR_OptimizationPlan::freeOptimizationPlan(plan); return startPC; }