ExpressionPtr ConstantExpression::preOptimize(AnalysisResultConstPtr ar) { if (ar->getPhase() < AnalysisResult::FirstPreOptimize) { return ExpressionPtr(); } ConstructPtr decl; while (!isScalar() && !m_dynamic && !(m_context & LValue)) { const Symbol *sym = resolveNS(ar); if (!sym) { // The constant may be defined in a native extension, so check if its // available and persistent. auto const cns = Unit::lookupPersistentCns(makeStaticString(m_name)); if (!cns) break; auto const& value = tvAsCVarRef(cns); if (!value.isAllowedAsConstantValue()) break; auto rep = makeScalarExpression(ar, value); rep->setComment(getText()); copyLocationTo(rep); return replaceValue(rep); } if (!const_cast<Symbol*>(sym)->checkDefined() || sym->isDynamic()) { sym = 0; m_dynamic = true; } if (!sym) break; if (!sym->isSystem()) BlockScope::s_constMutex.lock(); auto value = dynamic_pointer_cast<Expression>(sym->getValue()); if (!sym->isSystem()) BlockScope::s_constMutex.unlock(); if (!value || !value->isScalar()) { if (!m_depsSet && sym->getDeclaration()) { sym->getDeclaration()->getScope()->addUse( getScope(), BlockScope::UseKindConstRef); m_depsSet = true; } break; } Variant scalarValue; if (value->getScalarValue(scalarValue) && !scalarValue.isAllowedAsConstantValue()) { // block further optimization const_cast<Symbol*>(sym)->setDynamic(); m_dynamic = true; break; } if (sym->isSystem() && !value->is(KindOfScalarExpression)) { if (ExpressionPtr opt = value->preOptimize(ar)) { value = opt; } } ExpressionPtr rep = Clone(value, getScope()); rep->setComment(getText()); copyLocationTo(rep); return replaceValue(rep); } return ExpressionPtr(); }
ExpressionPtr ConstantExpression::preOptimize(AnalysisResultConstPtr ar) { if (ar->getPhase() < AnalysisResult::FirstPreOptimize) { return ExpressionPtr(); } ConstructPtr decl; while (!isScalar() && !m_dynamic && !(m_context & LValue)) { const Symbol *sym = resolveNS(ar); if (sym && (!const_cast<Symbol*>(sym)->checkDefined() || sym->isDynamic())) { sym = 0; m_dynamic = true; } if (!sym) break; if (!sym->isSystem()) BlockScope::s_constMutex.lock(); auto value = dynamic_pointer_cast<Expression>(sym->getValue()); if (!sym->isSystem()) BlockScope::s_constMutex.unlock(); if (!value || !value->isScalar()) { if (!m_depsSet && sym->getDeclaration()) { sym->getDeclaration()->getScope()->addUse( getScope(), BlockScope::UseKindConstRef); m_depsSet = true; } break; } Variant scalarValue; if (value->getScalarValue(scalarValue) && !scalarValue.isAllowedAsConstantValue()) { // block further optimization const_cast<Symbol*>(sym)->setDynamic(); m_dynamic = true; break; } if (sym->isSystem() && !value->is(KindOfScalarExpression)) { if (ExpressionPtr opt = value->preOptimize(ar)) { value = opt; } } ExpressionPtr rep = Clone(value, getScope()); rep->setComment(getText()); copyLocationTo(rep); return replaceValue(rep); } return ExpressionPtr(); }
ExpressionPtr ClassConstantExpression::preOptimize(AnalysisResultConstPtr ar) { if (ar->getPhase() < AnalysisResult::FirstPreOptimize) { return ExpressionPtr(); } if (m_class) { updateClassName(); if (m_class) { return ExpressionPtr(); } } ClassScopePtr cls = resolveClass(); if (!cls || (cls->isVolatile() && !isPresent())) { if (cls && !m_depsSet) { cls->addUse(getScope(), BlockScope::UseKindConstRef); m_depsSet = true; } return ExpressionPtr(); } ConstantTablePtr constants = cls->getConstants(); ClassScopePtr defClass = cls; ConstructPtr decl = constants->getValueRecur(ar, m_varName, defClass); if (decl) { BlockScope::s_constMutex.lock(); ExpressionPtr value = dynamic_pointer_cast<Expression>(decl); BlockScope::s_constMutex.unlock(); if (!value->isScalar() && (value->is(KindOfClassConstantExpression) || value->is(KindOfConstantExpression))) { std::set<ExpressionPtr> seen; do { if (!seen.insert(value).second) return ExpressionPtr(); value = value->preOptimize(ar); if (!value) return ExpressionPtr(); } while (!value->isScalar() && (value->is(KindOfClassConstantExpression) || value->is(KindOfConstantExpression))); } ExpressionPtr rep = Clone(value, getScope()); rep->setComment(getText()); copyLocationTo(rep); return replaceValue(rep); } return ExpressionPtr(); }