bool ListAssignment::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { assert(m_array); if (!cg.inExpression()) return true; if (m_variables) { preOutputVariables(cg, ar, m_variables->hasEffect() || m_array->hasEffect() ? FixOrder : 0); } m_array->preOutputCPP(cg, ar, 0); bool isArray = false, notArray = false; bool simpleVar = m_array->is(KindOfSimpleVariable) && !static_pointer_cast<SimpleVariable>(m_array)->getAlwaysStash(); bool needsUse = false; if (TypePtr type = m_array->getActualType()) { isArray = type->is(Type::KindOfArray); notArray = !isArray && (type->isPrimitive() || m_rhsKind == Null || (m_rhsKind == Checked && (type->is(Type::KindOfString) || type->is(Type::KindOfObject)))); } cg.wrapExpressionBegin(); if (outputLineMap(cg, ar)) cg_printf("0);\n"); if (notArray && isUnused()) { if (m_array->outputCPPUnneeded(cg, ar)) cg_printf(";\n"); m_cppTemp = "null"; } else { m_cppTemp = genCPPTemp(cg, ar); needsUse = simpleVar || m_array->isTemporary(); const char *decl; if (isArray && m_array->getCPPType()->is(Type::KindOfArray)) { decl = needsUse ? "CArrRef" : "Array"; } else { decl = needsUse ? "CVarRef" : "Variant"; } cg_printf("%s %s((", decl, m_cppTemp.c_str()); m_array->outputCPP(cg, ar); cg_printf("));\n"); } std::string tmp; if (notArray) { tmp = "null_variant"; if (needsUse) cg_printf("id(%s);\n", m_cppTemp.c_str()); needsUse = false; } else if (m_rhsKind != Checked || isArray) { tmp = m_cppTemp; } else { tmp = genCPPTemp(cg, ar); cg_printf("CVarRef %s(f_is_array(%s)?%s:null_variant);\n", tmp.c_str(), m_cppTemp.c_str(), m_cppTemp.c_str()); needsUse = true; } if (!outputCPPAssignment(cg, ar, tmp, simpleVar) && needsUse) { cg_printf("id(%s);\n", tmp.c_str()); } return true; }
void ArrayElementExpression::outputCodeModel(CodeGenerator &cg) { if (m_offset) { cg.printObjectHeader("BinaryOpExpression", 4); cg.printPropertyHeader("expression1"); m_variable->outputCodeModel(cg); cg.printPropertyHeader("expression2"); cg.printExpression(m_offset, false); cg.printPropertyHeader("operation"); cg.printValue(PHP_ARRAY_ELEMENT); cg.printPropertyHeader("sourceLocation"); cg.printLocation(this); cg.printObjectFooter(); } else { cg.printObjectHeader("UnaryOpExpression", 3); cg.printPropertyHeader("expression"); m_variable->outputCodeModel(cg); cg.printPropertyHeader("operation"); cg.printValue(PHP_ARRAY_APPEND_POINT_OP); cg.printPropertyHeader("sourceLocation"); cg.printLocation(this); cg.printObjectFooter(); } }
void Switch::codegen_declarations(CodeGenerator& g) const { for (casadi_int k=0; k<=f_.size(); ++k) { const Function& fk = k<f_.size() ? f_[k] : f_def_; g.add_dependency(fk); } }
bool DynamicFunctionCall::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { bool nonStatic = !m_class && m_className.empty(); if (!nonStatic && !m_class && !m_classScope && !isRedeclared()) { // call to an unknown class // set m_noStatic to avoid pointlessly wrapping the call // in STATIC_CLASS_NAME_CALL() m_noStatic = true; cg.pushCallInfo(-1); bool ret = FunctionCall::preOutputCPP(cg, ar, state); cg.popCallInfo(); return ret; } // Short circuit out if inExpression() returns false if (!cg.inExpression()) return true; cg.wrapExpressionBegin(); m_ciTemp = cg.createNewLocalId(shared_from_this()); if (!m_classScope && !m_className.empty() && m_cppTemp.empty() && !isSelf() && ! isParent() && !isStatic()) { // Create a temporary to hold the class name, in case it is not a // StaticString. m_clsNameTemp = cg.createNewLocalId(shared_from_this()); cg_printf("CStrRef clsName%d(", m_clsNameTemp); cg_printString(m_origClassName, ar, shared_from_this()); cg_printf(");\n"); } if (m_class) { int s = m_class->hasEffect() || m_nameExp->hasEffect() ? FixOrder : 0; m_class->preOutputCPP(cg, ar, s); } m_nameExp->preOutputCPP(cg, ar, 0); if (nonStatic) { cg_printf("const CallInfo *cit%d;\n", m_ciTemp); cg_printf("void *vt%d;\n", m_ciTemp); cg_printf("get_call_info_or_fail(cit%d, vt%d, ", m_ciTemp, m_ciTemp); if (m_nameExp->is(Expression::KindOfSimpleVariable)) { m_nameExp->outputCPP(cg, ar); } else { cg_printf("("); m_nameExp->outputCPP(cg, ar); cg_printf(")"); } cg_printf(");\n"); } else { cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp); if (m_class) { if (m_class->is(KindOfScalarExpression)) { ASSERT(strcasecmp(dynamic_pointer_cast<ScalarExpression>(m_class)-> getString().c_str(), "static") == 0); cg_printf("CStrRef cls%d = " "FrameInjection::GetStaticClassName(fi.getThreadInfo())", m_ciTemp); } else { cg_printf("C%sRef cls%d = ", m_class->getActualType() && m_class->getActualType()->is(Type::KindOfString) ? "Str" : "Var", m_ciTemp); m_class->outputCPP(cg, ar); } } else if (m_classScope) { cg_printf("CStrRef cls%d = ", m_ciTemp); cg_printString(m_classScope->getId(), ar, shared_from_this()); } else { cg_printf("CStrRef cls%d = ", m_ciTemp); cg_printString(m_className, ar, shared_from_this()); } cg_printf(";\n"); cg_printf("CStrRef mth%d = ", m_ciTemp); if (m_nameExp->is(Expression::KindOfSimpleVariable)) { m_nameExp->outputCPP(cg, ar); } else { cg_printf("("); m_nameExp->outputCPP(cg, ar); cg_printf(")"); } cg_printf(";\n"); bool dynamic = true; if (!m_class) { ClassScopeRawPtr origClass = getOriginalClass(); if (!origClass) { dynamic = false; } else { FunctionScopeRawPtr origFunc = getOriginalFunction(); if (origFunc) { if (origFunc->isStatic() || (m_classScope != origClass && (m_className.empty() || !origClass->derivesFrom( ar, m_className, true, true)))) { dynamic = false; } } } } if (dynamic) { if ((m_class && (!m_class->getActualType() || !m_class->getActualType()->is(Type::KindOfString))) || !getOriginalFunction() || !getOriginalClass() || getOriginalFunction()->isStatic()) { cg_printf("mcp%d.dynamicNamedCall(cls%d, mth%d);\n", m_ciTemp, m_ciTemp, m_ciTemp); } else { cg_printf("mcp%d.isObj = true;\n", m_ciTemp); cg_printf("mcp%d.rootObj = this;\n", m_ciTemp); cg_printf("mcp%d.name = &mth%d;\n", m_ciTemp, m_ciTemp); cg_printf("o_get_call_info_ex(cls%d, mcp%d);\n", m_ciTemp, m_ciTemp); } } else { cg_printf("mcp%d.staticMethodCall(cls%d, mth%d);\n", m_ciTemp, m_ciTemp, m_ciTemp); if (m_classScope) { cg_printf("%s%s.%sget_call_info(mcp%d);\n", Option::ClassStaticsCallbackPrefix, m_classScope->getId().c_str(), Option::ObjectStaticPrefix, m_ciTemp); } else if (isRedeclared()) { cg_printf("g->%s%s->%sget_call_info(mcp%d);\n", Option::ClassStaticsCallbackPrefix, m_className.c_str(), Option::ObjectStaticPrefix, m_ciTemp); } else { assert(false); } } cg_printf("const CallInfo *cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp); } if (m_params && m_params->getCount() > 0) { cg.pushCallInfo(m_ciTemp); m_params->preOutputCPP(cg, ar, 0); cg.popCallInfo(); } if (state & FixOrder) { cg.pushCallInfo(m_ciTemp); preOutputStash(cg, ar, state); cg.popCallInfo(); } return true; }
void MethodStatement::outputCodeModel(CodeGenerator &cg) { auto isAnonymous = ParserBase::IsClosureName(m_originalName); auto numProps = 4; if (m_attrList != nullptr) numProps++; if (m_ref) numProps++; if (m_params != nullptr) numProps++; if (m_retTypeAnnotation != nullptr) numProps++; if (!m_docComment.empty()) numProps++; cg.printObjectHeader("FunctionStatement", numProps); if (m_attrList != nullptr) { cg.printPropertyHeader("attributes"); cg.printExpressionVector(m_attrList); } cg.printPropertyHeader("modifiers"); m_modifiers->outputCodeModel(cg); if (m_ref) { cg.printPropertyHeader("returnsReference"); cg.printBool(true); } cg.printPropertyHeader("name"); cg.printValue(isAnonymous ? "" : m_originalName); //TODO: type parameters (task 3262469) if (m_params != nullptr) { cg.printPropertyHeader("parameters"); cg.printExpressionVector(m_params); } if (m_retTypeAnnotation != nullptr) { cg.printPropertyHeader("returnType"); m_retTypeAnnotation->outputCodeModel(cg); } cg.printPropertyHeader("block"); if (m_stmt != nullptr) { auto stmt = m_stmt; if (m_autoPropCount > 0) { stmt = static_pointer_cast<StatementList>(stmt->clone()); for (int i = m_autoPropCount; i > 0; i--) { stmt->removeElement(0); } } cg.printAsEnclosedBlock(stmt); } else { cg.printAsBlock(nullptr); } cg.printPropertyHeader("sourceLocation"); cg.printLocation(this); if (!m_docComment.empty()) { cg.printPropertyHeader("comments"); cg.printValue(m_docComment); } cg.printObjectFooter(); }
virtual PPMutationListener *GetPPMutationListener() { return CG->GetPPMutationListener(); }
virtual bool shouldSkipFunctionBody(Decl *D) { return CG->shouldSkipFunctionBody(D); }
virtual void HandleInterestingDecl(DeclGroupRef D) { CG->HandleInterestingDecl(D); }
virtual void HandleTranslationUnit(ASTContext &Ctx) { Decl * Decl = Visitor.GetLivenessFunction(); DeclGroupRef R = DeclGroupRef::Create(Ctx, &Decl, 1); CG->HandleTopLevelDecl(R); CG->HandleTranslationUnit(Ctx); }
virtual void Initialize(ASTContext &Context) { Visitor.SetContext(&Context); CG->Initialize(Context); }
virtual bool HandleTopLevelDecl(DeclGroupRef D) { for (DeclGroupRef::iterator b = D.begin(), e = D.end(); b != e; ++b) Visitor.TraverseDecl(*b); return CG->HandleTopLevelDecl(D); }
void ClassStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { ClassScopeRawPtr classScope = getClassScope(); if (cg.getContext() == CodeGenerator::NoContext) { if (classScope->isRedeclaring()) { cg_printf("g->%s%s = ClassStaticsPtr(NEW(%s%s)());\n", Option::ClassStaticsObjectPrefix, cg.formatLabel(m_name).c_str(), Option::ClassStaticsPrefix, classScope->getId(cg).c_str()); cg_printf("g->%s%s = &%s%s;\n", Option::ClassStaticsCallbackPrefix, cg.formatLabel(m_name).c_str(), Option::ClassWrapperFunctionPrefix, classScope->getId(cg).c_str()); } if (classScope->isVolatile()) { cg_printf("g->CDEC(%s) = true;\n", m_name.c_str()); } const vector<string> &bases = classScope->getBases(); for (vector<string>::const_iterator it = bases.begin(); it != bases.end(); ++it) { ClassScopePtr base = ar->findClass(*it); if (base && base->isVolatile()) { cg_printf("checkClassExists("); cg_printString(base->getOriginalName(), ar, shared_from_this()); string lname = Util::toLower(base->getOriginalName()); cg_printf(", &%s->CDEC(%s), %s->FVF(__autoload));\n", cg.getGlobals(ar), cg.formatLabel(lname).c_str(), cg.getGlobals(ar)); } } return; } if (cg.getContext() != CodeGenerator::CppForwardDeclaration) { printSource(cg); } string clsNameStr = classScope->getId(cg); const char *clsName = clsNameStr.c_str(); bool redeclared = classScope->isRedeclaring(); switch (cg.getContext()) { case CodeGenerator::CppDeclaration: { if (Option::GenerateCPPMacros) { classScope->outputForwardDeclaration(cg); } bool system = cg.getOutput() == CodeGenerator::SystemCPP; ClassScopePtr parCls; if (!m_parent.empty()) { parCls = ar->findClass(m_parent); if (parCls && parCls->isRedeclaring()) parCls.reset(); } if (Option::GenerateCppLibCode) { cg.printDocComment(classScope->getDocComment()); } cg_printf("class %s%s", Option::ClassPrefix, clsName); if (!m_parent.empty() && classScope->derivesDirectlyFrom(m_parent)) { if (!parCls) { cg_printf(" : public DynamicObjectData"); } else { cg_printf(" : public %s%s", Option::ClassPrefix, parCls->getId(cg).c_str()); } } else { if (classScope->derivesFromRedeclaring()) { cg_printf(" : public DynamicObjectData"); } else if (system) { cg_printf(" : public ExtObjectData"); } else { cg_printf(" : public ObjectData"); } } if (m_base && Option::UseVirtualDispatch) { for (int i = 0; i < m_base->getCount(); i++) { ScalarExpressionPtr exp = dynamic_pointer_cast<ScalarExpression>((*m_base)[i]); const char *intf = exp->getString().c_str(); ClassScopePtr intfClassScope = ar->findClass(intf); if (intfClassScope && !intfClassScope->isRedeclaring() && classScope->derivesDirectlyFrom(intf) && (!parCls || !parCls->derivesFrom(ar, intf, true, false))) { string id = intfClassScope->getId(cg); cg_printf(", public %s%s", Option::ClassPrefix, id.c_str()); } } } cg_indentBegin(" {\n"); cg_printf("public:\n"); cg.printSection("Properties"); classScope->getVariables()->outputCPPPropertyDecl(cg, ar, classScope->derivesFromRedeclaring()); if (Option::GenerateCppLibCode) { cg.printSection("Methods"); classScope->outputMethodWrappers(cg, ar); cg.printSection(">>>>>>>>>> Internal Implementation <<<<<<<<<<"); cg_printf("// NOTE: Anything below is subject to change. " "Use everything above instead.\n"); } cg.printSection("Class Map"); if (Option::GenerateCPPMacros) { cg_printf("virtual bool o_instanceof(CStrRef s) const;\n"); } if (Option::GenerateCPPMacros) { bool dyn = (!parCls && !m_parent.empty()) || classScope->derivesFromRedeclaring() == ClassScope::DirectFromRedeclared; bool idyn = parCls && classScope->derivesFromRedeclaring() == ClassScope::IndirectFromRedeclared; bool redec = classScope->isRedeclaring(); if (!classScope->derivesFromRedeclaring()) { outputCPPClassDecl(cg, ar, clsName, m_originalName.c_str(), parCls ? parCls->getId(cg).c_str() : "ObjectData"); } else { cg_printf("DECLARE_DYNAMIC_CLASS(%s, %s, %s)\n", clsName, m_originalName.c_str(), dyn || !parCls ? "DynamicObjectData" : parCls->getId(cg).c_str()); } if (system || Option::EnableEval >= Option::LimitedEval) { cg_printf("DECLARE_INVOKES_FROM_EVAL\n"); } bool hasGet = classScope->getAttribute( ClassScope::HasUnknownPropGetter); bool hasSet = classScope->getAttribute( ClassScope::HasUnknownPropSetter); bool hasCall = classScope->getAttribute( ClassScope::HasUnknownMethodHandler); bool hasCallStatic = classScope->getAttribute( ClassScope::HasUnknownStaticMethodHandler); if (dyn || idyn || redec || hasGet || hasSet || hasCall || hasCallStatic) { if (redec && classScope->derivedByDynamic()) { cg_printf("DECLARE_ROOT;\n"); if (!dyn && !idyn) { cg_printf("private: ObjectData* root;\n"); cg_printf("public:\n"); cg_printf("virtual ObjectData *getRoot() { return root; }\n"); } } string conInit = ""; bool hasParam = false; if (dyn) { conInit = " : DynamicObjectData(\"" + m_parent + "\", r)"; hasParam = true; } else if (idyn) { conInit = " : " + string(Option::ClassPrefix) + parCls->getId(cg) + "(r ? r : this)"; hasParam = true; } else { if (redec && classScope->derivedByDynamic()) { conInit = " : root(r ? r : this)"; } hasParam = true; } cg_indentBegin("%s%s(%s)%s {%s", Option::ClassPrefix, clsName, hasParam ? "ObjectData* r = NULL" : "", conInit.c_str(), hasGet || hasSet || hasCall || hasCallStatic ? "\n" : ""); if (hasGet) cg_printf("setAttribute(UseGet);\n"); if (hasSet) cg_printf("setAttribute(UseSet);\n"); if (hasCall) cg_printf("setAttribute(HasCall);\n"); if (hasCallStatic) cg_printf("setAttribute(HasCallStatic);\n"); cg_indentEnd("}\n"); } } cg_printf("void init();\n"); if (classScope->needLazyStaticInitializer()) { cg_printf("static GlobalVariables *lazy_initializer" "(GlobalVariables *g);\n"); } if (!classScope->getAttribute(ClassScope::HasConstructor)) { FunctionScopePtr func = classScope->findFunction(ar, "__construct", false); if (func && !func->isAbstract() && !classScope->isInterface()) { func->outputCPPCreateDecl(cg, ar); } } if (classScope->getAttribute(ClassScope::HasDestructor)) { cg_printf("public: virtual void destruct();\n"); } // doCall if (classScope->getAttribute(ClassScope::HasUnknownMethodHandler)) { cg_printf("Variant doCall(Variant v_name, Variant v_arguments, " "bool fatal);\n"); } if (classScope->isRedeclaring() && !classScope->derivesFromRedeclaring() && classScope->derivedByDynamic()) { cg_printf("Variant doRootCall(Variant v_name, Variant v_arguments, " "bool fatal);\n"); } if (m_stmt) m_stmt->outputCPP(cg, ar); { set<string> done; classScope->outputCPPStaticMethodWrappers(cg, ar, done, clsName); } if (cg.getOutput() == CodeGenerator::SystemCPP && ar->isBaseSysRsrcClass(clsName) && !classScope->hasProperty("rsrc")) { cg_printf("public: Variant %srsrc;\n", Option::PropertyPrefix); } if (Option::GenerateCPPMacros) { classScope->outputCPPJumpTableDecl(cg, ar); } cg_indentEnd("};\n"); if (redeclared) { cg_indentBegin("class %s%s : public ClassStatics {\n", Option::ClassStaticsPrefix, clsName); cg_printf("public:\n"); cg_printf("DECLARE_OBJECT_ALLOCATION(%s%s);\n", Option::ClassStaticsPrefix, clsName); cg_printf("%s%s() : ClassStatics(%d) {}\n", Option::ClassStaticsPrefix, clsName, classScope->getRedeclaringId()); cg_indentBegin("Variant %sgetInit(CStrRef s) {\n", Option::ObjectStaticPrefix); cg_printf("return %s%s::%sgetInit(s);\n", Option::ClassPrefix, clsName, Option::ObjectStaticPrefix); cg_indentEnd("}\n"); cg_indentBegin("Variant %sget(CStrRef s) {\n", Option::ObjectStaticPrefix); cg_printf("return %s%s::%sget(s);\n", Option::ClassPrefix, clsName, Option::ObjectStaticPrefix); cg_indentEnd("}\n"); cg_indentBegin("Variant &%slval(CStrRef s) {\n", Option::ObjectStaticPrefix); cg_printf("return %s%s::%slval(s);\n", Option::ClassPrefix, clsName, Option::ObjectStaticPrefix); cg_indentEnd("}\n"); cg_indentBegin("Object createOnly(ObjectData* root = NULL) {\n"); cg_printf("Object r((NEW(%s%s)(root)));\n", Option::ClassPrefix, clsName); cg_printf("r->init();\n"); cg_printf("return r;\n"); cg_indentEnd("}\n"); cg_indentBegin("Variant %sconstant(const char* s) {\n", Option::ObjectStaticPrefix); cg_printf("return %s%s::%sconstant(s);\n", Option::ClassPrefix, clsName, Option::ObjectStaticPrefix); cg_indentEnd("}\n"); cg_indentBegin("Variant %sinvoke_from_eval(const char *c, " "const char *s, Eval::VariableEnvironment &env, " "const Eval::FunctionCallExpression *call, " "int64 hash = -1, bool fatal = true) " "{\n", Option::ObjectStaticPrefix); cg_printf("return %s%s::%sinvoke_from_eval(c, s, env, call, hash, " "fatal);\n", Option::ClassPrefix, clsName, Option::ObjectStaticPrefix); cg_indentEnd("}\n"); cg_indentBegin("bool %sget_call_info(MethodCallPackage &mcp, " "int64 hash = -1) {\n", Option::ObjectStaticPrefix); cg_printf("return %s%s::%sget_call_info(mcp, hash);\n", Option::ClassPrefix, clsName, Option::ObjectStaticPrefix); cg_indentEnd("}\n"); cg_indentEnd("};\n"); } if (m_stmt) { cg.setContext(CodeGenerator::CppClassConstantsDecl); m_stmt->outputCPP(cg, ar); cg.setContext(CodeGenerator::CppDeclaration); } classScope->outputCPPGlobalTableWrappersDecl(cg, ar); } break; case CodeGenerator::CppImplementation: if (m_stmt) { cg.setContext(CodeGenerator::CppClassConstantsImpl); m_stmt->outputCPP(cg, ar); cg.setContext(CodeGenerator::CppImplementation); } classScope->outputCPPSupportMethodsImpl(cg, ar); if (redeclared) { cg_printf("IMPLEMENT_OBJECT_ALLOCATION(%s%s);\n", Option::ClassStaticsPrefix, clsName); } cg_indentBegin("void %s%s::init() {\n", Option::ClassPrefix, clsName); if (!m_parent.empty()) { if (classScope->derivesFromRedeclaring() == ClassScope::DirectFromRedeclared) { cg_printf("parent->init();\n"); } else { ClassScopePtr parCls = ar->findClass(m_parent); cg_printf("%s%s::init();\n", Option::ClassPrefix, parCls->getId(cg).c_str()); } } if (classScope->getVariables()-> getAttribute(VariableTable::NeedGlobalPointer)) { cg.printDeclareGlobals(); } cg.setContext(CodeGenerator::CppConstructor); if (m_stmt) m_stmt->outputCPP(cg, ar); // This is lame. Exception base class needs to prepare stacktrace outside // of its PHP constructor. Every subclass of exception also needs this // stacktrace, so we're adding an artificial __init__ in exception.php // and calling it here. if (m_name == "exception") { cg_printf("{CountableHelper h(this); t___init__();}\n"); } cg_indentEnd("}\n"); if (classScope->needStaticInitializer()) { cg_indentBegin("void %s%s::os_static_initializer() {\n", Option::ClassPrefix, clsName); cg.printDeclareGlobals(); cg.setContext(CodeGenerator::CppStaticInitializer); if (m_stmt) m_stmt->outputCPP(cg, ar); cg_indentEnd("}\n"); cg_indentBegin("void %s%s() {\n", Option::ClassStaticInitializerPrefix, clsName); cg_printf("%s%s::os_static_initializer();\n", Option::ClassPrefix, clsName); cg_indentEnd("}\n"); } if (classScope->needLazyStaticInitializer()) { cg_indentBegin("GlobalVariables *%s%s::lazy_initializer(" "GlobalVariables *g) {\n", Option::ClassPrefix, clsName); cg_indentBegin("if (!g->%s%s) {\n", Option::ClassStaticInitializerFlagPrefix, clsName); cg_printf("g->%s%s = true;\n", Option::ClassStaticInitializerFlagPrefix, clsName); cg.setContext(CodeGenerator::CppLazyStaticInitializer); if (m_stmt) m_stmt->outputCPP(cg, ar); cg_indentEnd("}\n"); cg_printf("return g;\n"); cg_indentEnd("}\n"); } cg.setContext(CodeGenerator::CppImplementation); if (m_stmt) m_stmt->outputCPP(cg, ar); break; case CodeGenerator::CppFFIDecl: case CodeGenerator::CppFFIImpl: if (m_stmt) m_stmt->outputCPP(cg, ar); break; case CodeGenerator::JavaFFI: { if (classScope->isRedeclaring()) break; // TODO support PHP namespaces, once HPHP supports it string packageName = Option::JavaFFIRootPackage; string packageDir = packageName; Util::replaceAll(packageDir, ".", "/"); string outputDir = ar->getOutputPath() + "/" + Option::FFIFilePrefix + packageDir + "/"; Util::mkdir(outputDir); // uses a different cg to generate a separate file for each PHP class // also, uses the original capitalized class name string clsFile = outputDir + getOriginalName() + ".java"; ofstream fcls(clsFile.c_str()); CodeGenerator cgCls(&fcls, CodeGenerator::FileCPP); cgCls.setContext(CodeGenerator::JavaFFI); cgCls.printf("package %s;\n\n", packageName.c_str()); cgCls.printf("import hphp.*;\n\n"); printSource(cgCls); string clsModifier; switch (m_type) { case T_CLASS: break; case T_ABSTRACT: clsModifier = "abstract "; break; case T_FINAL: clsModifier = "final "; break; } cgCls.printf("public %sclass %s ", clsModifier.c_str(), getOriginalName().c_str()); ClassScopePtr parCls; if (!m_parent.empty()) parCls = ar->findClass(m_parent); if (!m_parent.empty() && classScope->derivesDirectlyFrom(m_parent) && parCls && parCls->isUserClass() && !parCls->isRedeclaring()) { // system classes are not supported in static FFI translation // they shouldn't appear as superclasses as well cgCls.printf("extends %s", parCls->getOriginalName().c_str()); } else { cgCls.printf("extends HphpObject"); } if (m_base) { bool first = true; for (int i = 0; i < m_base->getCount(); i++) { ScalarExpressionPtr exp = dynamic_pointer_cast<ScalarExpression>((*m_base)[i]); const char *intf = exp->getString().c_str(); ClassScopePtr intfClassScope = ar->findClass(intf); if (intfClassScope && classScope->derivesFrom(ar, intf, false, false) && intfClassScope->isUserClass()) { if (first) { cgCls.printf(" implements "); first = false; } else { cgCls.printf(", "); } cgCls.printf(intfClassScope->getOriginalName().c_str()); } } } cgCls.indentBegin(" {\n"); // constructor for initializing the variant pointer cgCls.printf("protected %s(long ptr) { super(ptr); }\n\n", getOriginalName().c_str()); FunctionScopePtr cons = classScope->findConstructor(ar, true); if (cons && !cons->isAbstract() || m_type != T_ABSTRACT) { // if not an abstract class and not having an explicit constructor, // adds a default constructor outputJavaFFIConstructor(cgCls, ar, cons); } if (m_stmt) m_stmt->outputCPP(cgCls, ar); cgCls.indentEnd("}\n"); fcls.close(); } break; case CodeGenerator::JavaFFICppDecl: case CodeGenerator::JavaFFICppImpl: { if (classScope->isRedeclaring()) break; if (m_stmt) m_stmt->outputCPP(cg, ar); FunctionScopePtr cons = classScope->findConstructor(ar, true); if (cons && !cons->isAbstract() || m_type != T_ABSTRACT) { outputJavaFFICPPCreator(cg, ar, cons); } } break; default: ASSERT(false); break; } }
void ClassStatement::outputCPPClassDecl(CodeGenerator &cg, AnalysisResultPtr ar, const char *clsName, const char *originalName, const char *parent) { ClassScopeRawPtr classScope = getClassScope(); VariableTablePtr variables = classScope->getVariables(); ConstantTablePtr constants = classScope->getConstants(); if (variables->hasAllJumpTables() && constants->hasJumpTable() && classScope->hasAllJumpTables()) { cg_printf("DECLARE_CLASS(%s, %s, %s)\n", clsName, originalName, parent); return; } // Now we start to break down DECLARE_CLASS into lines of code that could // be generated differently... cg_printf("DECLARE_CLASS_COMMON(%s, %s)\n", clsName, cg.escapeLabel(originalName).c_str()); cg_printf("DECLARE_INVOKE_EX%s(%s, %s, %s)\n", Option::UseMethodIndex ? "WITH_INDEX" : "", clsName, cg.escapeLabel(originalName).c_str(), parent); cg.printSection("DECLARE_STATIC_PROP_OPS"); cg_printf("public:\n"); if (classScope->needStaticInitializer()) { cg_printf("static void os_static_initializer();\n"); } if (variables->hasJumpTable(VariableTable::JumpTableClassStaticGetInit)) { cg_printf("static Variant os_getInit(CStrRef s);\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_GETINIT_%s 1\n", clsName); } if (variables->hasJumpTable(VariableTable::JumpTableClassStaticGet)) { cg_printf("static Variant os_get(CStrRef s);\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_GET_%s 1\n", clsName); } if (variables->hasJumpTable(VariableTable::JumpTableClassStaticLval)) { cg_printf("static Variant &os_lval(CStrRef s);\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_LVAL_%s 1\n", clsName); } if (constants->hasJumpTable()) { cg_printf("static Variant os_constant(const char *s);\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_CONSTANT_%s 1\n", clsName); } cg.printSection("DECLARE_INSTANCE_PROP_OPS"); cg_printf("public:\n"); if (variables->hasJumpTable(VariableTable::JumpTableClassGetArray)) { cg_printf("virtual void o_getArray(Array &props, bool pubOnly = false) " "const;\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_GETARRAY_%s 1\n", clsName); } if (variables->hasJumpTable(VariableTable::JumpTableClassSetArray)) { cg_printf("virtual void o_setArray(CArrRef props);\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_SETARRAY_%s 1\n", clsName); } if (variables->hasJumpTable(VariableTable::JumpTableClassRealProp)) { cg_printf("virtual Variant *o_realProp(CStrRef s, int flags,\n"); cg_printf(" CStrRef context = null_string) " "const;\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_realProp_%s 1\n", clsName); } if (variables->hasNonStaticPrivate()) { cg_printf("Variant *o_realPropPrivate(CStrRef s, int flags) const;\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_realProp_PRIVATE_%s 1\n", clsName); } cg.printSection("DECLARE_INSTANCE_PUBLIC_PROP_OPS"); cg_printf("public:\n"); if (variables->hasJumpTable(VariableTable::JumpTableClassRealPropPublic)) { cg_printf("virtual Variant *o_realPropPublic(CStrRef s, " "int flags) const;\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_realProp_PUBLIC_%s 1\n", clsName); } cg.printSection("DECLARE_COMMON_INVOKE"); cg.printf("static bool os_get_call_info(MethodCallPackage &mcp, " "int64 hash = -1);\n"); if (Option::UseMethodIndex) { cg.printf("virtual bool o_get_call_info_with_index(MethodCallPackage &mcp," " MethodIndex mi, int64 hash = -1);\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_INVOKE_%s 1\n", clsName); } if (classScope->hasJumpTable(ClassScope::JumpTableInvoke)) { cg.printf("virtual bool o_get_call_info(MethodCallPackage &mcp, " "int64 hash = -1);\n"); } else { cg_printf("#define OMIT_JUMP_TABLE_CLASS_INVOKE_%s 1\n", clsName); } cg_printf("\n"); cg_printf("public:\n"); }
bool QOpExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (!hasEffect()) { return Expression::preOutputCPP(cg, ar, state); } bool fix_condition = m_condition->preOutputCPP(cg, ar, 0); if (!cg.inExpression()) { return fix_condition || (state & FixOrder) || (!m_expYes || m_expYes->preOutputCPP(cg, ar, 0)) || m_expNo->preOutputCPP(cg, ar, 0); } cg.setInExpression(false); bool fix_yes = (!m_expYes || m_expYes->preOutputCPP(cg, ar, 0)); bool fix_no = m_expNo->preOutputCPP(cg, ar, 0); cg.setInExpression(true); if (fix_yes || fix_no) { cg.wrapExpressionBegin(); if (isUnused()) { cg_printf("if ("); wrapBoolean(cg, ar, m_condition); cg_indentBegin(") {\n"); if (m_expYes) { m_expYes->preOutputCPP(cg, ar, 0); if (m_expYes->outputCPPUnneeded(cg, ar)) cg_printf(";\n"); } cg_indentEnd("\n"); cg_indentBegin("} else {\n"); m_expNo->preOutputCPP(cg, ar, 0); if (m_expNo->outputCPPUnneeded(cg, ar)) cg_printf(";\n"); cg_indentEnd("}\n"); m_cppValue = "null_variant"; } else { std::string tmp = genCPPTemp(cg, ar); if (m_expYes) { TypePtr typeYes = m_expYes->getActualType(); TypePtr typeNo = m_expNo->getActualType(); TypePtr type = typeYes && typeNo && Type::SameType(typeYes, typeNo) && !typeYes->is(Type::KindOfVariant) && m_expYes->isLiteralString() == m_expNo->isLiteralString() ? typeYes : Type::Variant; type->outputCPPDecl(cg, ar, getScope()); cg_printf(" %s;\n", tmp.c_str()); cg_printf("if ("); wrapBoolean(cg, ar, m_condition); cg_indentBegin(") {\n"); m_expYes->preOutputCPP(cg, ar, 0); cg_printf("%s = (", tmp.c_str()); m_expYes->outputCPP(cg, ar); cg_indentEnd(");\n"); } else { TypePtr typeYes = m_condition->getActualType(); TypePtr typeNo = m_expNo->getActualType(); TypePtr type = typeYes && typeNo && Type::SameType(typeYes, typeNo) && !typeYes->is(Type::KindOfVariant) && m_condition->isLiteralString() == m_expNo->isLiteralString() ? typeYes : Type::Variant; type->outputCPPDecl(cg, ar, getScope()); cg_printf(" %s = ", tmp.c_str()); m_condition->outputCPP(cg, ar); cg_printf(";\n"); cg_printf("if (toBoolean(%s)) {\n", tmp.c_str()); } cg_indentBegin("} else {\n"); m_expNo->preOutputCPP(cg, ar, 0); cg_printf("%s = (", tmp.c_str()); m_expNo->outputCPP(cg, ar); cg_printf(");\n"); cg_indentEnd("}\n"); m_cppValue = tmp; } } else if (state & FixOrder) { preOutputStash(cg, ar, state); return true; } return false; }
virtual ASTDeserializationListener *GetASTDeserializationListener() { return CG->GetASTDeserializationListener(); }
virtual void HandleTagDeclDefinition(TagDecl *D) { CG->HandleTagDeclDefinition(D); }
virtual void PrintStats() { CG->PrintStats(); }
virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) { CG->HandleCXXImplicitFunctionInstantiation(D); }
virtual void HandleImplicitImportDecl(ImportDecl *D) { CG->HandleImplicitImportDecl(D); }
virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) { CG->HandleTopLevelDeclInObjCContainer(D); }
bool ExpressionList::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (m_kind == ListKindParam && !m_arrayElements) { return Expression::preOutputCPP(cg, ar, state|StashKidVars); } unsigned n = m_exps.size(); bool inExpression = cg.inExpression(); if (!inExpression && (state & FixOrder)) { return true; } cg.setInExpression(false); bool ret = false; if (m_arrayElements) { /* * would like to do: * ret = Expression::preOutputCPP(cg, ar, state); * but icc has problems with the generated code. */ ret = hasEffect(); } else if (n > 1 && m_kind == ListKindLeft) { ret = true; } else { for (unsigned int i = 0; i < n; i++) { if (m_exps[i]->preOutputCPP(cg, ar, 0)) { ret = true; break; } } if (!ret) { ExpressionPtr e = m_exps[n - 1]; if (hasContext(LValue) && !hasAnyContext(RefValue|InvokeArgument) && !(e->hasContext(LValue) && !e->hasAnyContext(RefValue|InvokeArgument))) { ret = true; } else if (hasContext(RefValue) && !e->hasAllContext(LValue|ReturnContext) && !e->hasContext(RefValue)) { ret = true; } } } if (!inExpression) return ret; cg.setInExpression(true); if (!ret) { if (state & FixOrder) { preOutputStash(cg, ar, state); return true; } return false; } cg.wrapExpressionBegin(); if (m_arrayElements) { setCPPTemp(genCPPTemp(cg, ar)); outputCPPInternal(cg, ar, true, true); } else { unsigned ix = isUnused() ? (unsigned)-1 : m_kind == ListKindLeft ? 0 : n - 1; for (unsigned int i = 0; i < n; i++) { ExpressionPtr e = m_exps[i]; if (i != ix) e->setUnused(true); e->preOutputCPP(cg, ar, i == ix ? state : 0); if (i != ix) { if (e->outputCPPUnneeded(cg, ar)) { cg_printf(";\n"); } e->setCPPTemp("/**/"); continue; } /* We inlined a by-value function into the rhs of a by-ref assignment. */ bool noRef = hasContext(RefValue) && !e->hasAllContext(LValue|ReturnContext) && !e->hasContext(RefValue) && !e->isTemporary() && Type::IsMappedToVariant(e->getActualType()); /* If we need a non-const reference, but the expression is going to generate a const reference, fix it */ bool lvSwitch = hasContext(LValue) && !hasAnyContext(RefValue|InvokeArgument) && !(e->hasContext(LValue) && !e->hasAnyContext(RefValue|InvokeArgument)); if (e->hasAllContext(LValue|ReturnContext) && i + 1 == n) { e->clearContext(ReturnContext); } if (noRef || lvSwitch || (!i && n > 1)) { e->Expression::preOutputStash(cg, ar, state | FixOrder | StashAll); if (!(state & FixOrder)) { cg_printf("id(%s);\n", e->cppTemp().c_str()); } } if (e->hasCPPTemp() && Type::SameType(e->getGenType(), getGenType())) { string t = e->cppTemp(); if (noRef) { cg_printf("CVarRef %s_nr = wrap_variant(%s);\n", t.c_str(), t.c_str()); t += "_nr"; } if (lvSwitch) { cg_printf("Variant &%s_lv = const_cast<Variant&>(%s);\n", t.c_str(), t.c_str()); t += "_lv"; } setCPPTemp(t); } } } return true; }
virtual void CompleteTentativeDefinition(VarDecl *D) { CG->CompleteTentativeDefinition(D); }
void ClassStatement::outputCodeModel(CodeGenerator &cg) { auto numProps = 4; if (m_attrList != nullptr) numProps++; if (m_type == T_ABSTRACT || m_type == T_FINAL) numProps++; if (!m_parent.empty()) numProps++; if (m_base != nullptr) numProps++; if (m_stmt != nullptr) numProps++; if (!m_docComment.empty()) numProps++; cg.printObjectHeader("TypeStatement", numProps); if (m_attrList != nullptr) { cg.printPropertyHeader("attributes"); cg.printExpressionVector(m_attrList); } if (m_type == T_ABSTRACT) { cg.printPropertyHeader("modifiers"); cg.printModifierVector("abstract"); } else if (m_type == T_FINAL) { cg.printPropertyHeader("modifiers"); cg.printModifierVector("final"); } cg.printPropertyHeader("kind"); if (m_type == T_TRAIT) { cg.printValue(PHP_TRAIT); } else { cg.printValue(PHP_CLASS); } cg.printPropertyHeader("name"); cg.printValue(m_originalName); //TODO: type parameters (task 3262469) if (!m_parent.empty()) { cg.printPropertyHeader("baseClass"); cg.printTypeExpression(m_originalParent); } if (m_base != nullptr) { cg.printPropertyHeader("interfaces"); cg.printExpressionVector(m_base); } if (m_stmt != nullptr) { cg.printPropertyHeader("block"); cg.printAsBlock(m_stmt); } cg.printPropertyHeader("sourceLocation"); cg.printLocation(this->getLocation()); if (!m_docComment.empty()) { cg.printPropertyHeader("comments"); cg.printValue(m_docComment); } cg.printObjectFooter(); }
virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) { CG->HandleCXXStaticMemberVarInstantiation(D); }
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) { if (funcScope->isVolatile()) { string rname = CodeGenerator::FormatLabel(m_name); if (funcScope->isRedeclaring()) { cg.printf("g->GCI(%s) = &%s%s;\n", rname.c_str(), Option::CallInfoPrefix, fname.c_str()); } cg_printf("g->declareFunctionLit("); cg_printString(m_name, ar, shared_from_this()); cg_printf(");\n"); cg_printf("g->FVF(%s) = true;\n", rname.c_str()); } 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()); 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); } }
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { CG->HandleVTable(RD, DefinitionRequired); }
void MethodStatement::outputCodeModel(CodeGenerator &cg) { auto numProps = 3; if (m_attrList != nullptr) numProps++; if (m_ref) numProps++; if (m_params != nullptr) numProps++; if (m_retTypeAnnotation != nullptr) numProps++; if (m_stmt != nullptr) numProps++; if (!m_docComment.empty()) numProps++; cg.printObjectHeader("FunctionStatement", numProps); if (m_attrList != nullptr) { cg.printPropertyHeader("attributes"); cg.printExpressionVector(m_attrList); } cg.printPropertyHeader("modifiers"); m_modifiers->outputCodeModel(cg); if (m_ref) { cg.printPropertyHeader("returnsReference"); cg.printValue(m_ref); } cg.printPropertyHeader("name"); cg.printValue(m_originalName); //TODO: type parameters (task 3262469) if (m_params != nullptr) { cg.printPropertyHeader("parameters"); cg.printExpressionVector(m_params); } if (m_retTypeAnnotation != nullptr) { cg.printPropertyHeader("returnType"); m_retTypeAnnotation->outputCodeModel(cg); } if (m_stmt != nullptr) { cg.printPropertyHeader("block"); cg.printAsBlock(m_stmt); } cg.printPropertyHeader("location"); cg.printLocation(this->getLocation()); if (!m_docComment.empty()) { cg.printPropertyHeader("comments"); cg.printValue(m_docComment); } cg.printObjectFooter(); }
virtual ASTMutationListener *GetASTMutationListener() { return CG->GetASTMutationListener(); }
void Switch::codegen_body(CodeGenerator& g) const { // Project arguments with different sparsity if (project_in_) { // Project one or more argument g.local("i", "casadi_int"); g << "const casadi_real** arg1 = arg + " << n_in_ << ";\n"; } // Temporary memory for results with different sparsity if (project_out_) { // Project one or more results g.local("i", "casadi_int"); g << "casadi_real** res1 = res + " << n_out_ << ";\n"; } if (project_in_) g << "for (i=0; i<" << n_in_-1 << "; ++i) arg1[i]=arg[i+1];\n"; if (project_out_) g << "for (i=0; i<" << n_out_ << "; ++i) res1[i]=res[i];\n"; // Codegen condition bool if_else = f_.size()==1; g.add_auxiliary(CodeGenerator::AUX_TO_INT); g << (if_else ? "if" : "switch") << " (arg[0] ? casadi_to_int(*arg[0]) : 0) {\n"; // Loop over cases/functions for (casadi_int k=0; k<=f_.size(); ++k) { // For if, reverse order casadi_int k1 = if_else ? 1-k : k; if (!if_else) { // Codegen cases if (k1<f_.size()) { g << "case " << k1 << ":\n"; } else { g << "default:\n"; } } else if (k1==0) { // Else g << "} else {\n"; } // Get the function: const Function& fk = k1<f_.size() ? f_[k1] : f_def_; if (fk.is_null()) { g << "return 1;\n"; } else { // Project arguments with different sparsity for (casadi_int i=0; i<n_in_-1; ++i) { const Sparsity& f_sp = fk.sparsity_in(i); const Sparsity& sp = sparsity_in_[i+1]; if (f_sp!=sp) { if (f_sp.nnz()==0) { g << "arg1[" << i << "]=0;\n"; } else { g.local("t", "casadi_real", "*"); g << "t=w, w+=" << f_sp.nnz() << ";\n" << g.project("arg1[" + str(i) + "]", sp, "t", f_sp, "w") << "\n" << "arg1[" << i << "]=t;\n"; } } } // Temporary memory for results with different sparsity for (casadi_int i=0; i<n_out_; ++i) { const Sparsity& f_sp = fk.sparsity_out(i); const Sparsity& sp = sparsity_out_[i]; if (f_sp!=sp) { if (f_sp.nnz()==0) { g << "res1[" << i << "]=0;\n"; } else { g << "res1[" << i << "]=w, w+=" << f_sp.nnz() << ";\n"; } } } // Function call g << "if (" << g(fk, project_in_ ? "arg1" : "arg+1", project_out_ ? "res1" : "res", "iw", "w") << ") return 1;\n"; // Project results with different sparsity for (casadi_int i=0; i<n_out_; ++i) { const Sparsity& f_sp = fk.sparsity_out(i); const Sparsity& sp = sparsity_out_[i]; if (f_sp!=sp) { g << g.project("res1[" + str(i) + "]", f_sp, "res[" + str(i) + "]", sp, "w") << "\n"; } } // Break (if switch) if (!if_else) g << "break;\n"; } } // End switch/else g << "}\n"; }
bool ExpressionList::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (m_kind == ListKindParam && !m_arrayElements) { return Expression::preOutputCPP(cg, ar, state|StashKidVars); } unsigned n = m_exps.size(); bool inExpression = cg.inExpression(); if (!inExpression && (state & FixOrder)) { return true; } cg.setInExpression(false); bool ret = false; if (m_arrayElements) { /* * would like to do: * ret = Expression::preOutputCPP(cg, ar, state); * but icc has problems with the generated code. */ ret = hasEffect(); } else if (n > 1 && m_kind == ListKindLeft) { ret = true; } else { for (unsigned int i = 0; i < n; i++) { if (m_exps[i]->preOutputCPP(cg, ar, 0)) { ret = true; break; } } } if (!inExpression) return ret; cg.setInExpression(true); if (!ret) { if (state & FixOrder) { preOutputStash(cg, ar, state); return true; } return false; } cg.wrapExpressionBegin(); if (m_arrayElements) { setCPPTemp(genCPPTemp(cg, ar)); outputCPPInternal(cg, ar, true, true); } else { unsigned ix = m_kind == ListKindLeft ? 0 : n - 1; for (unsigned int i = 0; i < n; i++) { ExpressionPtr e = m_exps[i]; e->preOutputCPP(cg, ar, i == ix ? state : 0); if (i != ix) { if (e->outputCPPUnneeded(cg, ar)) { cg_printf(";\n"); } e->setCPPTemp("/**/"); } else if (e->hasCPPTemp() && Type::SameType(e->getType(), getType())) { setCPPTemp(e->cppTemp()); } else if (!i && n > 1) { e->Expression::preOutputStash(cg, ar, state | FixOrder); if (!(state & FixOrder)) { cg_printf("id(%s);\n", e->cppTemp().c_str()); } setCPPTemp(e->cppTemp()); } } } return true; }