Exemplo n.º 1
0
void MethodStatement::outputCPPStmt(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (m_stmt) {
    m_stmt->outputCPP(cg, ar);
    if (!m_stmt->hasRetExp()) {
      FunctionScopePtr funcScope = m_funcScope.lock();
      ClassScopePtr cls = ar->getClassScope();
      if (funcScope->isConstructor(cls)) {
        cg.printf("gasInCtor(oldInCtor);\n");
      }
    }
  }
}
void ReturnStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  bool braced = false;
  FunctionScopePtr func = getFunctionScope();
  ClassScopePtr cls = getClassScope();
  if (func->isConstructor(cls)) {
    cg_indentBegin("{\n"); braced = true;
    cg_printf("gasInCtor(oldInCtor);\n");
  }
  if (m_exp) {
    if (m_exp->hasContext(Expression::RefValue)) {
      m_exp->setContext(Expression::NoRefWrapper);
    }
    m_exp->outputCPPBegin(cg, ar);
  }

  cg_printf("return");
  if (m_exp) {
    bool close = false;
    cg_printf(" ");
    if (m_exp->hasContext(Expression::RefValue) && m_exp->isRefable()) {
      cg_printf("strongBind(");
      close = true;
    } else if (checkCopyElision(func, m_exp)) {
      cg_printf("wrap_variant(");
      close = true;
    }
    m_exp->outputCPP(cg, ar);
    if (close) cg_printf(")");
    cg_printf(";\n");
    cg.setReferenceTempUsed(false);
    m_exp->outputCPPEnd(cg, ar);
  } else if (func &&
             !(func->inPseudoMain() && !Option::GenerateCPPMain &&
               cg.getOutput() != CodeGenerator::SystemCPP)) {
    TypePtr type = func->getReturnType();
    if (type) {
      const char *initializer = type->getCPPInitializer();
      cg_printf(" %s", initializer ? initializer : "null");
    }
    cg_printf(";\n");
  }

  if (braced) cg_indentEnd("}\n");
}
Exemplo n.º 3
0
bool MethodStatement::outputFFI(CodeGenerator &cg, AnalysisResultPtr ar) {
  FunctionScopePtr funcScope = m_funcScope.lock();
  ClassScopePtr clsScope = ar->getClassScope();
  bool pseudoMain = funcScope->inPseudoMain();
  bool inClass = !m_className.empty();
  // only expose public methods, and ignore those in redeclared classes
  bool inaccessible =
    inClass && (!m_modifiers->isPublic() || clsScope->isRedeclaring());
  // skip constructors
  bool isConstructor = inClass && funcScope->isConstructor(clsScope);
  bool valid = !pseudoMain && !inaccessible && !isConstructor;

  if (cg.getContext() == CodeGenerator::CppFFIDecl ||
      cg.getContext() == CodeGenerator::CppFFIImpl) {
    if (valid) outputCPPFFIStub(cg, ar);
    return true;
  }

  if (cg.getContext() == CodeGenerator::HsFFI) {
    if (valid) outputHSFFIStub(cg, ar);
    return true;
  }

  if (cg.getContext() == CodeGenerator::JavaFFI
   || cg.getContext() == CodeGenerator::JavaFFIInterface) {
    if (valid) outputJavaFFIStub(cg, ar);
    return true;
  }

  if (cg.getContext() == CodeGenerator::JavaFFICppDecl
   || cg.getContext() == CodeGenerator::JavaFFICppImpl) {
    if (valid) outputJavaFFICPPStub(cg, ar);
    return true;
  }

  if (cg.getContext() == CodeGenerator::SwigFFIDecl
   || cg.getContext() == CodeGenerator::SwigFFIImpl) {
    if (valid) outputSwigFFIStub(cg, ar);
    return true;
  }

  return false;
}
Exemplo n.º 4
0
void MethodStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  FunctionScopePtr funcScope = m_funcScope.lock();
  ClassScopePtr scope = ar->getClassScope();
  string origFuncName;
  ar->pushScope(funcScope);

  if (outputFFI(cg, ar)) return;

  cg.setPHPLineNo(-1);

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

  switch (cg.getContext()) {
  case CodeGenerator::CppDeclaration:
    {
      if (!m_stmt) {
        cg.printf("// ");
      }
      m_modifiers->outputCPP(cg, ar);

      if (m_name == "__offsetget_lval") {
        cg.printf("virtual ");
      }
      TypePtr type = funcScope->getReturnType();
      if (type) {
        type->outputCPPDecl(cg, ar);
      } else {
        cg.printf("void");
      }
      if (m_name == "__lval") {
        cg.printf(" &___lval(");
      } else 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(const char* cls%s", Option::MethodImplPrefix,
                  m_name.c_str(),
                  funcScope->isVariableArgument() ||
                  (m_params && m_params->getCount()) ? ", " : "");
      } else {
        cg.printf(" %s%s(", Option::MethodPrefix, m_name.c_str());
      }
      funcScope->outputCPPParamsDecl(cg, ar, m_params, true);
      if (m_stmt) {
        cg.printf(");\n");
      } else {
        cg.printf(") = 0;\n");
      }

      if (funcScope->isConstructor(scope)
       && !funcScope->isAbstract() && !scope->isInterface()) {
        funcScope->outputCPPCreateDecl(cg, ar);
      }
    }
    break;
  case CodeGenerator::CppImplementation:
    if (m_stmt) {
      TypePtr type = funcScope->getReturnType();
      if (type) {
        type->outputCPPDecl(cg, ar);
      } else {
        cg.printf("void");
      }
      origFuncName = std::string(scope->getOriginalName()) +
                     "::" + m_originalName;
      if (Option::HotFunctions.find(origFuncName) !=
          Option::HotFunctions.end()) {
        cg.printf(" __attribute((__section__(\".text.hot\")))");
      } else if (Option::ColdFunctions.find(origFuncName) !=
                 Option::ColdFunctions.end()) {
        cg.printf(" __attribute((__section__(\".text.cold\")))");
      }
      if (m_name == "__lval") {
        cg.printf(" &%s%s::___lval(",
                  Option::ClassPrefix, scope->getId().c_str());
      } else if (m_name == "__offsetget_lval") {
        cg.printf(" &%s%s::___offsetget_lval(",
                  Option::ClassPrefix, scope->getId().c_str());
      } else if (m_modifiers->isStatic()) {
        cg.printf(" %s%s::%s%s(const char* cls%s", Option::ClassPrefix,
                  scope->getId().c_str(),
                  Option::MethodImplPrefix, m_name.c_str(),
                  funcScope->isVariableArgument() ||
                  (m_params && m_params->getCount()) ? ", " : "");
      } else {
        cg.printf(" %s%s::%s%s(", Option::ClassPrefix, scope->getId().c_str(),
                  Option::MethodPrefix, m_name.c_str());
      }
      funcScope->outputCPPParamsDecl(cg, ar, m_params, false);
      cg.indentBegin(") {\n");
      if (m_modifiers->isStatic()) {
        cg.printf("STATIC_METHOD_INJECTION(%s, %s::%s);\n",
                  scope->getOriginalName(), scope->getOriginalName(),
                  m_originalName.c_str());
      } else {
        cg.printf("INSTANCE_METHOD_INJECTION(%s, %s::%s);\n",
                  scope->getOriginalName(), scope->getOriginalName(),
                  m_originalName.c_str());
      }
      if (Option::GenRTTIProfileData && m_params) {
        for (int i = 0; i < m_params->getCount(); i++) {
          ParameterExpressionPtr param =
            dynamic_pointer_cast<ParameterExpression>((*m_params)[i]);
          if (param->hasRTTI()) {
            const string &paramName = param->getName();
            int id = ar->getParamRTTIEntryId(ar->getClassScope(), funcScope,
                                             paramName);
            if (id != -1) {
              cg.printf("RTTI_INJECTION(%s%s, %d);\n",
                        Option::VariablePrefix, paramName.c_str(), id);
            }
          }
        }
      }
      if (m_name == "__lval" || m_name == "__offsetget_lval") {
        ParameterExpressionPtr param =
          dynamic_pointer_cast<ParameterExpression>((*m_params)[0]);
        cg.printf("Variant &v = %s->__lvalProxy;\n",
                  cg.getOutput() == CodeGenerator::SystemCPP ?
                  "get_system_globals()" : "get_global_variables()");
        string lowered = Util::toLower(m_originalName);
        cg.printf("v = %s%s(%s%s);\n",
                  Option::MethodPrefix, 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");
        } else if (m_name == "__call") {
          ParameterExpressionPtr param;
          if (m_params->getCount() > 0) {
            param = dynamic_pointer_cast<ParameterExpression>((*m_params)[0]);
            cg.printf("INCALL_HELPER(%s%s);\n",
                      Option::VariablePrefix, param->getName().c_str());
          } else {
            cg.printf("INCALL_HELPER(\"\");\n");
          }
        }
        funcScope->outputCPP(cg, ar);
        cg.setContext(CodeGenerator::NoContext); // no inner functions/classes
        if (!funcScope->isStatic() && funcScope->getVariables()->
            getAttribute(VariableTable::ContainsDynamicVariable)) {
          cg.printf("%sthis = this;\n", Option::VariablePrefix);
        }
        outputCPPStmt(cg, ar);
        cg.setContext(CodeGenerator::CppImplementation);
      }
      cg.indentEnd("} /* function */\n");
    }
    break;
  default:
    break;
  }

  ar->popScope();
}
Exemplo n.º 5
0
void MethodStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  FunctionScopePtr funcScope = m_funcScope.lock();
  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);
      } 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);
        } else {
          cg_printf("void");
        }
        string origFuncName = getOriginalFullName();
        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 {
              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)) {
              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;
  }
}