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; }
bool DynamicFunctionCall::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { bool nonStatic = !m_class && m_className.empty(); if (!nonStatic && !m_class && !m_classScope && !isRedeclared()) return FunctionCall::preOutputCPP(cg, ar, state); // Short circuit out if inExpression() returns false if (!cg.inExpression()) return true; if (m_class) { m_class->preOutputCPP(cg, ar, state); } m_nameExp->preOutputCPP(cg, ar, state); cg.wrapExpressionBegin(); m_ciTemp = cg.createNewLocalId(shared_from_this()); bool lsb = false; 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 (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); } 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("mcp%d.staticMethodCall(", m_ciTemp); cg_printf("\"static\""); lsb = true; } else { cg_printf("mcp%d.dynamicNamedCall(", m_ciTemp); m_class->outputCPP(cg, ar); } cg_printf(", "); } else if (m_classScope) { cg_printf("mcp%d.staticMethodCall(\"%s\", ", m_ciTemp, m_classScope->getId(cg).c_str()); } else { cg_printf("mcp%d.staticMethodCall(\"%s\", ", m_ciTemp, m_className.c_str()); } } if (m_nameExp->is(Expression::KindOfSimpleVariable)) { m_nameExp->outputCPP(cg, ar); } else { cg_printf("("); m_nameExp->outputCPP(cg, ar); cg_printf(")"); } if (!nonStatic) { cg_printf(");\n"); if (lsb) cg_printf("mcp%d.lateStaticBind(info);\n"); cg_printf("const CallInfo *&cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp); if (m_classScope) { cg_printf("%s%s::%sget_call_info(mcp%d", Option::ClassPrefix, m_classScope->getId(cg).c_str(), Option::ObjectStaticPrefix, m_ciTemp, m_className.c_str()); } else if (isRedeclared()) { cg_printf("g->%s%s->%sget_call_info(mcp%d", Option::ClassStaticsObjectPrefix, m_className.c_str(), Option::ObjectStaticPrefix, m_ciTemp, m_className.c_str()); } } if (nonStatic || !m_class) { cg_printf(");\n"); } if (m_params && m_params->getCount() > 0) { cg.pushCallInfo(m_ciTemp); m_params->preOutputCPP(cg, ar, state); cg.popCallInfo(); } cg.pushCallInfo(m_ciTemp); preOutputStash(cg, ar, state); cg.popCallInfo(); if (!(state & FixOrder)) { cg_printf("id(%s);\n", cppTemp().c_str()); } return true; }
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, 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; }
bool NewObjectExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { string &cname = isSelf() || isParent() ? m_name : m_origName; if (m_name.empty() || !m_classScope || m_dynamic) { // Short circuit out if inExpression() returns false if (!cg.inExpression()) return true; if (m_nameExp) m_nameExp->preOutputCPP(cg, ar, state); cg.wrapExpressionBegin(); m_ciTemp = cg.createNewLocalId(shared_from_this()); m_objectTemp = cg.createNewLocalId(shared_from_this()); cg_printf("Object obj%d(", m_objectTemp); if (isRedeclared()) { bool outsideClass = !isPresent(); if (outsideClass) { ClassScope::OutputVolatileCheckBegin(cg, ar, getScope(), cname); } cg_printf("g->%s%s->createOnly()", Option::ClassStaticsObjectPrefix, m_name.c_str()); if (outsideClass) { ClassScope::OutputVolatileCheckEnd(cg); } } else { cg_printf("create_object_only("); if (!cname.empty()) { cg_printf("\"%s\"", cname.c_str()); } else if (m_nameExp->is(Expression::KindOfSimpleVariable)) { m_nameExp->outputCPP(cg, ar); } else { cg_printf("("); m_nameExp->outputCPP(cg, ar); cg_printf(")"); } cg_printf(")"); } cg_printf(");\n"); cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp, m_objectTemp); cg_printf("mcp%d.construct(obj%d);\n", m_ciTemp, m_objectTemp); 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, state); cg.popCallInfo(); } cg_printf("(cit%d->getMeth())(mcp%d, ", m_ciTemp, m_ciTemp); if (m_params && m_params->getOutputCount()) { cg.pushCallInfo(m_ciTemp); FunctionScope::OutputCPPArguments(m_params, m_funcScope, cg, ar, -1, false); cg.popCallInfo(); } else { cg_printf("Array()"); } cg_printf(");\n"); if (state & FixOrder) { cg.pushCallInfo(m_ciTemp); preOutputStash(cg, ar, state); cg.popCallInfo(); } if (hasCPPTemp() && !(state & FixOrder)) { cg_printf("id(%s);\n", cppTemp().c_str()); } return true; } else { bool tempRcvr = true; bool paramEffect = false; if (m_params && m_params->getCount() > 0) { for (int i = m_params->getCount(); i--; ) { if (!(*m_params)[i]->isScalar()) { paramEffect = true; break; } } } if (!paramEffect) { tempRcvr = false; } if (tempRcvr && cg.inExpression()) { bool outsideClass = !isPresent(); cg.wrapExpressionBegin(); m_receiverTemp = genCPPTemp(cg, ar); cg_printf("%s%s %s = ", Option::SmartPtrPrefix, m_classScope->getId(cg).c_str(), m_receiverTemp.c_str()); if (outsideClass) { m_classScope->outputVolatileCheckBegin(cg, ar, getScope(), cname); } cg_printf("NEWOBJ(%s%s)()", Option::ClassPrefix, m_classScope->getId(cg).c_str()); if (outsideClass) { m_classScope->outputVolatileCheckEnd(cg); } cg_printf(";\n"); } bool tempParams = FunctionCall::preOutputCPP(cg, ar, state); return tempRcvr || tempParams; } }
bool ObjectMethodExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (!m_name.empty() && m_valid && m_object->getType()->isSpecificObject()) { return FunctionCall::preOutputCPP(cg, ar, state); } // Short circuit out if inExpression() returns false if (!cg.inExpression()) return true; m_ciTemp = cg.createNewId(shared_from_this()); cg.wrapExpressionBegin(); bool isThis = m_object->isThis(); if (!isThis) { m_object->preOutputCPP(cg, ar, state); } if (m_name.empty()) { m_nameExp->preOutputCPP(cg, ar, state); } const MethodSlot *ms = NULL; if (!m_name.empty()) { ConstructPtr self = shared_from_this(); ms = ar->getOrAddMethodSlot(m_name, self); } cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp); if (ms) { cg_printf("mcp%d.methodCallWithIndex((", m_ciTemp); } else { cg_printf("mcp%d.methodCall((", m_ciTemp); } if (isThis) { cg_printf("GET_THIS()"); } else { outputCPPObject(cg, ar); } cg_printf("), "); if (!m_name.empty()) { uint64 hash = hash_string_i(m_name.c_str()); cg_printString(m_origName, ar, shared_from_this()); if (ms) { cg_printf(", %s", ms->runObjParam().c_str()); } cg_printf(", 0x%016llXLL);\n", hash); } else { m_nameExp->outputCPP(cg, ar); cg_printf(", -1);\n"); } cg_printf("const CallInfo *cit%d __attribute__((__unused__)) =" " mcp%d.ci;\n", m_ciTemp, m_ciTemp); if (m_params && m_params->getCount() > 0) { cg.pushCallInfo(m_ciTemp); m_params->preOutputCPP(cg, ar, state); cg.popCallInfo(); } if (state & FixOrder) { cg.pushCallInfo(m_ciTemp); preOutputStash(cg, ar, state); cg.popCallInfo(); } if (hasCPPTemp() && !(state & FixOrder)) { cg_printf("id(%s);\n", cppTemp().c_str()); } return true; }
bool BinaryOpExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (isOpEqual()) return Expression::preOutputCPP(cg, ar, state); bool effect2 = m_exp2->hasEffect(); const char *prefix = 0; if (effect2 || m_exp1->hasEffect()) { ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this()); ExpressionPtrVec ev; bool hasVoid = false; int numConcat = 0; bool ok = false; if (m_op == '.') { numConcat = getConcatList(ev, self, hasVoid); ok = hasVoid || (numConcat > MAX_CONCAT_ARGS && (!Option::GenConcat || cg.getOutput() == CodeGenerator::SystemCPP)); } else if (effect2 && m_op == T_CONCAT_EQUAL) { prefix = stringBufferPrefix(cg, ar, m_exp1); ok = prefix; if (!ok) { if (m_exp1->is(KindOfSimpleVariable)) { ok = true; ev.push_back(m_exp1); numConcat++; } } numConcat += getConcatList(ev, m_exp2, hasVoid); } if (ok) { if (!cg.inExpression()) return true; cg.wrapExpressionBegin(); std::string buf; if (prefix) { SimpleVariablePtr sv(static_pointer_cast<SimpleVariable>(m_exp1)); buf = stringBufferName(Option::TempPrefix, prefix, sv->getName().c_str()); m_cppTemp = "/**/"; } else if (numConcat) { buf = m_cppTemp = genCPPTemp(cg, ar); buf += "_buf"; cg_printf("StringBuffer %s;\n", buf.c_str()); } else { m_cppTemp = "\"\""; } for (size_t i = 0; i < ev.size(); i++) { ExpressionPtr exp = ev[i]; bool is_void = !exp->getActualType(); exp->preOutputCPP(cg, ar, 0); if (!is_void) { cg_printf("%s.append(", buf.c_str()); outputStringExpr(cg, ar, exp, true); cg_printf(")"); } else { exp->outputCPPUnneeded(cg, ar); } cg_printf(";\n"); } if (numConcat && !prefix) { cg_printf("CStrRef %s(%s.detach());\n", m_cppTemp.c_str(), buf.c_str()); if (m_op == T_CONCAT_EQUAL) { m_exp1->outputCPP(cg, ar); cg_printf(" = %s;\n", m_cppTemp.c_str()); } } return true; } } if (!isShortCircuitOperator()) { return Expression::preOutputCPP(cg, ar, state); } if (!effect2) { return m_exp1->preOutputCPP(cg, ar, state); } bool fix_e1 = m_exp1->preOutputCPP(cg, ar, 0); if (!cg.inExpression()) { return fix_e1 || m_exp2->preOutputCPP(cg, ar, 0); } cg.setInExpression(false); bool fix_e2 = m_exp2->preOutputCPP(cg, ar, 0); cg.setInExpression(true); if (fix_e2) { cg.wrapExpressionBegin(); std::string tmp = genCPPTemp(cg, ar); cg_printf("bool %s = (", tmp.c_str()); m_exp1->outputCPP(cg, ar); cg_printf(");\n"); cg_indentBegin("if (%s%s) {\n", m_op == T_LOGICAL_OR || m_op == T_BOOLEAN_OR ? "!" : "", tmp.c_str()); m_exp2->preOutputCPP(cg, ar, 0); cg_printf("%s = (", tmp.c_str()); m_exp2->outputCPP(cg, ar); cg_printf(");\n"); cg_indentEnd("}\n"); m_cppTemp = tmp; } else if (state & FixOrder) { preOutputStash(cg, ar, state); fix_e1 = true; } return fix_e1 || fix_e2; }
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; }
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; }
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; }
bool ObjectMethodExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (!m_name.empty() && m_valid && m_object->getType()->isSpecificObject()) { if (m_object->hasEffect()) { if (cg.inExpression()) { m_object->preOutputCPP(cg, ar, FixOrder); if (m_params) m_params->preOutputCPP(cg, ar, 0); if (state & FixOrder) { preOutputStash(cg, ar, state); } } return true; } return FunctionCall::preOutputCPP(cg, ar, state); } // Short circuit out if inExpression() returns false if (!cg.inExpression()) return true; cg.wrapExpressionBegin(); m_ciTemp = cg.createNewLocalId(shared_from_this()); if (outputLineMap(cg, ar)) cg_printf("0);\n"); bool isThis = m_object->isThis(); if (!isThis) { int s = 0; if (m_name.empty() && m_nameExp->hasEffect() && !m_object->isScalar()) { s = FixOrder; } m_object->preOutputCPP(cg, ar, s); } if (m_name.empty()) { m_nameExp->preOutputCPP(cg, ar, 0); } const MethodSlot *ms = NULL; if (!m_name.empty()) { ConstructPtr self = shared_from_this(); ms = ar->getOrAddMethodSlot(m_name, self); } cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp); if (!isThis) { TypePtr t = m_object->getType(); if (t && t->is(Type::KindOfObject)) { cg_printf("CObjRef obj%d = ", m_ciTemp); } else { cg_printf("CVarRef obj%d = ", m_ciTemp); } outputCPPObject(cg, ar); cg_printf(";\n"); } if (m_name.empty()) { cg_printf("CStrRef mth%d = ", m_ciTemp); m_nameExp->outputCPP(cg, ar); cg_printf(";\n"); } if (ms) { cg_printf("mcp%d.methodCallWithIndex((", m_ciTemp); } else { cg_printf("mcp%d.methodCall((", m_ciTemp); } if (isThis) { if (!getClassScope() || getClassScope()->derivedByDynamic() || !static_pointer_cast<SimpleVariable>(m_object)->isGuardedThis()) { cg_printf("GET_THIS_VALID()"); } else { cg_printf("this"); } } else { cg_printf("obj%d", m_ciTemp); } cg_printf("), "); if (!m_name.empty()) { uint64 hash = hash_string_i(m_name.c_str()); cg_printString(m_origName, ar, shared_from_this()); if (ms) { cg_printf(", %s", ms->runObjParam().c_str()); } cg_printf(", 0x%016llXLL);\n", hash); } else { cg_printf("mth%d, -1);\n", m_ciTemp); } cg_printf("const CallInfo *cit%d ATTRIBUTE_UNUSED = 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; }
bool NewObjectExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (m_classScope && (m_classScope->isAbstract() || m_classScope->isInterface() || m_classScope->isTrait())) { return false; } string &cname = isSelf() || isParent() ? m_name : m_origName; if (m_name.empty() || !m_classScope || m_dynamic) { // Short circuit out if inExpression() returns false if (!cg.inExpression()) return true; if (m_nameExp) m_nameExp->preOutputCPP(cg, ar, 0); cg.wrapExpressionBegin(); m_ciTemp = cg.createNewLocalId(shared_from_this()); m_objectTemp = cg.createNewLocalId(shared_from_this()); cg_printf("Object obj%d(", m_objectTemp); if (isRedeclared()) { bool outsideClass = !isPresent(); if (outsideClass) { ClassScope::OutputVolatileCheckBegin(cg, ar, getScope(), cname); } cg_printf("g->%s%s->createOnly()", Option::ClassStaticsCallbackPrefix, m_name.c_str()); if (outsideClass) { ClassScope::OutputVolatileCheckEnd(cg); } } else { cg_printf("create_object_only("); if (isStatic()) { cg_printf("FrameInjection::GetStaticClassName(fi.getThreadInfo())"); } else if (!cname.empty()) { cg_printString(cname, ar, getScope(), true); } else if (m_nameExp->is(Expression::KindOfSimpleVariable)) { m_nameExp->outputCPP(cg, ar); } else { cg_printf("("); m_nameExp->outputCPP(cg, ar); cg_printf(")"); } cg_printf(")"); } cg_printf(");\n"); cg_printf("MethodCallPackage mcp%d;\n", m_ciTemp); cg_printf("mcp%d.construct(obj%d);\n", m_ciTemp, m_objectTemp); cg_printf("const CallInfo *cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp); int pcount = m_params ? m_params->getCount() : 0; if (pcount > 0) { cg.pushCallInfo(m_ciTemp); m_params->preOutputCPP(cg, ar, 0); cg.popCallInfo(); } cg_printf("(cit%d->", m_ciTemp); outputDynamicCall(cg, ar, true); cg_printf(";\n"); if (state & FixOrder) { cg.pushCallInfo(m_ciTemp); preOutputStash(cg, ar, state); cg.popCallInfo(); } return true; } else { bool tempRcvr = true; bool paramEffect = false; if (m_params && m_params->getCount() > 0) { for (int i = m_params->getCount(); i--; ) { if (!(*m_params)[i]->isScalar()) { paramEffect = true; break; } } } if (!paramEffect) { tempRcvr = false; } if (tempRcvr && cg.inExpression()) { bool outsideClass = !isPresent(); cg.wrapExpressionBegin(); m_receiverTemp = genCPPTemp(cg, ar); cg_printf("%s%s %s = ", Option::SmartPtrPrefix, m_classScope->getId().c_str(), m_receiverTemp.c_str()); if (outsideClass) { m_classScope->outputVolatileCheckBegin(cg, ar, getScope(), cname); } cg_printf("%s%s()", Option::CreateObjectOnlyPrefix, m_classScope->getId().c_str()); if (outsideClass) { m_classScope->outputVolatileCheckEnd(cg); } cg_printf(";\n"); } bool tempParams = FunctionCall::preOutputCPP(cg, ar, state); return tempRcvr || tempParams; } }
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; return FunctionCall::preOutputCPP(cg, ar, state); } // Short circuit out if inExpression() returns false if (!cg.inExpression()) return true; cg.wrapExpressionBegin(); m_ciTemp = cg.createNewLocalId(shared_from_this()); bool lsb = false; 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(")"); } } 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 = ", m_ciTemp); cg_printString("static", ar, shared_from_this()); lsb = true; } else { cg_printf("CVarRef cls%d = ", 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"); if (m_class) { if (m_class->is(KindOfScalarExpression)) { cg_printf("mcp%d.staticMethodCall(cls%d, mth%d", m_ciTemp, m_ciTemp, m_ciTemp); } else { cg_printf("mcp%d.dynamicNamedCall(cls%d, mth%d", m_ciTemp, m_ciTemp, m_ciTemp); } } else { cg_printf("mcp%d.staticMethodCall(cls%d, mth%d", m_ciTemp, m_ciTemp, m_ciTemp); } } if (!nonStatic) { cg_printf(");\n"); if (lsb) cg_printf("mcp%d.lateStaticBind(fi.getThreadInfo());\n", m_ciTemp); cg_printf("const CallInfo *&cit%d = mcp%d.ci;\n", m_ciTemp, m_ciTemp); if (m_classScope) { cg_printf("%s%s.%sget_call_info(mcp%d", Option::ClassStaticsCallbackPrefix, m_classScope->getId().c_str(), Option::ObjectStaticPrefix, m_ciTemp); } else if (isRedeclared()) { cg_printf("g->%s%s->%sget_call_info(mcp%d", Option::ClassStaticsCallbackPrefix, m_className.c_str(), Option::ObjectStaticPrefix, m_ciTemp); } } if (nonStatic || !m_class) { cg_printf(");\n"); } 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; }
bool UnaryOpExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (m_op == T_ISSET && m_exp && m_exp->is(Expression::KindOfExpressionList)) { ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp); int count = exps->getCount(); if (count > 1) { bool fix_e1 = (*exps)[0]->preOutputCPP(cg, ar, 0); bool inExpression = cg.inExpression(); cg.setInExpression(false); bool fix_en = false; for (int i = 1; i < count; i++) { if ((*exps)[i]->preOutputCPP(cg, ar, 0)) { fix_en = true; break; } } cg.setInExpression(inExpression); if (inExpression && fix_en) { cg.wrapExpressionBegin(); std::string tmp = genCPPTemp(cg, ar); cg_printf("bool %s = (", tmp.c_str()); (*exps)[0]->outputCPPExistTest(cg, ar, m_op); cg_printf(");\n"); for (int i = 1; i < count; i++) { cg_indentBegin("if (%s) {\n", tmp.c_str()); ExpressionPtr e = (*exps)[i]; e->preOutputCPP(cg, ar, 0); cg_printf("%s = (", tmp.c_str()); e->outputCPPExistTest(cg, ar, m_op); cg_printf(");\n"); } for (int i = 1; i < count; i++) { cg_indentEnd("}\n"); } m_cppTemp = tmp; } else if (state & FixOrder) { preOutputStash(cg, ar, state); fix_e1 = true; } return fix_e1 || fix_en; } } if (m_op == '@') { if (isUnused()) m_exp->setUnused(true); bool doit = (state & FixOrder) || m_exp->hasEffect(); if (doit && cg.inExpression()) { cg.wrapExpressionBegin(); std::string tmp = genCPPTemp(cg, ar); cg_printf("Silencer %s(true);\n", tmp.c_str()); m_exp->preOutputCPP(cg, ar, 0); this->preOutputStash(cg, ar, state | FixOrder | StashAll); cg_printf("%s.disable();\n", tmp.c_str()); } return doit; } else if (m_op == T_PRINT && m_exp && !m_exp->hasEffect()) { ExpressionPtrVec ev; bool hasVoid = false; if (BinaryOpExpression::getConcatList(ev, m_exp, hasVoid) > 1 || hasVoid ) { if (!cg.inExpression()) return true; cg.wrapExpressionBegin(); for (int i = 0, s = ev.size(); i < s; i++) { ExpressionPtr e = ev[i]; e->preOutputCPP(cg, ar, 0); cg_printf("print("); e->outputCPP(cg, ar); cg_printf(");\n"); } m_cppTemp = "id(1)"; return true; } } if (m_op == T_CLASS || m_op == T_FUNCTION) { if (cg.inExpression()) { cg.wrapExpressionBegin(); m_definedScope->outputCPPDef(cg); setCPPTemp("id(0)"); } return true; } return Expression::preOutputCPP(cg, ar, state); }