예제 #1
0
TypePtr ConstantTable::add(const std::string &name, TypePtr type,
                           ExpressionPtr exp, AnalysisResultConstPtr ar,
                           ConstructPtr construct) {

  if (name == "true" || name == "false") {
    return Type::Boolean;
  }

  Symbol *sym = genSymbol(name, true);
  if (!sym->declarationSet()) {
    setType(ar, sym, type, true);
    sym->setDeclaration(construct);
    sym->setValue(exp);
    return type;
  }

  if (m_blockScope.isFirstPass()) {
    if (construct) {
      if (exp != sym->getValue()) {
        Compiler::Error(Compiler::DeclaredConstantTwice, construct,
                        sym->getDeclaration());
        if (!sym->isDynamic()) {
          sym->setDynamic();
          m_hasDynamic = true;
        }
        type = Type::Variant;
      }
    } else if (exp) {
      sym->setValue(exp);
    }
    setType(ar, sym, type, true);
  }

  return type;
}
예제 #2
0
void VariableTable::forceVariants(AnalysisResultConstPtr ar, int varClass,
                                  bool recur /* = true */) {
  int mask = varClass & ~m_forcedVariants;
  if (mask) {
    if (!m_hasPrivate) mask &= ~AnyPrivateVars;
    if (!m_hasStatic) mask &= ~AnyStaticVars;

    if (mask) {
      for (unsigned int i = 0; i < m_symbolVec.size(); i++) {
        Symbol *sym = m_symbolVec[i];
        if (!sym->isHidden() && sym->declarationSet() &&
            mask & GetVarClassMaskForSym(sym)) {
          setType(ar, sym, Type::Variant, true);
          sym->setIndirectAltered();
        }
      }
    }
    m_forcedVariants |= varClass;

    if (recur) {
      ClassScopePtr parent = m_blockScope.getParentScope(ar);
      if (parent && !parent->isRedeclaring()) {
        parent->getVariables()->forceVariants(ar, varClass & ~AnyPrivateVars);
      }
    }
  }
}
예제 #3
0
Symbol *VariableTable::findProperty(ClassScopePtr &cls,
                                    const string &name,
                                    AnalysisResultConstPtr ar) {
  Symbol *sym = getSymbol(name);
  if (sym) {
    assert(sym->declarationSet());
    if (!sym->isOverride()) {
      return sym;
    }
    assert(!sym->isStatic());
    sym = nullptr;
  }

  if (!sym) {
    if (ClassScopePtr parent = findParent(ar, name, sym)) {
      sym = parent->findProperty(parent, name, ar);
      if (sym) {
        cls = parent;
        return sym;
      }
    }
  }

  return sym;
}
예제 #4
0
Symbol *SymbolTable::genSymbol(const std::string &name, bool konst,
                               ConstructPtr construct) {
  Symbol *sym = genSymbol(name, konst);
  if (!sym->declarationSet() && construct) {
    m_symbolVec.push_back(sym);
    sym->setDeclaration(construct);
  }
  return sym;
}
예제 #5
0
void ConstantTable::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) {
  bool decl = true;
  if (cg.getContext() == CodeGenerator::CppConstantsDecl) {
    decl = false;
  }

  bool printed = false;
  for (StringToSymbolMap::iterator iter = m_symbolMap.begin(),
         end = m_symbolMap.end(); iter != end; ++iter) {
    Symbol *sym = &iter->second;
    if (!sym->declarationSet() || sym->isDynamic()) continue;
    if (sym->isSystem() && cg.getOutput() != CodeGenerator::SystemCPP) continue;
    const string &name = sym->getName();
    ConstructPtr value = sym->getValue();
    printed = true;

    cg_printf(decl ? "extern const " : "const ");
    TypePtr type = sym->getFinalType();
    bool isString = type->is(Type::KindOfString);
    if (isString) {
      cg_printf("StaticString");
    } else {
      type->outputCPPDecl(cg, ar);
    }
    if (decl) {
      cg_printf(" %s%s", Option::ConstantPrefix,
                cg.formatLabel(name).c_str());
    } else {
      cg_printf(" %s%s", Option::ConstantPrefix,
                cg.formatLabel(name).c_str());
      cg_printf(isString ? "(" : " = ");
      if (value) {
        ExpressionPtr exp = dynamic_pointer_cast<Expression>(value);
        ASSERT(!exp->getExpectedType());
        ScalarExpressionPtr scalarExp =
          dynamic_pointer_cast<ScalarExpression>(exp);
        if (isString && scalarExp) {
          cg_printf("LITSTR_INIT(%s)",
                    scalarExp->getCPPLiteralString(cg).c_str());
        } else {
          exp->outputCPP(cg, ar);
        }
      } else {
        cg_printf("\"%s\"", cg.escapeLabel(name).c_str());
      }
      if (isString) {
        cg_printf(")");
      }
    }
    cg_printf(";\n");
  }
  if (printed) {
    cg_printf("\n");
  }
}
예제 #6
0
void ConstantTable::collectCPPGlobalSymbols(StringPairVec &symbols,
                                            CodeGenerator &cg,
                                            AnalysisResultPtr ar) {
  for (StringToSymbolMap::iterator iter = m_symbolMap.begin(),
         end = m_symbolMap.end(); iter != end; ++iter) {
    Symbol *sym = &iter->second;
    if (sym->declarationSet() && sym->isDynamic()) {
      string varname = Option::ConstantPrefix + cg.formatLabel(sym->getName());
      symbols.push_back(pair<string, string>(varname, varname));
    }
  }
}
예제 #7
0
void ConstantTable::outputCPPDynamicImpl(CodeGenerator &cg,
                                         AnalysisResultPtr ar) {
  for (StringToSymbolMap::iterator iter = m_symbolMap.begin(),
         end = m_symbolMap.end(); iter != end; ++iter) {
    Symbol *sym = &iter->second;
    if (sym->declarationSet() && sym->isDynamic()) {
      cg_printf("%s%s = \"%s\";\n", Option::ConstantPrefix,
                cg.formatLabel(sym->getName()).c_str(),
                cg.escapeLabel(sym->getName()).c_str());
    }
  }
}
예제 #8
0
void Symbol::import(BlockScopeRawPtr scope, const Symbol &src_sym) {
  setName(src_sym.getName());
  setSystem();
  if (src_sym.declarationSet()) {
    ConstructPtr sc = src_sym.getDeclaration();
    if (sc) sc->resetScope(scope);
    setDeclaration(sc);
  }
  if (src_sym.valueSet()) {
    ConstructPtr sc = src_sym.getValue();
    if (sc) sc->resetScope(scope);
    setValue(sc);
  }
  if (src_sym.isDynamic()) {
    setDynamic();
  }
  if (src_sym.isConstant()) {
    setConstant();
  }
}
예제 #9
0
void ConstantTable::outputCPPDynamicDecl(CodeGenerator &cg,
                                         AnalysisResultPtr ar) {
  const char *prefix = Option::ConstantPrefix;
  string classId;
  const char *fmt = "Variant %s%s%s;\n";
  ClassScopePtr scope = ar->getClassScope();
  if (scope) {
    prefix = Option::ClassConstantPrefix;
    classId = scope->getId(cg);
    fmt = "Variant %s%s_%s;\n";
  }

  for (StringToSymbolMap::iterator iter = m_symbolMap.begin(),
         end = m_symbolMap.end(); iter != end; ++iter) {
    Symbol *sym = &iter->second;
    if (sym->declarationSet() && sym->isDynamic()) {
      cg_printf(fmt, prefix, classId.c_str(),
                cg.formatLabel(sym->getName()).c_str());
    }
  }
}
예제 #10
0
void MethodStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  FunctionScopeRawPtr funcScope = getFunctionScope();
  ClassScopePtr scope = getClassScope();

  if (outputFFI(cg, ar)) return;

  cg.setPHPLineNo(-1);

  CodeGenerator::Context context = cg.getContext();

  if (context == CodeGenerator::CppImplementation) {
    printSource(cg);
  }

  bool isWrapper = context == CodeGenerator::CppTypedParamsWrapperDecl ||
    context == CodeGenerator::CppTypedParamsWrapperImpl;

  bool needsWrapper = isWrapper ||
    (Option::HardTypeHints && funcScope->needsTypeCheckWrapper());

  const char *prefix = needsWrapper && !isWrapper ?
    Option::TypedMethodPrefix : Option::MethodPrefix;

  switch (context) {
    case CodeGenerator::CppDeclaration:
    case CodeGenerator::CppTypedParamsWrapperDecl:
    {
      if (!m_stmt && !funcScope->isPerfectVirtual()) {
        cg_printf("// ");
      }

      m_modifiers->outputCPP(cg, ar);

      if (!m_stmt || m_name == "__offsetget_lval" ||
          funcScope->isPerfectVirtual()) {
        cg_printf("virtual ");
      }
      TypePtr type = funcScope->getReturnType();
      if (type) {
        type->outputCPPDecl(cg, ar, getScope());
      } else {
        cg_printf("void");
      }
      if (m_name == "__offsetget_lval") {
        cg_printf(" &___offsetget_lval(");
      } else if (m_modifiers->isStatic() && m_stmt) {
        // Static method wrappers get generated as support methods
        cg_printf(" %s%s(CStrRef cls%s",
                  needsWrapper && !isWrapper ?
                  Option::TypedMethodImplPrefix : Option::MethodImplPrefix,
                  cg.formatLabel(m_name).c_str(),
                  funcScope->isVariableArgument() ||
                  (m_params && m_params->getCount()) ? ", " : "");
      } else {
        cg_printf(" %s%s(", prefix, cg.formatLabel(m_name).c_str());
      }
      funcScope->outputCPPParamsDecl(cg, ar, m_params, true);
      if (m_stmt) {
        cg_printf(");\n");
      } else if (funcScope->isPerfectVirtual()) {
        cg_printf(") { return throw_fatal(\"pure virtual\");}\n");
      } else {
        cg_printf(") = 0;\n");
      }

      if (context != CodeGenerator::CppTypedParamsWrapperDecl) {
        if (funcScope->isConstructor(scope)
            && !funcScope->isAbstract() && !scope->isInterface()) {
          funcScope->outputCPPCreateDecl(cg, ar);
        }
        if (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()) {
          cg.setContext(CodeGenerator::CppTypedParamsWrapperDecl);
          outputCPPImpl(cg, ar);
          cg.setContext(context);
        }
      }
    }
    break;
    case CodeGenerator::CppImplementation:
    case CodeGenerator::CppTypedParamsWrapperImpl:
      if (m_stmt) {
        TypePtr type = funcScope->getReturnType();
        if (type) {
          type->outputCPPDecl(cg, ar, getScope());
        } else {
          cg_printf("void");
        }
        string origFuncName = getOriginalFullName();
        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 (m_name == "__offsetget_lval") {
          cg_printf(" &%s%s::___offsetget_lval(",
                    Option::ClassPrefix, scope->getId(cg).c_str());
        } else if (m_modifiers->isStatic()) {
          cg_printf(" %s%s::%s%s(CStrRef cls%s", Option::ClassPrefix,
                    scope->getId(cg).c_str(),
                    needsWrapper && !isWrapper ?
                    Option::TypedMethodImplPrefix : Option::MethodImplPrefix,
                    cg.formatLabel(m_name).c_str(),
                    funcScope->isVariableArgument() ||
                    (m_params && m_params->getCount()) ? ", " : "");
        } else {
          cg_printf(" %s%s::%s%s(", Option::ClassPrefix,
                    scope->getId(cg).c_str(),
                    prefix, cg.formatLabel(m_name).c_str());
        }
        funcScope->outputCPPParamsDecl(cg, ar, m_params, false);
        cg_indentBegin(") {\n");
        if (context != CodeGenerator::CppTypedParamsWrapperImpl) {
          if (m_stmt->hasBody()) {
            const char *sys =
              (cg.getOutput() == CodeGenerator::SystemCPP ? "_BUILTIN" : "");
            if (m_modifiers->isStatic()) {
              cg_printf("STATIC_METHOD_INJECTION%s(%s, %s);\n", sys,
                        scope->getOriginalName().c_str(),
                        origFuncName.c_str());
            } else if (cg.getOutput() != CodeGenerator::SystemCPP &&
                       !scope->isRedeclaring() && !scope->derivedByDynamic()) {
              cg_printf("INSTANCE_METHOD_INJECTION_ROOTLESS(%s, %s);\n",
                        scope->getOriginalName().c_str(),
                        origFuncName.c_str());
            } else if (scope->getOriginalName() != "XhprofFrame") {
              cg_printf("INSTANCE_METHOD_INJECTION%s(%s, %s);\n", sys,
                        scope->getOriginalName().c_str(),
                        origFuncName.c_str());
            }
          }
          outputCPPArgInjections(cg, ar, origFuncName.c_str(),
                                 scope, funcScope);
          if (m_name == "__offsetget_lval") {
            ParameterExpressionPtr param =
              dynamic_pointer_cast<ParameterExpression>((*m_params)[0]);
            cg_printf("Variant &v = %s->__lvalProxy;\n", cg.getGlobals(ar));
            string lowered = Util::toLower(m_originalName);
            cg_printf("v = %s%s(%s%s);\n",
                      prefix, lowered.c_str(),
                      Option::VariablePrefix, param->getName().c_str());
            cg_printf("return v;\n");
          } else {
            if (funcScope->isConstructor(scope)) {
              cg_printf("bool oldInCtor = gasInCtor(true);\n");
            } else if (m_name == "__destruct") {
              cg_printf("setInDtor();\n");
            }
            funcScope->outputCPP(cg, ar);
            cg.setContext(
              CodeGenerator::NoContext); // no inner functions/classes
            if (!funcScope->isStatic() && funcScope->getVariables()->
                getAttribute(VariableTable::ContainsDynamicVariable)) {
              Symbol *sym = funcScope->getVariables()->getSymbol("this");
              if (sym && sym->declarationSet()) {
                cg_printf("%sthis = this;\n", Option::VariablePrefix);
              }
            }
            outputCPPStmt(cg, ar);
          }
          cg_indentEnd("}\n");
          if (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()) {
            cg.setContext(CodeGenerator::CppTypedParamsWrapperImpl);
            outputCPPImpl(cg, ar);
          }
        } else {
          outputCPPTypeCheckWrapper(cg, ar);
          cg_indentEnd("}\n");
        }
        cg.setContext(context);
        cg.printImplSplitter();
      }
      break;
    default:
      break;
  }
}