bool AssignmentExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (m_variable->is(Expression::KindOfArrayElementExpression)) { ExpressionPtr exp = m_value; ExpressionPtr vv( static_pointer_cast<ArrayElementExpression>(m_variable)->getVariable()); if ((vv->is(KindOfArrayElementExpression) || vv->is(KindOfObjectPropertyExpression)) && (vv->getContainedEffects() && (CreateEffect|AccessorEffect))) { /* We are in a case such as $a->b['c'] = ...; $a['b']['c'] = ...; Where evaluating m_variable may modify $a. Unless we can prove that the rhs is not referring to the same thing as $a, we must generate a temporary for it (note that we could do better with the following checks). */ if (!(m_ref && exp->isRefable()) && !exp->isTemporary() && !exp->isScalar() && exp->getActualType() && !exp->getActualType()->isPrimitive() && exp->getActualType()->getKindOf() != Type::KindOfString) { state |= Expression::StashAll; } } } return Expression::preOutputCPP(cg, ar, state); }
ExpressionPtr Expression::replaceValue(ExpressionPtr rep, bool noWarn) { if (hasContext(Expression::RefValue) && isRefable(true) && !rep->isRefable(true)) { /* An assignment isRefable, but the rhs may not be. Need this to prevent "bad pass by reference" errors. */ auto el = std::make_shared<ExpressionList>( getScope(), getRange(), noWarn ? ExpressionList::ListKindWrappedNoWarn : ExpressionList::ListKindWrapped); el->addElement(rep); rep->clearContext(AssignmentRHS); rep = el; } if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) { static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash(); } rep->copyContext(m_context & ~(DeadStore|AccessContext)); if (rep->getScope() != getScope()) { rep->resetScope(getScope()); } return rep; }
ExpressionPtr Expression::replaceValue(ExpressionPtr rep) { if (hasContext(Expression::RefValue) && isRefable(true) && !rep->isRefable(true)) { /* An assignment isRefable, but the rhs may not be. Need this to prevent "bad pass by reference" errors. */ ExpressionListPtr el(new ExpressionList(getScope(), getRange(), ExpressionList::ListKindWrapped)); el->addElement(rep); rep->clearContext(AssignmentRHS); rep = el; } if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) { static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash(); } rep->copyContext(m_context & ~(DeadStore|AccessContext)); if (TypePtr t1 = getType()) { if (TypePtr t2 = rep->getType()) { if (!Type::SameType(t1, t2)) { rep->setExpectedType(t1); } } } if (rep->getScope() != getScope()) { rep->resetScope(getScope()); } return rep; }
void FunctionScope::outputCPPArguments(ExpressionListPtr params, CodeGenerator &cg, AnalysisResultPtr ar, int extraArg, bool variableArgument, int extraArgArrayId /* = -1 */) { int paramCount = params ? params->getOutputCount() : 0; ASSERT(extraArg <= paramCount); int iMax = paramCount - extraArg; bool extra = false; if (variableArgument) { if (paramCount == 0) { cg.printf("0"); } else { cg.printf("%d, ", paramCount); } } int firstExtra = 0; for (int i = 0; i < paramCount; i++) { ExpressionPtr param = (*params)[i]; cg.setItemIndex(i); if (i > 0) cg.printf(extra ? "." : ", "); if (!extra && (i == iMax || extraArg < 0)) { if (extraArgArrayId != -1) { if (cg.getOutput() == CodeGenerator::SystemCPP) { cg.printf("SystemScalarArrays::%s[%d]", Option::SystemScalarArrayName, extraArgArrayId); } else { cg.printf("ScalarArrays::%s[%d]", Option::ScalarArrayName, extraArgArrayId); } break; } extra = true; // Parameter arrays are always vectors. cg.printf("Array(ArrayInit(%d, true).", paramCount - i); firstExtra = i; } if (extra) { bool needRef = param->hasContext(Expression::RefValue) && !param->hasContext(Expression::NoRefWrapper) && param->isRefable(); cg.printf("set%s(%d, ", needRef ? "Ref" : "", i - firstExtra); if (needRef) { // The parameter itself shouldn't be wrapped with ref() any more. param->setContext(Expression::NoRefWrapper); } param->outputCPP(cg, ar); cg.printf(")"); } else { param->outputCPP(cg, ar); } } if (extra) { cg.printf(".create())"); } }
bool AssignmentExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { if (m_variable->is(Expression::KindOfArrayElementExpression)) { ExpressionPtr exp = m_value; if (!(m_ref && exp->isRefable()) && !exp->isTemporary() && !exp->isScalar() && exp->getActualType() && !exp->getActualType()->isPrimitive() && exp->getActualType()->getKindOf() != Type::KindOfString) { state |= Expression::StashAll; } } return Expression::preOutputCPP(cg, ar, state); }
static int cloneStmtsForInline(InlineCloneInfo &info, StatementPtr s, const std::string &prefix, AnalysisResultConstPtr ar, FunctionScopePtr scope) { switch (s->getKindOf()) { case Statement::KindOfStatementList: { for (int i = 0, n = s->getKidCount(); i < n; ++i) { if (int ret = cloneStmtsForInline(info, s->getNthStmt(i), prefix, ar, scope)) { return ret; } } return 0; } case Statement::KindOfExpStatement: info.elist->addElement(cloneForInline( info, dynamic_pointer_cast<ExpStatement>(s)-> getExpression(), prefix, ar, scope)); return 0; case Statement::KindOfReturnStatement: { ExpressionPtr exp = dynamic_pointer_cast<ReturnStatement>(s)->getRetExp(); if (exp) { exp = cloneForInline(info, exp, prefix, ar, scope); if (exp->hasContext(Expression::RefValue)) { exp->clearContext(Expression::RefValue); if (exp->isRefable()) exp->setContext(Expression::LValue); } info.elist->addElement(exp); return 1; } return -1; } default: not_reached(); } return 1; }
void FunctionScope::outputCPPArguments(ExpressionListPtr params, CodeGenerator &cg, AnalysisResultPtr ar, int extraArg, bool variableArgument, int extraArgArrayId /* = -1 */, int extraArgArrayHash /* = -1 */, int extraArgArrayIndex /* = -1 */) { int paramCount = params ? params->getOutputCount() : 0; ASSERT(extraArg <= paramCount); int iMax = paramCount - extraArg; bool extra = false; if (variableArgument) { if (paramCount == 0) { cg_printf("0"); } else { cg_printf("%d, ", paramCount); } } int firstExtra = 0; for (int i = 0; i < paramCount; i++) { ExpressionPtr param = (*params)[i]; cg.setItemIndex(i); if (i > 0) cg_printf(extra ? "." : ", "); if (!extra && (i == iMax || extraArg < 0)) { if (extraArgArrayId != -1) { assert(extraArgArrayHash != -1 && extraArgArrayIndex != -1); ar->outputCPPScalarArrayId(cg, extraArgArrayId, extraArgArrayHash, extraArgArrayIndex); break; } extra = true; // Parameter arrays are always vectors. if (Option::GenArrayCreate && cg.getOutput() != CodeGenerator::SystemCPP) { if (!params->hasNonArrayCreateValue(false, i)) { ar->m_arrayIntegerKeySizes.insert(paramCount - i); cg_printf("Array("); params->outputCPPUniqLitKeyArrayInit(cg, ar, paramCount - i, false, i); cg_printf(")"); return; } } firstExtra = i; cg_printf("Array(ArrayInit(%d, true).", paramCount - i); } if (extra) { bool needRef = param->hasContext(Expression::RefValue) && !param->hasContext(Expression::NoRefWrapper) && param->isRefable(); cg_printf("set%s(", needRef ? "Ref" : ""); if (needRef) { // The parameter itself shouldn't be wrapped with ref() any more. param->setContext(Expression::NoRefWrapper); } param->outputCPP(cg, ar); cg_printf(")"); } else { param->outputCPP(cg, ar); } } if (extra) { cg_printf(".create())"); } }