void FunctionStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { CodeGenerator::Context context = cg.getContext(); FunctionScopeRawPtr funcScope = getFunctionScope(); string fname = funcScope->getId(); bool pseudoMain = funcScope->inPseudoMain(); string origFuncName = !pseudoMain ? funcScope->getOriginalName() : ("run_init::" + funcScope->getContainingFile()->getName()); if (outputFFI(cg, ar)) return; if (context == CodeGenerator::NoContext) { funcScope->outputCPPDef(cg); return; } if (context == CodeGenerator::CppDeclaration && !funcScope->isInlined()) return; if (context == CodeGenerator::CppPseudoMain && (!pseudoMain || getFileScope()->canUseDummyPseudoMain(ar))) { return; } if (context == CodeGenerator::CppImplementation && (funcScope->isInlined() || pseudoMain)) return; cg.setPHPLineNo(-1); if (pseudoMain && !Option::GenerateCPPMain) { if (context == CodeGenerator::CppPseudoMain) { if (cg.getOutput() != CodeGenerator::SystemCPP) { cg.setContext(CodeGenerator::NoContext); // no inner functions/classes funcScope->getVariables()->setAttribute(VariableTable::ForceGlobal); outputCPPStmt(cg, ar); funcScope->getVariables()->clearAttribute(VariableTable::ForceGlobal); cg.setContext(CodeGenerator::CppPseudoMain); return; } } else if (context == CodeGenerator::CppForwardDeclaration && cg.getOutput() != CodeGenerator::SystemCPP) { return; } } if (context == CodeGenerator::CppImplementation) { printSource(cg); } else if (context == CodeGenerator::CppForwardDeclaration && Option::GenerateCppLibCode) { cg_printf("\n"); printSource(cg); cg.printDocComment(funcScope->getDocComment()); } bool isWrapper = context == CodeGenerator::CppTypedParamsWrapperDecl || context == CodeGenerator::CppTypedParamsWrapperImpl; bool needsWrapper = isWrapper || (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()); int startLineImplementation = -1; if (context == CodeGenerator::CppDeclaration || context == CodeGenerator::CppImplementation || context == CodeGenerator::CppPseudoMain) { startLineImplementation = cg.getLineNo(CodeGenerator::PrimaryStream); } if (funcScope->isInlined()) cg_printf("inline "); TypePtr type = funcScope->getReturnType(); if (type) { bool isHeader = cg.isFileOrClassHeader(); cg.setFileOrClassHeader(true); type->outputCPPDecl(cg, ar, getScope()); cg.setFileOrClassHeader(isHeader); } else { cg_printf("void"); } if (Option::FunctionSections.find(origFuncName) != Option::FunctionSections.end()) { string funcSection = Option::FunctionSections[origFuncName]; if (!funcSection.empty()) { cg_printf(" __attribute__ ((section (\".text.%s\")))", funcSection.c_str()); } } if (pseudoMain) { cg_printf(" %s%s(", Option::PseudoMainPrefix, funcScope->getContainingFile()->pseudoMainName().c_str()); } else { cg_printf(" %s%s(", needsWrapper && !isWrapper ? Option::TypedFunctionPrefix : Option::FunctionPrefix, fname.c_str()); } switch (context) { case CodeGenerator::CppForwardDeclaration: case CodeGenerator::CppTypedParamsWrapperDecl: funcScope->outputCPPParamsDecl(cg, ar, m_params, true); if (!isWrapper) { int opt = Option::GetOptimizationLevel(m_cppLength); if (opt < 3) cg_printf(") __attribute__((optimize(%d))", opt); } cg_printf(");\n"); if (!isWrapper) { if (funcScope->hasDirectInvoke()) { cg_printf("Variant %s%s(void *extra, CArrRef params);\n", Option::InvokePrefix, fname.c_str()); } if (needsWrapper) { cg.setContext(CodeGenerator::CppTypedParamsWrapperDecl); outputCPPImpl(cg, ar); cg.setContext(context); } } break; case CodeGenerator::CppDeclaration: case CodeGenerator::CppImplementation: case CodeGenerator::CppPseudoMain: case CodeGenerator::CppTypedParamsWrapperImpl: { funcScope->outputCPPParamsDecl(cg, ar, m_params, false); cg_indentBegin(") {\n"); if (!isWrapper) { const char *suffix = (cg.getOutput() == CodeGenerator::SystemCPP ? "_BUILTIN" : ""); if (pseudoMain) { cg_printf("PSEUDOMAIN_INJECTION%s(%s, %s%s);\n", suffix, origFuncName.c_str(), Option::PseudoMainPrefix, funcScope->getContainingFile()->pseudoMainName().c_str()); } else { if (m_stmt->hasBody()) { if (suffix[0] == '\0' && !funcScope->needsCheckMem()) { suffix = "_NOMEM"; } const string &name = funcScope->getInjectionId(); cg_printf("FUNCTION_INJECTION%s(%s);\n", suffix, name.c_str()); } outputCPPArgInjections(cg, ar, origFuncName.c_str(), ClassScopePtr(), funcScope); } funcScope->outputCPP(cg, ar); if (funcScope->needsRefTemp()) cg.genReferenceTemp(shared_from_this()); if (funcScope->needsObjTemp()) { cg_printf("ObjectData *obj_tmp UNUSED;\n"); } cg.setContext(CodeGenerator::NoContext); // no inner functions/classes outputCPPStmt(cg, ar); if (funcScope->needsRefTemp()) cg.clearRefereceTemp(); cg_indentEnd("}\n"); ASSERT(startLineImplementation >= 0); m_cppLength = cg.getLineNo(CodeGenerator::PrimaryStream) - startLineImplementation; if (needsWrapper) { cg.setContext(CodeGenerator::CppTypedParamsWrapperImpl); outputCPPImpl(cg, ar); } cg.setContext(context); } else { outputCPPTypeCheckWrapper(cg, ar); cg_indentEnd("}\n"); } cg.printImplSplitter(); } break; default: ASSERT(false); } }