Comparar commits
37 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 30b0fc0026 | |||
| 4f78c7de03 | |||
| d6a8578e34 | |||
| 085f510c23 | |||
| 1e1eac2a0e | |||
| 565465d580 | |||
| 38be2694ae | |||
| d87b7c84fb | |||
| a8b31881f6 | |||
| bd49a4ac26 | |||
| c33c344f99 | |||
| ec3d41f15f | |||
| afc63c1ab6 | |||
| b10c2021e2 | |||
| d04d9ec022 | |||
| 5a4db6875a | |||
| 251b5d78b4 | |||
| d2ca7292fb | |||
| ebb9f3cadd | |||
| b9d8d0ff47 | |||
| 73f16bc03b | |||
| 540cac6ec2 | |||
| c20fcce91b | |||
| 922a61dad5 | |||
| a568ad1a07 | |||
| 5815d21518 | |||
| 757c1414f5 | |||
| a1745fb58b | |||
| 20f0306dd3 | |||
| 8121dbb0d3 | |||
| 1177492d76 | |||
| 23cd8e033e | |||
| 6050afa844 | |||
| 98a2c6ede2 | |||
| e766a8a4ac | |||
| 5b7366968a | |||
| 2d963c4ffb |
+19
-4
@@ -1,5 +1,10 @@
|
||||
*.[oad]
|
||||
*.hhbc
|
||||
/bin*-g
|
||||
/bin*-O
|
||||
/bin/*.so
|
||||
/bin/hphp_options
|
||||
/bin/systemlib.php
|
||||
.mkdir
|
||||
hphp.log
|
||||
|
||||
@@ -32,8 +37,16 @@ hphp.log
|
||||
/hphp/hhvm/gen
|
||||
/hphp/hhvm/hhvm
|
||||
|
||||
*.ext_hhvm.cpp
|
||||
*.ext_hhvm.h
|
||||
/hphp/runtime/ext/*.ext_hhvm.cpp
|
||||
/hphp/runtime/ext/*.ext_hhvm.h
|
||||
/hphp/runtime/ext/*/*.ext_hhvm.cpp
|
||||
/hphp/runtime/ext/*/*.ext_hhvm.h
|
||||
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.cpp
|
||||
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.h
|
||||
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.cpp
|
||||
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.h
|
||||
/hphp/runtime/base/builtin-functions.cpp.ext_hhvm.cpp
|
||||
/hphp/runtime/base/builtin-functions.cpp.ext_hhvm.h
|
||||
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.cpp
|
||||
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.h
|
||||
|
||||
@@ -42,6 +55,10 @@ hphp.log
|
||||
/hphp/ffi/java/classes
|
||||
/hphp/ffi/java/hphp_ffi_java.h
|
||||
|
||||
# Ignore all makefiles generated for fbcode's third-party repo
|
||||
/bin/*.mk
|
||||
!/bin/run.mk
|
||||
|
||||
CMakeFiles
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
@@ -51,8 +68,6 @@ install_manifest.txt
|
||||
|
||||
/hphp/TAGS
|
||||
|
||||
/hphp/third_party/libzip/libzip.dylib
|
||||
|
||||
# Generated makefiles
|
||||
/hphp/runtime/ext_hhvm/Makefile
|
||||
/hphp/test/Makefile
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[submodule "hphp/submodules/folly"]
|
||||
path = hphp/submodules/folly
|
||||
url = git://github.com/facebook/folly.git
|
||||
+8
-20
@@ -4,35 +4,23 @@ compiler:
|
||||
- gcc
|
||||
|
||||
before_script:
|
||||
- time TRAVIS=1 ./configure_ubuntu_12.04.sh
|
||||
- TRAVIS=1 ./configure_ubuntu_12.04.sh
|
||||
# for some tests
|
||||
- time sudo locale-gen de_DE && sudo locale-gen zh_CN.utf8 && sudo locale-gen fr_FR
|
||||
- time HPHP_HOME=`pwd` make -j 6
|
||||
# mysql configuration for unit-tests
|
||||
- mysql -e 'CREATE DATABASE IF NOT EXISTS hhvm;'
|
||||
- export PDO_MYSQL_TEST_DSN="mysql:host=127.0.0.1;dbname=hhvm"
|
||||
- export PDO_MYSQL_TEST_USER="travis"
|
||||
- export PDO_MYSQL_TEST_PASS=""
|
||||
- sudo locale-gen de_DE && sudo locale-gen zh_CN.utf8 && sudo locale-gen fr_FR
|
||||
- HPHP_HOME=`pwd` make -j 6
|
||||
|
||||
# Test suites take longer to run in RepoAuthoritative mode (-r) than normal so
|
||||
# split out the -r from normal runs and further split the -r runs by suite to
|
||||
# avoid the possibility of slower machines exceeding the 50 minute test timeout
|
||||
env:
|
||||
- TEST_RUN_MODE="-m jit quick"
|
||||
- TEST_RUN_MODE="-m jit slow"
|
||||
- TEST_RUN_MODE="-m jit zend"
|
||||
- TEST_RUN_MODE="-m jit -r quick"
|
||||
- TEST_RUN_MODE="-m jit -r slow"
|
||||
- TEST_RUN_MODE="-m jit all"
|
||||
- TEST_RUN_MODE="-m interp all"
|
||||
- TEST_RUN_MODE="-m jit -r quick slow"
|
||||
- TEST_RUN_MODE="-m interp -r quick slow"
|
||||
- TEST_RUN_MODE="-m jit -r zend"
|
||||
- TEST_RUN_MODE="-m interp quick"
|
||||
- TEST_RUN_MODE="-m interp slow"
|
||||
- TEST_RUN_MODE="-m interp zend"
|
||||
- TEST_RUN_MODE="-m interp -r quick"
|
||||
- TEST_RUN_MODE="-m interp -r slow"
|
||||
- TEST_RUN_MODE="-m interp -r zend"
|
||||
|
||||
script: time hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
|
||||
script: hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
irc: "chat.freenode.net#hhvm"
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
option(ENABLE_ZEND_COMPAT "Enable Zend source compatibility (beta)" OFF)
|
||||
|
||||
set(ZEND_COMPAT_PROJECTS)
|
||||
set(ZEND_COMPAT_BUILD_DIRS)
|
||||
set(ZEND_COMPAT_EXCLUDE_IDLS)
|
||||
set(ZEND_COMPAT_LINK_LIBRARIES)
|
||||
|
||||
# Look for projects
|
||||
set(EZC_DIR "${HPHP_HOME}/hphp/runtime/ext_zend_compat/")
|
||||
file(GLOB ezc_projects RELATIVE ${EZC_DIR} "${EZC_DIR}/*")
|
||||
foreach(ezc_project ${ezc_projects})
|
||||
get_filename_component(ezc_name ${ezc_project} NAME)
|
||||
if ((NOT ${ezc_name} STREQUAL "php-src") AND (IS_DIRECTORY "${EZC_DIR}/${ezc_name}"))
|
||||
list(APPEND ZEND_COMPAT_PROJECTS ${ezc_name})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (ENABLE_ZEND_COMPAT)
|
||||
foreach(ezc_project ${ZEND_COMPAT_PROJECTS})
|
||||
if (${ezc_project} STREQUAL "yaml")
|
||||
find_package(LibYaml)
|
||||
if (LibYaml_INCLUDE_DIRS)
|
||||
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/yaml")
|
||||
include_directories(${LibYaml_INCLUDE_DIRS})
|
||||
list(APPEND ZEND_COMPAT_LINK_LIBRARIES ${LibYaml_LIBRARIES})
|
||||
else()
|
||||
list(APPEND ZEND_COMPAT_EXCLUDE_IDLS "yaml.idl.json")
|
||||
endif()
|
||||
elseif (${ezc_project} STREQUAL "mongo")
|
||||
include_directories("${EZC_DIR}/mongo/mcon")
|
||||
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/mongo")
|
||||
else()
|
||||
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/${ezc_project}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (ZEND_COMPAT_BUILD_DIRS)
|
||||
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/php-src")
|
||||
include_directories("${EZC_DIR}/php-src")
|
||||
include_directories("${EZC_DIR}/php-src/main")
|
||||
include_directories("${EZC_DIR}/php-src/Zend")
|
||||
include_directories("${EZC_DIR}/php-src/TSRM")
|
||||
endif()
|
||||
else()
|
||||
foreach(ezc_project ${ZEND_COMPAT_PROJECTS})
|
||||
list(APPEND ZEND_COMPAT_EXCLUDE_IDLS "${ezc_project}.idl.json")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# This is really ugly, but cmake's list(FIND)
|
||||
# doesn't entirely work the way it should
|
||||
macro(ZEND_COMPAT_STRIP_IDLS IDLS)
|
||||
foreach(idl ${${IDLS}})
|
||||
get_filename_component(idl_name ${idl} NAME)
|
||||
foreach(f ${ARGV})
|
||||
if (${idl_name} STREQUAL ${f})
|
||||
list(REMOVE_ITEM ${IDLS} ${idl})
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endmacro()
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_FREETYPE QUIET freetype2)
|
||||
|
||||
find_path(FREETYPE_INCLUDE_DIRS NAMES freetype/config/ftheader.h
|
||||
HINTS ${PC_FREETYPE_INCLUDEDIR} ${PC_FREETYPE_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES freetype2)
|
||||
|
||||
find_library(FREETYPE_LIBRARIES NAMES freetype)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Freetype DEFAULT_MSG
|
||||
FREETYPE_LIBRARIES
|
||||
FREETYPE_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(FREETYPE_INCLUDE_DIRS FREETYPE_LIBRARIES)
|
||||
@@ -0,0 +1,121 @@
|
||||
# - Find GD
|
||||
# Find the native GD includes and library
|
||||
# This module defines
|
||||
# GD_INCLUDE_DIR, where to find gd.h, etc.
|
||||
# GD_LIBRARIES, the libraries needed to use GD.
|
||||
# GD_FOUND, If false, do not try to use GD.
|
||||
# also defined, but not for general use are
|
||||
# GD_LIBRARY, where to find the GD library.
|
||||
# GD_SUPPORTS_PNG, GD_SUPPORTS_JPEG, GD_SUPPORTS_GIF, test
|
||||
# support for image formats in GD.
|
||||
|
||||
FIND_PATH(GD_INCLUDE_DIR gd.h
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
SET(GD_NAMES ${GD_NAMES} bgd)
|
||||
else(WIN32)
|
||||
SET(GD_NAMES ${GD_NAMES} gd)
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
FIND_LIBRARY(GD_LIBRARY
|
||||
NAMES ${GD_NAMES}
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib
|
||||
)
|
||||
|
||||
IF (GD_LIBRARY AND GD_INCLUDE_DIR)
|
||||
SET(GD_LIBRARIES ${GD_LIBRARY})
|
||||
SET(GD_FOUND "YES")
|
||||
ELSE (GD_LIBRARY AND GD_INCLUDE_DIR)
|
||||
SET(GD_FOUND "NO")
|
||||
ENDIF (GD_LIBRARY AND GD_INCLUDE_DIR)
|
||||
|
||||
IF (GD_FOUND)
|
||||
IF (WIN32 AND NOT CYGWIN)
|
||||
SET(GD_SUPPORTS_PNG ON)
|
||||
SET(GD_SUPPORTS_JPEG ON)
|
||||
SET(GD_SUPPORTS_GIF ON)
|
||||
get_filename_component(GD_LIBRARY_DIR ${GD_LIBRARY} PATH)
|
||||
ELSE (WIN32 AND NOT CYGWIN)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
GET_FILENAME_COMPONENT(GD_LIB_PATH ${GD_LIBRARY} PATH)
|
||||
GET_FILENAME_COMPONENT(GD_LIB ${GD_LIBRARY} NAME)
|
||||
|
||||
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImagePng" "${GD_LIB_PATH}" GD_SUPPORTS_PNG)
|
||||
IF (GD_SUPPORTS_PNG)
|
||||
find_package(PNG)
|
||||
IF (PNG_FOUND)
|
||||
SET(GD_LIBRARIES ${GD_LIBRARIES} ${PNG_LIBRARIES})
|
||||
SET(GD_INCLUDE_DIR ${GD_INCLUDE_DIR} ${PNG_INCLUDE_DIR})
|
||||
ELSE (PNG_FOUND)
|
||||
SET(GD_SUPPORTS_PNG "NO")
|
||||
ENDIF (PNG_FOUND)
|
||||
ENDIF (GD_SUPPORTS_PNG)
|
||||
|
||||
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageJpeg" "${GD_LIB_PATH}" GD_SUPPORTS_JPEG)
|
||||
IF (GD_SUPPORTS_JPEG)
|
||||
find_package(JPEG)
|
||||
IF (JPEG_FOUND)
|
||||
SET(GD_LIBRARIES ${GD_LIBRARIES} ${JPEG_LIBRARIES})
|
||||
SET(GD_INCLUDE_DIR ${GD_INCLUDE_DIR} ${JPEG_INCLUDE_DIR})
|
||||
ELSE (JPEG_FOUND)
|
||||
SET(GD_SUPPORTS_JPEG "NO")
|
||||
ENDIF (JPEG_FOUND)
|
||||
ENDIF (GD_SUPPORTS_JPEG)
|
||||
|
||||
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageGif" "${GD_LIB_PATH}" GD_SUPPORTS_GIF)
|
||||
|
||||
# Trim the list of include directories
|
||||
SET(GDINCTRIM)
|
||||
FOREACH(GD_DIR ${GD_INCLUDE_DIR})
|
||||
SET(GD_TMP_FOUND OFF)
|
||||
FOREACH(GD_TRIMMED ${GDINCTRIM})
|
||||
IF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}")
|
||||
SET(GD_TMP_FOUND ON)
|
||||
ENDIF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}")
|
||||
ENDFOREACH(GD_TRIMMED ${GDINCTRIM})
|
||||
IF (NOT GD_TMP_FOUND)
|
||||
SET(GDINCTRIM "${GDINCTRIM}" "${GD_DIR}")
|
||||
ENDIF (NOT GD_TMP_FOUND)
|
||||
ENDFOREACH(GD_DIR ${GD_INCLUDE_DIR})
|
||||
SET(GD_INCLUDE_DIR ${GDINCTRIM})
|
||||
|
||||
SET(GD_LIBRARY_DIR)
|
||||
|
||||
# Generate trimmed list of library directories and list of libraries
|
||||
FOREACH(GD_LIB ${GD_LIBRARIES})
|
||||
GET_FILENAME_COMPONENT(GD_NEXTLIBDIR ${GD_LIB} PATH)
|
||||
SET(GD_TMP_FOUND OFF)
|
||||
FOREACH(GD_LIBDIR ${GD_LIBRARY_DIR})
|
||||
IF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}")
|
||||
SET(GD_TMP_FOUND ON)
|
||||
ENDIF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}")
|
||||
ENDFOREACH(GD_LIBDIR ${GD_LIBRARIES})
|
||||
IF (NOT GD_TMP_FOUND)
|
||||
SET(GD_LIBRARY_DIR "${GD_LIBRARY_DIR}" "${GD_NEXTLIBDIR}")
|
||||
ENDIF (NOT GD_TMP_FOUND)
|
||||
ENDFOREACH(GD_LIB ${GD_LIBRARIES})
|
||||
ENDIF (WIN32 AND NOT CYGWIN)
|
||||
ENDIF (GD_FOUND)
|
||||
|
||||
IF (GD_FOUND)
|
||||
IF (NOT GD_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found GD: ${GD_LIBRARY}")
|
||||
ENDIF (NOT GD_FIND_QUIETLY)
|
||||
ELSE (GD_FOUND)
|
||||
IF (GD_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find GD library")
|
||||
ENDIF (GD_FIND_REQUIRED)
|
||||
ENDIF (GD_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
GD_LIBRARY
|
||||
GD_LIBRARIES
|
||||
GD_INCLUDE_DIR
|
||||
GD_LIBRARY_DIR
|
||||
GD_SUPPORTS_PNG
|
||||
GD_SUPPORTS_JPEG
|
||||
GD_SUPPORTS_GIF
|
||||
)
|
||||
@@ -18,7 +18,7 @@ endif (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS)
|
||||
|
||||
find_path (DWARF_INCLUDE_DIR
|
||||
NAMES
|
||||
libdwarf.h dwarf.h
|
||||
dwarf.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/include/libdwarf
|
||||
@@ -50,13 +50,5 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDwarf DEFAULT_MSG
|
||||
LIBDWARF_LIBRARIES
|
||||
LIBDWARF_INCLUDE_DIRS)
|
||||
|
||||
if (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${LIBDWARF_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${LIBDWARF_LIBRARIES})
|
||||
include(CheckSymbolExists)
|
||||
CHECK_SYMBOL_EXISTS(dwarf_encode_leb128 "libdwarf.h" LIBDWARF_HAVE_ENCODE_LEB128)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBDW_INCLUDE_DIR DWARF_INCLUDE_DIR)
|
||||
mark_as_advanced(LIBDWARF_INCLUDE_DIRS LIBDWARF_LIBRARIES)
|
||||
mark_as_advanced(LIBDWARF_HAVE_ENCODE_LEB128)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
if (LIBJPEG_LIBRARIES AND LIBJPEG_INCLUDE_DIRS)
|
||||
set (LibJpeg_FIND_QUIETLY TRUE)
|
||||
endif (LIBJPEG_LIBRARIES AND LIBJPEG_INCLUDE_DIRS)
|
||||
|
||||
find_path(LIBJPEG_INCLUDE_DIRS NAMES jpeglib.h)
|
||||
find_library(LIBJPEG_LIBRARIES NAMES jpeg)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibJpeg DEFAULT_MSG
|
||||
LIBJPEG_LIBRARIES
|
||||
LIBJPEG_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(LIBJPEG_INCLUDE_DIRS LIBJPEG_LIBRARIES)
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
if (LIBPNG_LIBRARIES AND LIBPNG_INCLUDE_DIRS)
|
||||
set (LibPng_FIND_QUIETLY TRUE)
|
||||
endif (LIBPNG_LIBRARIES AND LIBPNG_INCLUDE_DIRS)
|
||||
|
||||
find_path(LIBPNG_INCLUDE_DIRS NAMES png.h)
|
||||
find_library(LIBPNG_LIBRARIES NAMES png)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibPng DEFAULT_MSG
|
||||
LIBPNG_LIBRARIES
|
||||
LIBPNG_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(LIBPNG_INCLUDE_DIRS LIBPNG_LIBRARIES)
|
||||
@@ -1,12 +0,0 @@
|
||||
if (LIBODBC_LIBRARIES AND LIBODBC_INCLUDE_DIRS)
|
||||
set (LibUODBC_FIND_QUIETLY TRUE)
|
||||
endif (LIBODBC_LIBRARIES AND LIBODBC_INCLUDE_DIRS)
|
||||
|
||||
find_path (LIBODBC_INCLUDE_DIRS NAMES sqlext.h)
|
||||
find_library (LIBODBC_LIBRARIES NAMES odbc)
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUODBC DEFAULT_MSG
|
||||
LIBODBC_LIBRARIES
|
||||
LIBODBC_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(LIBODBC_INCLUDE_DIRS LIBODBC_LIBRARIES)
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
if (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
|
||||
set (LibVpx_FIND_QUIETLY TRUE)
|
||||
endif (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
|
||||
|
||||
find_path(LIBVPX_INCLUDE_DIRS NAMES vpx_codec.h)
|
||||
find_library(LIBVPX_LIBRARIES NAMES vpx)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibVpx DEFAULT_MSG
|
||||
LIBVPX_LIBRARIES
|
||||
LIBVPX_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(LIBVPX_INCLUDE_DIRS LIBVPX_LIBRARIES)
|
||||
@@ -1,13 +0,0 @@
|
||||
if (LibYaml_LIBRARIES AND LibYaml_INCLUDE_DIRS)
|
||||
set (LibYaml_FIND_QUIETLY TRUE)
|
||||
endif (LibYaml_LIBRARIES AND LibYaml_INCLUDE_DIRS)
|
||||
|
||||
find_path (LibYaml_INCLUDE_DIRS NAMES yaml.h)
|
||||
find_library (LibYaml_LIBRARIES NAMES yaml)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibYaml DEFAULT_MSG
|
||||
LibYaml_LIBRARIES
|
||||
LibYaml_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(LibYaml_INCLUDE_DIRS LibYaml_LIBRARIES)
|
||||
@@ -1,28 +0,0 @@
|
||||
# folly-config.h is a generated file from autotools
|
||||
# We need to do the equivalent checks here and use
|
||||
# add_definitions as needed
|
||||
add_definitions(-DFOLLY_NO_CONFIG=1)
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
extern \"C\" void (*test_ifunc(void))() { return 0; }
|
||||
void func() __attribute__((ifunc(\"test_ifunc\")));
|
||||
" FOLLY_IFUNC)
|
||||
if (FOLLY_IFUNC)
|
||||
add_definitions("-DHAVE_IFUNC=1")
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES rt)
|
||||
include(CheckFunctionExists)
|
||||
CHECK_FUNCTION_EXISTS("clock_gettime" HAVE_CLOCK_GETTIME)
|
||||
|
||||
if (HAVE_CLOCK_GETTIME)
|
||||
add_definitions("-DFOLLY_HAVE_CLOCK_GETTIME=1")
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
find_path(FEATURES_H_INCLUDE_DIR NAMES features.h)
|
||||
if (FEATURES_H_INCLUDE_DIR)
|
||||
include_directories("${FEATURES_H_INCLUDE_DIR}")
|
||||
add_definitions("-DFOLLY_HAVE_FEATURES_H=1")
|
||||
endif()
|
||||
+17
-12
@@ -1,5 +1,14 @@
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#if GCC_VERSION < 40600
|
||||
#error Need GCC 4.6.0+
|
||||
#endif
|
||||
int main() { return 0; }" HAVE_GCC_46)
|
||||
|
||||
if(NOT HAVE_GCC_46)
|
||||
message(FATAL_ERROR "Need at least GCC 4.6")
|
||||
endif()
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#if GCC_VERSION < 40700
|
||||
@@ -7,10 +16,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
#endif
|
||||
int main() { return 0; }" HAVE_GCC_47)
|
||||
|
||||
if (NOT HAVE_GCC_47)
|
||||
message(FATAL_ERROR "Need at least GCC 4.7")
|
||||
endif()
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#if GCC_VERSION < 40800
|
||||
#error Not GCC 4.8.0+
|
||||
@@ -32,18 +37,18 @@ endif()
|
||||
|
||||
if($ENV{CXX} MATCHES "icpc")
|
||||
set(CMAKE_C_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -w")
|
||||
set(CMAKE_CXX_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -w1 -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names")
|
||||
set(CMAKE_CXX_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -fno-omit-frame-pointer -ftemplate-depth-120 -Wall -Woverloaded-virtual -Wno-deprecated -w1 -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names")
|
||||
else()
|
||||
set(GNUCC_48_OPT "")
|
||||
set(GNUCC_UNINIT_OPT "")
|
||||
if(HAVE_GCC_47)
|
||||
set(GNUCC_UNINIT_OPT "-Wno-maybe-uninitialized")
|
||||
endif()
|
||||
set(GNUCC_LOCAL_TYPEDEF_OPT "")
|
||||
if(HAVE_GCC_48)
|
||||
set(GNUCC_48_OPT "-Wno-unused-local-typedefs -fno-canonical-system-headers -Wno-deprecated-declarations")
|
||||
set(GNUCC_LOCAL_TYPEDEF_OPT "-Wno-unused-local-typedefs")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "-w")
|
||||
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized -mcrc32 ${GNUCC_48_OPT}")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*")
|
||||
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized -Wno-mismatched-tags -Wno-unknown-warning-option -Wno-return-type-c-linkage -Qunused-arguments")
|
||||
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-120 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++0x -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes ${GNUCC_UNINIT_OPT} ${GNUCC_LOCAL_TYPEDEF_OPT}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
+19
-76
@@ -31,11 +31,6 @@ endif()
|
||||
find_package(Boost 1.48.0 COMPONENTS system program_options filesystem regex REQUIRED)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
link_directories(${Boost_LIBRARY_DIRS})
|
||||
# Boost 1.49 supports a better flat_multimap, but 1.48 is good enough
|
||||
if (Boost_VERSION GREATER 104899)
|
||||
add_definitions("-DHAVE_BOOST1_49")
|
||||
endif()
|
||||
|
||||
|
||||
# features.h
|
||||
FIND_PATH(FEATURES_HEADER features.h)
|
||||
@@ -90,46 +85,22 @@ include_directories(${LIBEVENT_INCLUDE_DIR})
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${LIBEVENT_LIB}")
|
||||
CHECK_FUNCTION_EXISTS("evhttp_bind_socket_with_fd" HAVE_CUSTOM_LIBEVENT)
|
||||
if(HAVE_CUSTOM_LIBEVENT)
|
||||
message("Using custom LIBEVENT")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_CUSTOM_LIBEVENT")
|
||||
endif()
|
||||
if (NOT HAVE_CUSTOM_LIBEVENT)
|
||||
unset(HAVE_CUSTOM_LIBEVENT CACHE)
|
||||
unset(LIBEVENT_INCLUDE_DIR CACHE)
|
||||
unset(LIBEVENT_LIB CACHE)
|
||||
unset(LibEvent_FOUND CACHE)
|
||||
message(FATAL_ERROR "Custom libevent is required with HipHop patches")
|
||||
endif ()
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
find_package(LibUODBC)
|
||||
if (LIBUODBC_INCLUDE_DIRS)
|
||||
include_directories(${LIBUODBC_INCLUDE_DIRS})
|
||||
add_definitions("-DHAVE_UODBC")
|
||||
endif ()
|
||||
|
||||
# GD checks
|
||||
add_definitions(-DPNG_SKIP_SETJMP_CHECK)
|
||||
find_package(LibVpx)
|
||||
if (LIBVPX_INCLUDE_DIRS)
|
||||
include_directories(${LIBVPX_INCLUDE_DIRS})
|
||||
add_definitions("-DHAVE_GD_WEBP")
|
||||
endif()
|
||||
find_package(LibJpeg)
|
||||
if (LIBJPEG_INCLUDE_DIRS)
|
||||
include_directories(${LIBJPEG_INCLUDE_DIRS})
|
||||
add_definitions("-DHAVE_GD_JPG")
|
||||
endif()
|
||||
find_package(LibPng)
|
||||
if (LIBPNG_INCLUDE_DIRS)
|
||||
include_directories(${LIBPNG_INCLUDE_DIRS})
|
||||
add_definitions("-DHAVE_GD_PNG")
|
||||
endif()
|
||||
find_package(Freetype)
|
||||
if (FREETYPE_INCLUDE_DIRS)
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS})
|
||||
add_definitions("-DHAVE_LIBFREETYPE -DHAVE_GD_FREETYPE -DENABLE_GD_TTF")
|
||||
endif()
|
||||
find_package(GD REQUIRED)
|
||||
|
||||
# libXed
|
||||
find_package(LibXed)
|
||||
if (LibXed_INCLUDE_DIR AND LibXed_LIBRARY)
|
||||
include_directories(${LibXed_INCLUDE_DIR})
|
||||
add_definitions("-DHAVE_LIBXED")
|
||||
add_definitions(-DHAVE_LIBXED)
|
||||
endif()
|
||||
|
||||
# CURL checks
|
||||
@@ -165,7 +136,6 @@ include_directories("${HPHP_HOME}/hphp/third_party/libmbfl/filter")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/lz4")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/double-conversion/src")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/folly")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/libzip")
|
||||
|
||||
# ICU
|
||||
find_package(ICU REQUIRED)
|
||||
@@ -319,9 +289,6 @@ include_directories(${CCLIENT_INCLUDE_PATH})
|
||||
|
||||
find_package(LibDwarf REQUIRED)
|
||||
include_directories(${LIBDWARF_INCLUDE_DIRS})
|
||||
if (LIBDWARF_HAVE_ENCODE_LEB128)
|
||||
add_definitions("-DHAVE_LIBDWARF_20130729")
|
||||
endif()
|
||||
|
||||
find_package(LibElf REQUIRED)
|
||||
include_directories(${LIBELF_INCLUDE_DIRS})
|
||||
@@ -335,26 +302,17 @@ if (NOT RECENT_CCLIENT)
|
||||
message(FATAL_ERROR "Your version of c-client is too old, you need 2007")
|
||||
endif()
|
||||
|
||||
|
||||
if (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.c")
|
||||
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.c" auth_gss CCLIENT_HAS_GSS)
|
||||
elseif (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.h")
|
||||
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.h" auth_gss CCLIENT_HAS_GSS)
|
||||
endif()
|
||||
|
||||
find_package(Libpam)
|
||||
if (PAM_INCLUDE_PATH)
|
||||
include_directories(${PAM_INCLUDE_PATH})
|
||||
endif()
|
||||
|
||||
if (NOT CCLIENT_HAS_GSS)
|
||||
add_definitions(-DSKIP_IMAP_GSS=1)
|
||||
endif()
|
||||
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.h" auth_gss CCLIENT_NEEDS_PAM)
|
||||
|
||||
if (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.c")
|
||||
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.c" ssl_onceonlyinit CCLIENT_HAS_SSL)
|
||||
elseif (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.h")
|
||||
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.h" ssl_onceonlyinit CCLIENT_HAS_SSL)
|
||||
endif()
|
||||
|
||||
if (CCLIENT_NEEDS_PAM)
|
||||
find_package(Libpam REQUIRED)
|
||||
include_directories(${PAM_INCLUDE_PATH})
|
||||
else()
|
||||
add_definitions(-DSKIP_IMAP_GSS=1)
|
||||
endif()
|
||||
|
||||
if (NOT CCLIENT_HAS_SSL)
|
||||
@@ -488,21 +446,7 @@ endif()
|
||||
target_link_libraries(${target} ${ONIGURUMA_LIBRARIES})
|
||||
target_link_libraries(${target} ${Mcrypt_LIB})
|
||||
target_link_libraries(${target} ${GD_LIBRARY})
|
||||
if (FREETYPE_LIBRARIES)
|
||||
target_link_libraries(${target} ${FREETYPE_LIBRARIES})
|
||||
endif()
|
||||
if (LIBJPEG_LIBRARIES)
|
||||
target_link_libraries(${target} ${LIBJPEG_LIBRARIES})
|
||||
endif()
|
||||
if (LIBPNG_LIBRARIES)
|
||||
target_link_libraries(${target} ${LIBPNG_LIBRARIES})
|
||||
endif()
|
||||
if (LIBVPX_LIBRARIES)
|
||||
target_link_libraries(${target} ${LIBVPX_LIBRARIES})
|
||||
endif()
|
||||
if (LIBUODBC_LIBRARIES)
|
||||
target_link_libraries(${target} ${LIBUODBC_LIBRARIES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${target} ${LDAP_LIBRARIES})
|
||||
target_link_libraries(${target} ${LBER_LIBRARIES})
|
||||
|
||||
@@ -518,7 +462,6 @@ endif()
|
||||
target_link_libraries(${target} lz4)
|
||||
target_link_libraries(${target} double-conversion)
|
||||
target_link_libraries(${target} folly)
|
||||
target_link_libraries(${target} zip_static)
|
||||
|
||||
target_link_libraries(${target} afdt)
|
||||
target_link_libraries(${target} mbfl)
|
||||
@@ -532,7 +475,7 @@ endif()
|
||||
target_link_libraries(${target} ${NCURSES_LIBRARY})
|
||||
target_link_libraries(${target} ${CCLIENT_LIBRARY})
|
||||
|
||||
if (PAM_LIBRARY)
|
||||
if (CCLIENT_NEEDS_PAM)
|
||||
target_link_libraries(${target} ${PAM_LIBRARY})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -38,27 +38,6 @@ function(auto_sources RETURN_VALUE PATTERN SOURCE_SUBDIRS)
|
||||
set(${RETURN_VALUE} ${${RETURN_VALUE}} PARENT_SCOPE)
|
||||
endfunction(auto_sources)
|
||||
|
||||
macro(HHVM_SELECT_SOURCES DIR)
|
||||
auto_sources(files "*.cpp" "RECURSE" "${DIR}")
|
||||
foreach(f ${files})
|
||||
if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
|
||||
list(APPEND CXX_SOURCES ${f})
|
||||
endif()
|
||||
endforeach()
|
||||
auto_sources(files "*.c" "RECURSE" "${DIR}")
|
||||
foreach(f ${files})
|
||||
if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
|
||||
list(APPEND C_SOURCES ${f})
|
||||
endif()
|
||||
endforeach()
|
||||
auto_sources(files "*.S" "RECURSE" "${DIR}")
|
||||
foreach(f ${files})
|
||||
if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
|
||||
list(APPEND ASM_SOURCES ${f})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro(HHVM_SELECT_SOURCES)
|
||||
|
||||
function(CONTAINS_STRING FILE SEARCH RETURN_VALUE)
|
||||
file(STRINGS ${FILE} FILE_CONTENTS REGEX ".*${SEARCH}.*")
|
||||
if (FILE_CONTENTS)
|
||||
@@ -89,34 +68,20 @@ macro(MYSQL_SOCKET_SEARCH)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function(embed_systemlib TARGET DEST SOURCE SECTNAME)
|
||||
function(embed_systemlib TARGET DEST SOURCE)
|
||||
if (APPLE)
|
||||
target_link_libraries(${TARGET} -Wl,-sectcreate,__text,${SECTNAME},${SOURCE})
|
||||
target_link_libraries(${TARGET} -Wl,-sectcreate,__text,systemlib,${SOURCE})
|
||||
else()
|
||||
add_custom_command(TARGET ${TARGET} POST_BUILD
|
||||
COMMAND "objcopy"
|
||||
ARGS "--add-section" "${SECTNAME}=${SOURCE}" ${DEST}
|
||||
COMMENT "Embedding ${SOURCE} in ${TARGET} as ${SECTNAME}")
|
||||
ARGS "--add-section" "systemlib=${SOURCE}" ${DEST}
|
||||
COMMENT "Embedding systemlib.php in ${TARGET}")
|
||||
endif()
|
||||
# Add the systemlib file to the "LINK_DEPENDS" for the systemlib, this will cause it
|
||||
# to be relinked and the systemlib re-embedded
|
||||
set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS ${SOURCE})
|
||||
endfunction(embed_systemlib)
|
||||
|
||||
function(embed_all_systemlibs TARGET DEST)
|
||||
embed_systemlib(${TARGET} ${DEST} ${HPHP_HOME}/hphp/system/systemlib.php systemlib)
|
||||
auto_sources(SYSTEMLIBS "ext_*.php" "RECURSE" "${HPHP_HOME}/hphp/runtime")
|
||||
foreach(SLIB ${SYSTEMLIBS})
|
||||
get_filename_component(SLIB_BN ${SLIB} "NAME_WE")
|
||||
string(LENGTH ${SLIB_BN} SLIB_BN_LEN)
|
||||
math(EXPR SLIB_BN_REL_LEN "${SLIB_BN_LEN} - 4")
|
||||
string(SUBSTRING ${SLIB_BN} 4 ${SLIB_BN_REL_LEN} SLIB_EXTNAME)
|
||||
string(MD5 SLIB_HASH_NAME ${SLIB_EXTNAME})
|
||||
string(SUBSTRING ${SLIB_HASH_NAME} 0 12 SLIB_HASH_NAME_SHORT)
|
||||
embed_systemlib(${TARGET} ${DEST} ${SLIB} "ext.${SLIB_HASH_NAME_SHORT}")
|
||||
endforeach()
|
||||
endfunction(embed_all_systemlibs)
|
||||
|
||||
# Custom install function that doesn't relink, instead it uses chrpath to change it, if
|
||||
# it's available, otherwise, it leaves the chrpath alone
|
||||
function(HHVM_INSTALL TARGET DEST)
|
||||
@@ -143,5 +108,5 @@ function(HHVM_EXTENSION EXTNAME)
|
||||
endfunction()
|
||||
|
||||
function(HHVM_SYSTEMLIB EXTNAME SOURCE_FILE)
|
||||
embed_systemlib(${EXTNAME} "${EXTNAME}.so" ${SOURCE_FILE} systemlib)
|
||||
embed_systemlib(${EXTNAME} "${EXTNAME}.so" ${SOURCE_FILE})
|
||||
endfunction()
|
||||
|
||||
+4
-26
@@ -1,18 +1,9 @@
|
||||
include(Options)
|
||||
|
||||
# Do this until cmake has a define for ARMv8
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#ifndef __AARCH64EL__
|
||||
#error Not ARMv8
|
||||
#endif
|
||||
int main() { return 0; }" IS_AARCH64)
|
||||
|
||||
if (APPLE OR IS_AARCH64)
|
||||
if (APPLE)
|
||||
set(HHVM_ANCHOR_SYMS -Wl,-u,_register_libevent_server)
|
||||
else()
|
||||
set(ENABLE_FASTCGI 1)
|
||||
set(HHVM_ANCHOR_SYMS -Wl,-uregister_libevent_server,-uregister_fastcgi_server)
|
||||
set(HHVM_ANCHOR_SYMS -Wl,-uregister_libevent_server)
|
||||
endif()
|
||||
|
||||
set(HHVM_LINK_LIBRARIES
|
||||
@@ -23,15 +14,9 @@ set(HHVM_LINK_LIBRARIES
|
||||
hphp_parser
|
||||
hphp_zend
|
||||
hphp_util
|
||||
hphp_hhbbc
|
||||
vixl neo
|
||||
${HHVM_ANCHOR_SYMS})
|
||||
|
||||
if(ENABLE_FASTCGI)
|
||||
LIST(APPEND HHVM_LINK_LIBRARIES hphp_thrift)
|
||||
LIST(APPEND HHVM_LINK_LIBRARIES hphp_proxygen)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
@@ -62,7 +47,8 @@ include(HPHPCompiler)
|
||||
include(HPHPFunctions)
|
||||
include(HPHPFindLibs)
|
||||
|
||||
add_definitions(-D_REENTRANT=1 -D_PTHREADS=1 -D__STDC_FORMAT_MACROS -DFOLLY_HAVE_WEAK_SYMBOLS=1)
|
||||
add_definitions(-D_REENTRANT=1 -D_PTHREADS=1 -D__STDC_FORMAT_MACROS)
|
||||
add_definitions(-DHHVM_LIB_PATH_DEFAULT="${HPHP_HOME}/bin")
|
||||
|
||||
if (LINUX)
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
@@ -119,14 +105,6 @@ if(APPLE)
|
||||
add_definitions(-DMACOSX_DEPLOYMENT_TARGET=10.6)
|
||||
endif()
|
||||
|
||||
if(ENABLE_FASTCGI)
|
||||
add_definitions(-DENABLE_FASTCGI=1)
|
||||
endif ()
|
||||
|
||||
if(DISABLE_HARDWARE_COUNTERS)
|
||||
add_definitions(-DNO_HARDWARE_COUNTERS=1)
|
||||
endif ()
|
||||
|
||||
# enable the OSS options if we have any
|
||||
add_definitions(-DHPHP_OSS=1)
|
||||
|
||||
|
||||
@@ -13,6 +13,3 @@ option(USE_JEMALLOC "Use jemalloc" ON)
|
||||
option(USE_TCMALLOC "Use tcmalloc (if jemalloc is not used)" ON)
|
||||
option(USE_GOOGLE_HEAP_PROFILER "Use Google heap profiler" OFF)
|
||||
option(USE_GOOGLE_CPU_PROFILER "Use Google cpu profiler" OFF)
|
||||
|
||||
option(DISABLE_HARDWARE_COUNTERS "Disable hardware counters (for XenU systems)" OFF)
|
||||
|
||||
|
||||
+21
-11
@@ -1,18 +1,18 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7 FATAL_ERROR)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5 FATAL_ERROR)
|
||||
PROJECT(hphp C CXX ASM)
|
||||
|
||||
IF(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(FATAL_ERROR "HHVM requires a 64bit OS")
|
||||
IF("$ENV{HPHP_HOME}" STREQUAL "")
|
||||
message(FATAL_ERROR "You should set the HPHP_HOME environmental")
|
||||
ENDIF()
|
||||
|
||||
set(HPHP_HOME "$ENV{HPHP_HOME}")
|
||||
if (NOT HPHP_HOME)
|
||||
set(HPHP_HOME "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
message("Using HPHP_HOME == ${HPHP_HOME}")
|
||||
file(TO_CMAKE_PATH "$ENV{HPHP_HOME}" HPHP_HOME)
|
||||
|
||||
IF(NOT EXISTS "${HPHP_HOME}/CMake/HPHPSetup.cmake")
|
||||
message(FATAL_ERROR "Invalid HPHP_HOME. Set it to the root of your hhvm tree, or run `cmake .` from there.")
|
||||
IF(NOT IS_DIRECTORY ${HPHP_HOME})
|
||||
message(FATAL_ERROR "The value of HPHP_HOME does not exist")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT EXISTS "${HPHP_HOME}/LICENSE.PHP")
|
||||
message(FATAL_ERROR "The value of HPHP_HOME in incorrect")
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
|
||||
@@ -20,5 +20,15 @@ SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/CMake/HPHPFunctions.cmake")
|
||||
include(CheckFunctionExists)
|
||||
|
||||
add_subdirectory(hphp)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/hphp)
|
||||
|
||||
IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
message(FATAL_ERROR "32-bit support is currently unsupported, check back with a later version of HipHop")
|
||||
ENDIF()
|
||||
|
||||
if ("$ENV{USE_HHVM}" STREQUAL "1")
|
||||
message("Building for HHVM")
|
||||
endif()
|
||||
if ("$ENV{USE_HPHPC}" STREQUAL "1")
|
||||
message(FATAL_ERROR "Building HPHPc is no longer supported")
|
||||
endif()
|
||||
|
||||
+13
-13
@@ -1,46 +1,46 @@
|
||||
# HHVM [](https://travis-ci.org/facebook/hhvm)
|
||||
# HipHop VM for PHP [](https://travis-ci.org/facebook/hiphop-php)
|
||||
|
||||
HHVM (aka the HipHop Virtual Machine) is a new open-source virtual machine designed for executing programs written in PHP. HHVM uses a just-in-time compilation approach to achieve superior performance while maintaining the flexibility that PHP developers are accustomed to. To date, HHVM (and its predecessor HPHPc before it) has realized over a 9x increase in web request throughput and over a 5x reduction in memory consumption for Facebook compared with the Zend PHP 5.2 engine + APC.
|
||||
HipHop VM (HHVM) is a new open-source virtual machine designed for executing programs written in PHP. HHVM uses a just-in-time compilation approach to achieve superior performance while maintaining the flexibility that PHP developers are accustomed to. HipHop VM (and before it HPHPc) has realized > 5x increase in throughput for Facebook compared with Zend PHP 5.2.
|
||||
|
||||
HHVM can be run as a standalone webserver (i.e. without the Apache webserver and the "modphp" extension). HHVM can also be used together with a FastCGI-based webserver, and work is in progress to make HHVM work smoothly with Apache.
|
||||
HipHop is most commonly run as a standalone server, replacing both Apache and modphp.
|
||||
|
||||
## FAQ
|
||||
|
||||
Our [FAQ](https://github.com/facebook/hhvm/wiki/FAQ) has answers to many common questions about HHVM, from [general questions](https://github.com/facebook/hhvm/wiki/FAQ#general) to questions geared towards those that want to [use](https://github.com/facebook/hhvm/wiki/FAQ#users) or [contribute](https://github.com/facebook/hhvm/wiki/FAQ#contributors) to HHVM.
|
||||
Our [FAQ](https://github.com/facebook/hiphop-php/wiki/FAQ) has answers to many common questions about HHVM, from [general questions](https://github.com/facebook/hiphop-php/wiki/FAQ#general) to questions geared towards those that want to [use](https://github.com/facebook/hiphop-php/wiki/FAQ#users) or [contribute](https://github.com/facebook/hiphop-php/wiki/FAQ#contributors) to HHVM.
|
||||
|
||||
## Installing
|
||||
|
||||
You can install a [prebuilt package](https://github.com/facebook/hhvm/wiki#installing-pre-built-packages-for-hhvm) or [compile from source](https://github.com/facebook/hhvm/wiki#building-hhvm).
|
||||
You can install a [prebuilt package](https://github.com/facebook/hiphop-php/wiki#installing-pre-built-packages-for-hhvm) or [compile from source](https://github.com/facebook/hiphop-php/wiki#building-hhvm).
|
||||
|
||||
## Running
|
||||
|
||||
You can run standalone programs just by passing them to hhvm: `hhvm my_script.php`.
|
||||
|
||||
HHVM bundles in a webserver. So if you want to run on port 80 in the current directory:
|
||||
HipHop bundles in a webserver. So if you want to run on port 80 in the current directory:
|
||||
|
||||
```
|
||||
sudo hhvm -m server
|
||||
```
|
||||
|
||||
For anything more complicated, you'll want to make a [config.hdf](https://github.com/facebook/hhvm/wiki/Runtime-options#server) and run `sudo hhvm -m server -c config.hdf`.
|
||||
For anything more complicated, you'll want to make a [config.hdf](https://github.com/facebook/hiphop-php/wiki/Runtime-options#server) and run `sudo hhvm -m server -c config.hdf`.
|
||||
|
||||
## Contributing
|
||||
|
||||
We'd love to have your help in making HHVM better.
|
||||
We'd love to have your help in making HipHop better.
|
||||
|
||||
Before changes can be accepted a [Contributor License Agreement](http://developers.facebook.com/opensource/cla) ([pdf](https://github.com/facebook/hhvm/raw/master/hphp/doc/FB_Individual_CLA.pdf) - print, sign, scan, link) must be signed.
|
||||
Before changes can be accepted a [Contributor License Agreement](http://developers.facebook.com/opensource/cla) ([pdf](https://github.com/facebook/hiphop-php/raw/master/hphp/doc/FB_Individual_CLA.pdf) - print, sign, scan, link) must be signed.
|
||||
|
||||
If you run into problems, please open an [issue](http://github.com/facebook/hhvm/issues), or better yet, [fork us and send a pull request](https://github.com/facebook/hhvm/pulls). Join us on [#hhvm on freenode](http://webchat.freenode.net/?channels=hhvm).
|
||||
If you run into problems, please open an [issue](http://github.com/facebook/hiphop-php/issues), or better yet, [fork us and send a pull request](https://github.com/facebook/hiphop-php/pulls). Join us on [#hhvm on freenode](http://webchat.freenode.net/?channels=hhvm).
|
||||
|
||||
If you want to help but don't know where to start, try fixing some of the [Zend tests that don't pass](hphp/test/zend/bad). You can run them with [hphp/test/run](hphp/test/run). When they work, move them to [zend/good](hphp/test/zend/good) and send a pull request.
|
||||
|
||||
All the open issues tagged [Zend incompatibility](https://github.com/facebook/hhvm/issues?labels=zend+incompatibility&page=1&state=open) are real issues reported by the community in existing PHP code and [frameworks](https://github.com/facebook/hhvm/wiki/OSS-PHP-Frameworks-Unit-Testing:-General) that could use some attention. Please add appropriate test cases as you make changes; see [here](hphp/test) for more information. Travis-CI is integrated with this GitHub project and will provide test results automatically on all pulls.
|
||||
All the open issues tagged [Zend incompatibility](https://github.com/facebook/hiphop-php/issues?labels=zend+incompatibility&page=1&state=open) are real issues reported by the community in existing PHP code and [frameworks](https://github.com/facebook/hiphop-php/wiki/OSS-PHP-Frameworks-Unit-Testing:-General) that could use some attention. Please add appropriate test cases as you make changes; see [here](hphp/test) for more information. Travis-CI is integrated with this GitHub project and will provide test results automatically on all pulls.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
HHVM is licensed under the PHP and Zend licenses except as otherwise noted.
|
||||
HipHop VM is licensed under the PHP and Zend licenses except as otherwise noted.
|
||||
|
||||
## Reporting Crashes
|
||||
|
||||
See [Reporting Crashes](https://github.com/facebook/hhvm/wiki/Reporting-Crashes) for helpful tips on how to report crashes in an actionable manner.
|
||||
See [Reporting Crashes](https://github.com/facebook/hiphop-php/wiki/Reporting-Crashes) for helpful tips on how to report crashes in an actionable manner.
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
This file just exists to keep the bin/ directory in git.
|
||||
externo
+1
-1
@@ -3,7 +3,7 @@
|
||||
if [ "$1" = '--help' ] || [ "$1" = '-h' ]; then
|
||||
echo 'usage: ./configure -Dvariable=argument ...\n'
|
||||
echo 'Variables: '
|
||||
echo ' CMAKE_BUILD_TYPE=Debug|Release Sets build type (default Release).'
|
||||
echo ' CMAKE_BUILD_TYPE=Debug|Release Sets build type (default Relase).'
|
||||
|
||||
exit 2
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#########################################
|
||||
#
|
||||
# Install all the dependencies for HipHop
|
||||
# Install all the dependancies for HipHop
|
||||
#
|
||||
#########################################
|
||||
|
||||
@@ -20,15 +20,12 @@ if [ "x${TRAVIS}" != "x" ]; then
|
||||
fi
|
||||
|
||||
export CMAKE_PREFIX_PATH=`/bin/pwd`/..
|
||||
export HPHP_HOME=`/bin/pwd`
|
||||
|
||||
# install python-software-properties before trying to add a PPA
|
||||
sudo apt-get -y update
|
||||
sudo apt-get install -y python-software-properties
|
||||
|
||||
# install apt-fast to speed up later dependency installation
|
||||
# install apt-fast to speedup later dependency installation
|
||||
sudo add-apt-repository -y ppa:apt-fast/stable
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install apt-fast
|
||||
sudo apt-get update
|
||||
sudo apt-get install apt-fast
|
||||
|
||||
# install the actual dependencies
|
||||
sudo apt-fast -y update
|
||||
@@ -36,8 +33,8 @@ sudo apt-fast -y install git-core cmake g++ libboost1.48-dev libmysqlclient-dev
|
||||
libxml2-dev libmcrypt-dev libicu-dev openssl build-essential binutils-dev \
|
||||
libcap-dev libgd2-xpm-dev zlib1g-dev libtbb-dev libonig-dev libpcre3-dev \
|
||||
autoconf libtool libcurl4-openssl-dev libboost-regex1.48-dev libboost-system1.48-dev \
|
||||
libboost-program-options1.48-dev libboost-filesystem1.48-dev libboost-thread1.48-dev \
|
||||
wget memcached libreadline-dev libncurses-dev libmemcached-dev libbz2-dev \
|
||||
libboost-program-options1.48-dev libboost-filesystem1.48-dev wget memcached \
|
||||
libreadline-dev libncurses-dev libmemcached-dev libbz2-dev \
|
||||
libc-client2007e-dev php5-mcrypt php5-imagick libgoogle-perftools-dev \
|
||||
libcloog-ppl0 libelf-dev libdwarf-dev libunwind7-dev subversion &
|
||||
|
||||
@@ -46,9 +43,6 @@ git clone git://github.com/bagder/curl.git --quiet &
|
||||
svn checkout http://google-glog.googlecode.com/svn/trunk/ google-glog --quiet &
|
||||
wget http://www.canonware.com/download/jemalloc/jemalloc-3.0.0.tar.bz2 --quiet &
|
||||
|
||||
# init submodules
|
||||
git submodule update --init
|
||||
|
||||
# wait until all background processes finished
|
||||
FAIL=0
|
||||
|
||||
@@ -66,22 +60,6 @@ else
|
||||
exit 100
|
||||
fi
|
||||
|
||||
# Leave this install till after the main parallel package install above
|
||||
# since it adds a non-12.04 package repo and we don't want to
|
||||
# pull EVERYTHING in, just the newer gcc compiler (and toolchain)
|
||||
GCC_VER=4.7
|
||||
if [ "x${TRAVIS}" != "x" ]; then
|
||||
GCC_VER=4.8
|
||||
fi
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install gcc-${GCC_VER} g++-${GCC_VER}
|
||||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VER} 60 \
|
||||
--slave /usr/bin/g++ g++ /usr/bin/g++-${GCC_VER}
|
||||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 40 \
|
||||
--slave /usr/bin/g++ g++ /usr/bin/g++-4.6
|
||||
sudo update-alternatives --set gcc /usr/bin/gcc-${GCC_VER}
|
||||
|
||||
# libevent
|
||||
cd libevent
|
||||
git checkout release-1.4.14b-stable
|
||||
@@ -123,4 +101,4 @@ cmake .
|
||||
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "Done. Now run:"
|
||||
echo " CMAKE_PREFIX_PATH=\`pwd\`/.. make"
|
||||
echo " CMAKE_PREFIX_PATH=\`pwd\`/.. HPHP_HOME=\`pwd\` make"
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# HHVM build results
|
||||
*.hhbc
|
||||
*.[oa]
|
||||
/hhvm/hhvm
|
||||
/hhvm/hphp
|
||||
|
||||
# vim swapfiles
|
||||
.*.swp
|
||||
.*.swo
|
||||
|
||||
# tags files
|
||||
*/tags
|
||||
*/TAGS
|
||||
|
||||
# logs
|
||||
*.log
|
||||
|
||||
# git patch files
|
||||
*.diff
|
||||
|
||||
# OS X
|
||||
.DS_Store
|
||||
._.DS_Store
|
||||
|
||||
# gdb
|
||||
.gdb_history
|
||||
+50
-13
@@ -16,12 +16,44 @@
|
||||
#
|
||||
|
||||
include(HPHPSetup)
|
||||
include(FollySetup)
|
||||
include(ExtZendCompat)
|
||||
|
||||
add_definitions("-DHHVM")
|
||||
# HHVM Build
|
||||
SET(USE_HHVM TRUE)
|
||||
SET(ENV{HHVM} 1)
|
||||
ADD_DEFINITIONS("-DHHVM -DHHVM_BINARY=1 -DHHVM_PATH=\\\"${HPHP_HOME}/hphp/hhvm/hhvm\\\"")
|
||||
|
||||
add_subdirectory(tools/bootstrap)
|
||||
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/debugger runtime/eval runtime/ext runtime/server runtime/vm)
|
||||
foreach (dir ${RECURSIVE_SOURCE_SUBDIRS})
|
||||
auto_sources(files "*.cpp" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
|
||||
list(APPEND CXX_SOURCES ${files})
|
||||
|
||||
auto_sources(files "*.c" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
|
||||
list(APPEND C_SOURCES ${files})
|
||||
|
||||
auto_sources(files "*.S" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
|
||||
list(APPEND ASM_SOURCES ${files})
|
||||
endforeach(dir ${RECURSIVE_SOURCE_SUBDIRS})
|
||||
|
||||
if(NOT LINUX)
|
||||
add_definitions(-DNO_HARDWARE_COUNTERS)
|
||||
list(REMOVE_ITEM CXX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/runtime/vm/debug/elfwriter.cpp)
|
||||
endif()
|
||||
|
||||
# Not working with off-the-shelf libevent
|
||||
list(REMOVE_ITEM CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/runtime/server/server-name-indication.cpp")
|
||||
|
||||
# remove ext_hhvm, and anything in a test folder
|
||||
foreach (file ${CXX_SOURCES})
|
||||
if (${file} MATCHES "ext_hhvm")
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif()
|
||||
if (${file} MATCHES "/test/")
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif()
|
||||
endforeach(file ${CXX_SOURCES})
|
||||
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||
|
||||
add_subdirectory(third_party/libafdt)
|
||||
add_subdirectory(third_party/libmbfl)
|
||||
@@ -30,11 +62,19 @@ add_subdirectory(third_party/timelib)
|
||||
add_subdirectory(third_party/lz4)
|
||||
add_subdirectory(third_party/double-conversion)
|
||||
add_subdirectory(third_party/folly)
|
||||
add_subdirectory(third_party/libzip)
|
||||
if(ENABLE_FASTCGI)
|
||||
add_subdirectory(third_party/ti)
|
||||
add_subdirectory(third_party/thrift)
|
||||
endif()
|
||||
|
||||
ADD_LIBRARY(hphp_runtime_static STATIC
|
||||
${CXX_SOURCES} ${C_SOURCES} ${ASM_SOURCES})
|
||||
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES OUTPUT_NAME "hphp_runtime")
|
||||
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES PREFIX "lib")
|
||||
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
SET(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
|
||||
hphp_link(hphp_runtime_static)
|
||||
add_dependencies(hphp_runtime_static hphp_parser)
|
||||
|
||||
add_subdirectory("tools/bootstrap")
|
||||
|
||||
add_subdirectory(vixl)
|
||||
add_subdirectory(neo)
|
||||
@@ -42,13 +82,10 @@ add_subdirectory(parser)
|
||||
add_subdirectory(zend)
|
||||
add_subdirectory(util)
|
||||
|
||||
add_subdirectory(hhbbc)
|
||||
add_subdirectory(compiler)
|
||||
add_subdirectory(runtime)
|
||||
add_subdirectory(runtime/ext_hhvm)
|
||||
add_subdirectory(system)
|
||||
|
||||
add_subdirectory(hhvm)
|
||||
add_subdirectory(system)
|
||||
|
||||
if (NOT "$ENV{HPHP_NOTEST}" STREQUAL "1")
|
||||
add_subdirectory(test)
|
||||
|
||||
+7
-102
@@ -1,104 +1,9 @@
|
||||
Next release
|
||||
- FrozenMap collection
|
||||
- Deprecated Vector|Set|Map::put() method removed
|
||||
- == between Frozen{Vector|Set|Map} and {Vector|Set|Map} now can return true
|
||||
- Map collections learned the in-place retain() and retainWithKey()
|
||||
- 'num' scalar typehint that accepts both ints and floats
|
||||
|
||||
"Beastie Boys" 6-Jan-2014
|
||||
- Support lex-time binary constants (eg. 0b10111)
|
||||
- StreamWrappers now support rmdir, mkdir, rename and unlink
|
||||
- Miscellaneous Zend PHP compatibility fixes
|
||||
- Default StatCache to off
|
||||
- Miscellaneous FastCGI fixes
|
||||
- Miscellaneous region compiler fixes
|
||||
- Map and StableMap collections use the same underlying implementation
|
||||
- Trait requirements enforced
|
||||
- hhprof performance improvements
|
||||
- Add array to string conversion notice
|
||||
- Add RaiseNotice IR opcode
|
||||
- Fix VirtualHost.<name>.Pattern matching
|
||||
- Fix various memory leaks (pdo_parse_params, Gen*WaitHandle)
|
||||
- Import a lot more Zend tests that used to crash or hang
|
||||
- Clean up base.h
|
||||
- XLS register allocation cleanup
|
||||
- Enable region compiler by default for JIT functions in ahot
|
||||
- Fatal on eval() in RepoAuthoritative mode
|
||||
- Enable LTO for HHVM
|
||||
- Fix a few SPL compatibility issues
|
||||
|
||||
"Appleseed" 23-Dec-2013
|
||||
- Fix issues with DOCUMENT_ROOT in fastcgi
|
||||
- Better type inference for collections and builtins in repo mode
|
||||
- Shorter syntax for lambda expressions w/ automatic captures
|
||||
- Parser support for trait require clauses
|
||||
- Move FrozenVector and Set to the HH namespace
|
||||
- Fix resource to array conversion
|
||||
- Fix a request local memory leak in foreach of apc arrays
|
||||
- Initial php_odbc API implementation
|
||||
- Implement PHP's hash_copy() function
|
||||
- Experimental tool: Memoization Opportunity Profiler
|
||||
- Various small parity/behavior fixes (in phar, proc_open, filter_var)
|
||||
- A Eval.DumpHhas=1 option to dump hhas for a php file
|
||||
- Better warnings in Set::toArray
|
||||
- Fix the behavior of foreach loops in finally blocks
|
||||
- chmod -x runtime/vm/jit/*.{cpp,h}
|
||||
- Changes to make hhvm build clean with clang-3.4
|
||||
- Fix array_product to not be bug-compatible with PHP 5.2
|
||||
- Change the Map datastructure---preserves order and does faster foreach
|
||||
- FrozenSet collection
|
||||
- Generate pid.map when we unmap text section, for the perf tool
|
||||
- Implemented GlobIterator
|
||||
- Implemented Reflection::export and Reflection::getModifierNames
|
||||
|
||||
"Tom Yum" 9-Dec-2013
|
||||
- support date.timezone in ini files
|
||||
- implement fileinfo
|
||||
- special comparisons for DateTime
|
||||
- delete unimplemented functions
|
||||
- support for the finally clause in try blocks
|
||||
|
||||
"Huarache" 26-Nov-2013
|
||||
- Linker re-ordering of hot functions
|
||||
- Huge pages for hot functions
|
||||
- Implement ZipArchive
|
||||
- preg_replace /e support
|
||||
- get_mem_usage() no longer can be negative
|
||||
- Userland file system support
|
||||
- Implement fileinfo extension
|
||||
- wordwrap() fixes
|
||||
- PDO::sqliteCreateFunction()
|
||||
- Implement NumberFormatter
|
||||
- Implement Locale
|
||||
- Implement DatePeriod
|
||||
- Many reflection fixes
|
||||
- Stub out PharData
|
||||
- A ton of performance fixes
|
||||
- A ton of open source framework fixes
|
||||
- FastCGI Server Support
|
||||
|
||||
"Garlic Alfredo" 11-Nov-2013
|
||||
- teach implode() about collections
|
||||
- fix ini parsing leak
|
||||
- Make array not an instanceof Traversable
|
||||
|
||||
"Burrito" 28-Oct-2013
|
||||
- Initial support for using FastCGI
|
||||
- Initial support for php.ini configuration files
|
||||
- Log when a nullable (e.g. ?int) is incorrect
|
||||
- Add support for collections to array_diff, array_diff_key, array_intersect,
|
||||
array_intersect_key
|
||||
- tc-print improvements and fixes
|
||||
- Several debugger fixes
|
||||
- More improvements to the experimental PHP extension compat layer
|
||||
- Fixed how parse errors are handled by eval()
|
||||
- Support custom reason for status header
|
||||
- Emit better error message when hhvm's systemlib doesn't load properly
|
||||
- Fixes / clarifications added to the bytecode specification
|
||||
- Lots of other bug fixes, clean up, PHP compat fixes, and JIT improvements
|
||||
- <cool stuff goes here>
|
||||
|
||||
"Sausage" 14-Oct-2013
|
||||
- Direct invocation of callable arrays: $f = [$cls_or_obj, 'method']; $f()
|
||||
- Fixed issue that caused memory_get_usage to report double the actual usage.
|
||||
- Direct invocation of callable arrays: $f = [$cls_or_instance, 'method']; $f()
|
||||
- ASAN clean
|
||||
- Support dynamically loadable extensions
|
||||
- Support loading mini-systemlibs from extensions
|
||||
@@ -120,7 +25,7 @@ Next release
|
||||
- Support arbitrary expressions inside empty()
|
||||
|
||||
"Bobotie" 16-Sep-2013
|
||||
- HNI (HipHop Native Interface) for calling C++ functions from PHP
|
||||
- HNI (HipHop Native Interface) for calling C++ functions from Php
|
||||
- Fix PropertyAccessorMap::isset
|
||||
- Expose more POSIX constants
|
||||
- Fixed behavior of stream_get_contents when default args are used.
|
||||
@@ -134,14 +39,14 @@ Next release
|
||||
- Import ftp extension
|
||||
|
||||
"Kimchi" 2-Sep-2013
|
||||
- Fix order of custom attributes and visibility in ctor arg promotion
|
||||
- Fix order of custom attributes and visibility in ctor arg promotion
|
||||
- Implement CachingIterator
|
||||
- Implement RecursiveCachingIterator
|
||||
- Generalized heuristic for choosing when to inline in the jit
|
||||
- Introduced a Zend compatibility layer to compile extensions
|
||||
- Imported calendar extension
|
||||
- Use gcc-4.8.1 by default
|
||||
- Improve hhvm command line parsing logic
|
||||
- Improve hhvm commandline parsing logic
|
||||
- Fix register_shutdown in session_set_save_handler to match PHP 5.4
|
||||
- Add "native" functions for use in Systemlib
|
||||
- PHP extension source-compatitblility layer
|
||||
@@ -199,7 +104,7 @@ Next release
|
||||
"Wasabi Peas" 08-Jul-2013
|
||||
- always_assert when we run out of TC space
|
||||
- Initial changes to get HHVM compiling on OSX
|
||||
- Consolidate ObjectData and Instance
|
||||
- Consolodate ObjectData and Instance
|
||||
- Prototype heap tracing framework & Heap profiler
|
||||
- Better JIT code generation for Mod and Div
|
||||
- Fixes to enable compilation with clang
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#include "hphp/compiler/analysis/live_dict.h"
|
||||
#include "hphp/compiler/analysis/ref_dict.h"
|
||||
|
||||
#include "hphp/runtime/vm/runtime.h"
|
||||
#include "hphp/runtime/base/builtin-functions.h"
|
||||
|
||||
#include "hphp/parser/hphp.tab.hpp"
|
||||
#include "hphp/parser/location.h"
|
||||
@@ -1927,7 +1927,6 @@ StatementPtr AliasManager::canonicalizeRecur(StatementPtr s, int &ret) {
|
||||
|
||||
switch (stype) {
|
||||
case Statement::KindOfUseTraitStatement:
|
||||
case Statement::KindOfTraitRequireStatement:
|
||||
case Statement::KindOfTraitPrecStatement:
|
||||
case Statement::KindOfTraitAliasStatement:
|
||||
return StatementPtr();
|
||||
@@ -1969,7 +1968,7 @@ StatementPtr AliasManager::canonicalizeRecur(StatementPtr s, int &ret) {
|
||||
}
|
||||
|
||||
case Statement::KindOfIfBranchStatement:
|
||||
always_assert(false);
|
||||
always_assert(0);
|
||||
break;
|
||||
|
||||
case Statement::KindOfForStatement: {
|
||||
@@ -2109,6 +2108,7 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
|
||||
}
|
||||
|
||||
cs->clearVisited();
|
||||
cs->clearChildOfYield();
|
||||
|
||||
StatementPtr s = dpc(Statement, cs);
|
||||
if (s) {
|
||||
@@ -2361,6 +2361,9 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
|
||||
case Expression::KindOfSimpleFunctionCall:
|
||||
{
|
||||
SimpleFunctionCallPtr sfc(spc(SimpleFunctionCall, e));
|
||||
if (sfc->getName() == "hphp_create_continuation") {
|
||||
m_inlineAsExpr = false;
|
||||
}
|
||||
sfc->updateVtFlags();
|
||||
}
|
||||
case Expression::KindOfDynamicFunctionCall:
|
||||
@@ -2396,6 +2399,9 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
|
||||
// expressions. TODO: revisit this later
|
||||
m_inlineAsExpr = false;
|
||||
break;
|
||||
case Expression::KindOfYieldExpression:
|
||||
spc(YieldExpression, e)->getValueExpression()->setChildOfYield();
|
||||
break;
|
||||
case Expression::KindOfUnaryOpExpression:
|
||||
if (Option::EnableEval > Option::NoEval && spc(UnaryOpExpression, e)->
|
||||
getOp() == T_EVAL) {
|
||||
@@ -2531,10 +2537,8 @@ public:
|
||||
}
|
||||
private:
|
||||
|
||||
#define CONSTRUCT_EXP(from) \
|
||||
#define CONSTRUCT_PARAMS(from) \
|
||||
(from)->getScope(), (from)->getLocation()
|
||||
#define CONSTRUCT_STMT(from) \
|
||||
(from)->getScope(), (from)->getLabelScope(), (from)->getLocation()
|
||||
|
||||
AnalysisResultConstPtr m_ar;
|
||||
bool m_changed;
|
||||
@@ -2607,7 +2611,7 @@ private:
|
||||
|
||||
ExpressionListPtr el(
|
||||
new ExpressionList(
|
||||
CONSTRUCT_EXP(target),
|
||||
CONSTRUCT_PARAMS(target),
|
||||
ExpressionList::ListKindComma));
|
||||
if (target->isUnused()) {
|
||||
el->setUnused(true);
|
||||
@@ -2951,7 +2955,7 @@ private:
|
||||
slistPtr->insertElement(
|
||||
ExpStatementPtr(
|
||||
new ExpStatement(
|
||||
CONSTRUCT_STMT(slistPtr), assertion)),
|
||||
CONSTRUCT_PARAMS(slistPtr), assertion)),
|
||||
idx);
|
||||
}
|
||||
break;
|
||||
@@ -3032,12 +3036,12 @@ private:
|
||||
} else {
|
||||
ExpStatementPtr newExpStmt(
|
||||
new ExpStatement(
|
||||
CONSTRUCT_STMT(branch),
|
||||
CONSTRUCT_PARAMS(branch),
|
||||
after));
|
||||
|
||||
IfBranchStatementPtr newBranch(
|
||||
new IfBranchStatement(
|
||||
CONSTRUCT_STMT(branch),
|
||||
CONSTRUCT_PARAMS(branch),
|
||||
ExpressionPtr(), newExpStmt));
|
||||
|
||||
branches->addElement(newBranch);
|
||||
@@ -3304,12 +3308,6 @@ private:
|
||||
static bool isNewResult(ExpressionPtr e) {
|
||||
if (!e) return false;
|
||||
if (e->is(Expression::KindOfNewObjectExpression)) return true;
|
||||
if (e->is(Expression::KindOfBinaryOpExpression)) {
|
||||
auto b = spc(BinaryOpExpression, e);
|
||||
if (b->getOp() == T_COLLECTION) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (e->is(Expression::KindOfAssignmentExpression)) {
|
||||
return isNewResult(spc(AssignmentExpression, e)->getValue());
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "hphp/compiler/statement/loop_statement.h"
|
||||
#include "hphp/compiler/statement/class_variable.h"
|
||||
#include "hphp/compiler/statement/use_trait_statement.h"
|
||||
#include "hphp/compiler/statement/trait_require_statement.h"
|
||||
#include "hphp/compiler/analysis/symbol_table.h"
|
||||
#include "hphp/compiler/package.h"
|
||||
#include "hphp/compiler/parser/parser.h"
|
||||
@@ -489,7 +488,8 @@ void AnalysisResult::link(FileScopePtr user, FileScopePtr provider) {
|
||||
|
||||
bool AnalysisResult::addClassDependency(FileScopePtr usingFile,
|
||||
const std::string &className) {
|
||||
if (m_systemClasses.find(className) != m_systemClasses.end())
|
||||
if (BuiltinSymbols::s_classes.find(className) !=
|
||||
BuiltinSymbols::s_classes.end())
|
||||
return true;
|
||||
|
||||
StringToClassScopePtrVecMap::const_iterator iter =
|
||||
@@ -507,7 +507,8 @@ bool AnalysisResult::addClassDependency(FileScopePtr usingFile,
|
||||
|
||||
bool AnalysisResult::addFunctionDependency(FileScopePtr usingFile,
|
||||
const std::string &functionName) {
|
||||
if (m_functions.find(functionName) != m_functions.end())
|
||||
if (BuiltinSymbols::s_functions.find(functionName) !=
|
||||
BuiltinSymbols::s_functions.end())
|
||||
return true;
|
||||
StringToFunctionScopePtrMap::const_iterator iter =
|
||||
m_functionDecs.find(functionName);
|
||||
@@ -569,16 +570,12 @@ bool AnalysisResult::isSystemConstant(const std::string &constName) const {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Program
|
||||
|
||||
void AnalysisResult::addSystemFunction(FunctionScopeRawPtr fs) {
|
||||
FunctionScopePtr& entry = m_functions[fs->getName()];
|
||||
assert(!entry);
|
||||
entry = fs;
|
||||
}
|
||||
|
||||
void AnalysisResult::addSystemClass(ClassScopeRawPtr cs) {
|
||||
ClassScopePtr& entry = m_systemClasses[cs->getName()];
|
||||
assert(!entry);
|
||||
entry = cs;
|
||||
void AnalysisResult::loadBuiltins() {
|
||||
AnalysisResultPtr ar = shared_from_this();
|
||||
BuiltinSymbols::LoadFunctions(ar, m_functions);
|
||||
BuiltinSymbols::LoadClasses(ar, m_systemClasses);
|
||||
BuiltinSymbols::LoadVariables(ar, m_variables);
|
||||
BuiltinSymbols::LoadConstants(ar, m_constants);
|
||||
}
|
||||
|
||||
void AnalysisResult::checkClassDerivations() {
|
||||
@@ -590,11 +587,7 @@ void AnalysisResult::checkClassDerivations() {
|
||||
hphp_string_iset seen;
|
||||
cls->checkDerivation(ar, seen);
|
||||
if (Option::WholeProgram) {
|
||||
try {
|
||||
cls->importUsedTraits(ar);
|
||||
} catch (const AnalysisTimeFatalException& e) {
|
||||
cls->setFatal(e);
|
||||
}
|
||||
cls->importUsedTraits(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -612,26 +605,22 @@ void AnalysisResult::resolveNSFallbackFuncs() {
|
||||
}
|
||||
|
||||
void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
|
||||
for (const auto& iter : fs->getFunctions()) {
|
||||
FunctionScopePtr func = iter.second;
|
||||
const StringToFunctionScopePtrMap &funcs = fs->getFunctions();
|
||||
|
||||
for (StringToFunctionScopePtrMap::const_iterator iter = funcs.begin();
|
||||
iter != funcs.end(); ++iter) {
|
||||
FunctionScopePtr func = iter->second;
|
||||
if (!func->inPseudoMain()) {
|
||||
FunctionScopePtr &funcDec = m_functionDecs[iter.first];
|
||||
FunctionScopePtr &funcDec = m_functionDecs[iter->first];
|
||||
if (funcDec) {
|
||||
if (funcDec->isSystem()) {
|
||||
assert(funcDec->allowOverride());
|
||||
funcDec = func;
|
||||
} else if (func->isSystem()) {
|
||||
assert(func->allowOverride());
|
||||
} else {
|
||||
FunctionScopePtrVec &funcVec = m_functionReDecs[iter.first];
|
||||
int sz = funcVec.size();
|
||||
if (!sz) {
|
||||
funcDec->setRedeclaring(sz++);
|
||||
funcVec.push_back(funcDec);
|
||||
}
|
||||
func->setRedeclaring(sz++);
|
||||
funcVec.push_back(func);
|
||||
FunctionScopePtrVec &funcVec = m_functionReDecs[iter->first];
|
||||
int sz = funcVec.size();
|
||||
if (!sz) {
|
||||
funcDec->setRedeclaring(sz++);
|
||||
funcVec.push_back(funcDec);
|
||||
}
|
||||
func->setRedeclaring(sz++);
|
||||
funcVec.push_back(func);
|
||||
} else {
|
||||
funcDec = func;
|
||||
}
|
||||
@@ -639,12 +628,13 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
|
||||
}
|
||||
|
||||
if (const StringToFunctionScopePtrVecMap *redec = fs->getRedecFunctions()) {
|
||||
for (const auto &iter : *redec) {
|
||||
FunctionScopePtrVec::const_iterator i = iter.second.begin();
|
||||
FunctionScopePtrVec::const_iterator e = iter.second.end();
|
||||
FunctionScopePtr &funcDec = m_functionDecs[iter.first];
|
||||
for (StringToFunctionScopePtrVecMap::const_iterator iter = redec->begin();
|
||||
iter != redec->end(); ++iter) {
|
||||
FunctionScopePtrVec::const_iterator i = iter->second.begin();
|
||||
FunctionScopePtrVec::const_iterator e = iter->second.end();
|
||||
FunctionScopePtr &funcDec = m_functionDecs[iter->first];
|
||||
assert(funcDec); // because the first one was in funcs above
|
||||
FunctionScopePtrVec &funcVec = m_functionReDecs[iter.first];
|
||||
FunctionScopePtrVec &funcVec = m_functionReDecs[iter->first];
|
||||
int sz = funcVec.size();
|
||||
if (!sz) {
|
||||
funcDec->setRedeclaring(sz++);
|
||||
@@ -657,9 +647,11 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& iter : fs->getClasses()) {
|
||||
ClassScopePtrVec &clsVec = m_classDecs[iter.first];
|
||||
clsVec.insert(clsVec.end(), iter.second.begin(), iter.second.end());
|
||||
const StringToClassScopePtrVecMap &classes = fs->getClasses();
|
||||
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
|
||||
iter != classes.end(); ++iter) {
|
||||
ClassScopePtrVec &clsVec = m_classDecs[iter->first];
|
||||
clsVec.insert(clsVec.end(), iter->second.begin(), iter->second.end());
|
||||
}
|
||||
|
||||
m_classAliases.insert(fs->getClassAliases().begin(),
|
||||
@@ -975,14 +967,11 @@ struct OptVisitor {
|
||||
|
||||
AnalysisResultPtr m_ar;
|
||||
unsigned m_nscope;
|
||||
JobQueueDispatcher<OptWorker<When>> *m_dispatcher;
|
||||
JobQueueDispatcher<BlockScope *, OptWorker<When> > *m_dispatcher;
|
||||
};
|
||||
|
||||
template <typename When>
|
||||
class OptWorker : public JobQueueWorker<BlockScope*,
|
||||
void*,
|
||||
true,
|
||||
true> {
|
||||
class OptWorker : public JobQueueWorker<BlockScope *, true, true> {
|
||||
public:
|
||||
OptWorker() {}
|
||||
|
||||
@@ -1001,8 +990,8 @@ public:
|
||||
acc->second += 1;
|
||||
#endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */
|
||||
try {
|
||||
auto visitor =
|
||||
(DepthFirstVisitor<When, OptVisitor>*) m_context;
|
||||
DepthFirstVisitor<When, OptVisitor > *visitor =
|
||||
(DepthFirstVisitor<When, OptVisitor >*)m_opaque;
|
||||
{
|
||||
Lock ldep(BlockScope::s_depsMutex);
|
||||
Lock lstate(BlockScope::s_jobStateMutex);
|
||||
@@ -1191,7 +1180,7 @@ void OptWorker<Pre>::onThreadExit() {
|
||||
} \
|
||||
if (threadCount <= 0) threadCount = 1; \
|
||||
this->m_data.m_dispatcher = \
|
||||
new JobQueueDispatcher<worker>( \
|
||||
new JobQueueDispatcher<BlockScope *, worker >( \
|
||||
threadCount, true, 0, false, this); \
|
||||
} while (0)
|
||||
|
||||
@@ -1236,7 +1225,7 @@ template <typename When>
|
||||
void
|
||||
AnalysisResult::preWaitCallback(bool first,
|
||||
const BlockScopeRawPtrQueue &scopes,
|
||||
void *context) {
|
||||
void *opaque) {
|
||||
// default is no-op
|
||||
}
|
||||
|
||||
@@ -1245,7 +1234,7 @@ bool
|
||||
AnalysisResult::postWaitCallback(bool first,
|
||||
bool again,
|
||||
const BlockScopeRawPtrQueue &scopes,
|
||||
void *context) {
|
||||
void *opaque) {
|
||||
// default is no-op
|
||||
return again;
|
||||
}
|
||||
@@ -1310,7 +1299,7 @@ struct BIPairCmp {
|
||||
template <typename When>
|
||||
void
|
||||
AnalysisResult::processScopesParallel(const char *id,
|
||||
void *context /* = NULL */) {
|
||||
void *opaque /* = NULL */) {
|
||||
BlockScopeRawPtrQueue scopes;
|
||||
getScopesSet(scopes);
|
||||
|
||||
@@ -1347,7 +1336,7 @@ AnalysisResult::processScopesParallel(const char *id,
|
||||
|
||||
BlockScopeRawPtrQueue enqueued;
|
||||
again = dfv.visitParallel(scopes, first, enqueued);
|
||||
preWaitCallback<When>(first, scopes, context);
|
||||
preWaitCallback<When>(first, scopes, opaque);
|
||||
|
||||
#ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL
|
||||
{
|
||||
@@ -1401,7 +1390,7 @@ AnalysisResult::processScopesParallel(const char *id,
|
||||
std::cout << "Number of waiting scopes: " << numWaiting << std::endl;
|
||||
#endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */
|
||||
|
||||
again = postWaitCallback<When>(first, again, scopes, context);
|
||||
again = postWaitCallback<When>(first, again, scopes, opaque);
|
||||
first = false;
|
||||
} while (again);
|
||||
dfv.data().stop();
|
||||
@@ -1573,8 +1562,7 @@ DepthFirstVisitor<InferTypes, OptVisitor>::visitScope(BlockScopeRawPtr scope) {
|
||||
|
||||
template<>
|
||||
bool AnalysisResult::postWaitCallback<InferTypes>(
|
||||
bool first, bool again,
|
||||
const BlockScopeRawPtrQueue &scopes, void *context) {
|
||||
bool first, bool again, const BlockScopeRawPtrQueue &scopes, void *opaque) {
|
||||
|
||||
#ifdef HPHP_INSTRUMENT_TYPE_INF
|
||||
std::cout << "Number of rescheduled: " <<
|
||||
@@ -1616,10 +1604,12 @@ void AnalysisResult::inferTypes() {
|
||||
BlockScopeRawPtrQueue scopes;
|
||||
getScopesSet(scopes);
|
||||
|
||||
for (auto scope : scopes) {
|
||||
scope->setInTypeInference(true);
|
||||
scope->clearUpdated();
|
||||
assert(scope->getNumDepsToWaitFor() == 0);
|
||||
for (BlockScopeRawPtrQueue::iterator
|
||||
it = scopes.begin(), end = scopes.end();
|
||||
it != end; ++it) {
|
||||
(*it)->setInTypeInference(true);
|
||||
(*it)->clearUpdated();
|
||||
assert((*it)->getNumDepsToWaitFor() == 0);
|
||||
}
|
||||
|
||||
#ifdef HPHP_INSTRUMENT_TYPE_INF
|
||||
@@ -1630,11 +1620,13 @@ void AnalysisResult::inferTypes() {
|
||||
|
||||
processScopesParallel<InferTypes>("InferTypes");
|
||||
|
||||
for (auto scope : scopes) {
|
||||
scope->setInTypeInference(false);
|
||||
scope->clearUpdated();
|
||||
assert(scope->getMark() == BlockScope::MarkProcessed);
|
||||
assert(scope->getNumDepsToWaitFor() == 0);
|
||||
for (BlockScopeRawPtrQueue::iterator
|
||||
it = scopes.begin(), end = scopes.end();
|
||||
it != end; ++it) {
|
||||
(*it)->setInTypeInference(false);
|
||||
(*it)->clearUpdated();
|
||||
assert((*it)->getMark() == BlockScope::MarkProcessed);
|
||||
assert((*it)->getNumDepsToWaitFor() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1676,12 +1668,12 @@ StatementPtr DepthFirstVisitor<Post, OptVisitor>::visit(StatementPtr stmt) {
|
||||
return stmt->postOptimize(this->m_data.m_ar);
|
||||
}
|
||||
|
||||
class FinalWorker : public JobQueueWorker<MethodStatementPtr, AnalysisResult*> {
|
||||
class FinalWorker : public JobQueueWorker<MethodStatementPtr> {
|
||||
public:
|
||||
virtual void doJob(MethodStatementPtr m) {
|
||||
try {
|
||||
AliasManager am(1);
|
||||
am.finalSetup(m_context->shared_from_this(), m);
|
||||
am.finalSetup(((AnalysisResult*)m_opaque)->shared_from_this(), m);
|
||||
} catch (Exception &e) {
|
||||
Logger::Error("%s", e.getMessage().c_str());
|
||||
}
|
||||
@@ -1690,11 +1682,11 @@ public:
|
||||
|
||||
template<>
|
||||
void AnalysisResult::preWaitCallback<Post>(
|
||||
bool first, const BlockScopeRawPtrQueue &scopes, void *context) {
|
||||
assert(!Option::ControlFlow || context != nullptr);
|
||||
bool first, const BlockScopeRawPtrQueue &scopes, void *opaque) {
|
||||
assert(!Option::ControlFlow || opaque != nullptr);
|
||||
if (first && Option::ControlFlow) {
|
||||
auto *dispatcher
|
||||
= (JobQueueDispatcher<FinalWorker> *) context;
|
||||
JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *dispatcher
|
||||
= (JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *) opaque;
|
||||
for (BlockScopeRawPtrQueue::const_iterator it = scopes.begin(),
|
||||
end = scopes.end(); it != end; ++it) {
|
||||
BlockScopeRawPtr scope = *it;
|
||||
@@ -1718,7 +1710,7 @@ void AnalysisResult::postOptimize() {
|
||||
}
|
||||
if (threadCount <= 0) threadCount = 1;
|
||||
|
||||
JobQueueDispatcher<FinalWorker> dispatcher(
|
||||
JobQueueDispatcher<FinalWorker::JobType, FinalWorker> dispatcher(
|
||||
threadCount, true, 0, false, this);
|
||||
|
||||
processScopesParallel<Post>("PostOptimize", &dispatcher);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "hphp/compiler/analysis/symbol_table.h"
|
||||
#include "hphp/compiler/analysis/function_container.h"
|
||||
#include "hphp/compiler/package.h"
|
||||
#include "hphp/compiler/hphp.h"
|
||||
|
||||
#include "hphp/util/string-bag.h"
|
||||
#include "hphp/util/thread-local.h"
|
||||
@@ -37,7 +36,7 @@ namespace HPHP {
|
||||
|
||||
|
||||
DECLARE_BOOST_TYPES(ClassScope);
|
||||
DECLARE_EXTENDED_BOOST_TYPES(FileScope);
|
||||
DECLARE_BOOST_TYPES(FileScope);
|
||||
DECLARE_BOOST_TYPES(FunctionScope);
|
||||
DECLARE_BOOST_TYPES(Location);
|
||||
DECLARE_BOOST_TYPES(AnalysisResult);
|
||||
@@ -151,8 +150,7 @@ public:
|
||||
|
||||
void addNSFallbackFunc(ConstructPtr c, FileScopePtr fs);
|
||||
|
||||
void addSystemFunction(FunctionScopeRawPtr fs);
|
||||
void addSystemClass(ClassScopeRawPtr cs);
|
||||
void loadBuiltins();
|
||||
void analyzeProgram(bool system = false);
|
||||
void analyzeIncludes();
|
||||
void analyzeProgramFinal();
|
||||
|
||||
@@ -155,7 +155,9 @@ bool BlockScope::hasUser(BlockScopeRawPtr user, int useKinds) const {
|
||||
}
|
||||
|
||||
void BlockScope::addUse(BlockScopeRawPtr user, int useKinds) {
|
||||
if ((is(ClassScope) || is(FunctionScope)) && getStmt()) {
|
||||
if (is(ClassScope) ? static_cast<HPHP::ClassScope*>(this)->isUserClass() :
|
||||
is(FunctionScope) &&
|
||||
static_cast<HPHP::FunctionScope*>(this)->isUserFunction()) {
|
||||
|
||||
if (user.get() == this) {
|
||||
m_selfUser |= useKinds;
|
||||
|
||||
@@ -1,391 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/analysis/capture_extractor.h"
|
||||
#include "hphp/compiler/expression/join_clause.h"
|
||||
#include "hphp/compiler/expression/scalar_expression.h"
|
||||
#include "hphp/parser/hphp.tab.hpp"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Rewrites the construct rooted in cp so that it is in a form
|
||||
* that a query processor can evaluate while referencing only
|
||||
* state that is contained in the query processor or supplied
|
||||
* to the query processor in the form of arguments to the query.
|
||||
* For instance, a reference to a local variable in the scope
|
||||
* containing the query expression will be rewritten into a
|
||||
* reference to a (synthetic) parameter of the query expression.
|
||||
* This is similar to the way lambda expressions capture variables
|
||||
* from their enclosing environment.
|
||||
* Note that rewriting implies allocating new objects.
|
||||
* The original construct is not mutated in any way.
|
||||
* If the original construct is already in the right form, it is
|
||||
* returned as is.
|
||||
*/
|
||||
ExpressionPtr CaptureExtractor::rewrite(ExpressionPtr ep) {
|
||||
assert(ep != nullptr);
|
||||
switch (ep->getKindOf()) {
|
||||
case Expression::KindOfQueryExpression: {
|
||||
return rewriteQuery(static_pointer_cast<QueryExpression>(ep));
|
||||
}
|
||||
case Expression::KindOfSelectClause: {
|
||||
// leave select clauses alone, another visitor deals with them.
|
||||
return ep;
|
||||
}
|
||||
case Expression::KindOfFromClause:
|
||||
case Expression::KindOfLetClause:
|
||||
case Expression::KindOfIntoClause:
|
||||
case Expression::KindOfWhereClause: {
|
||||
return rewriteSimpleClause(static_pointer_cast<SimpleQueryClause>(ep));
|
||||
}
|
||||
case Expression::KindOfGroupClause:
|
||||
case Expression::KindOfJoinClause:
|
||||
case Expression::KindOfOrderbyClause:
|
||||
case Expression::KindOfOrdering: {
|
||||
// leave these alone. they are query specific and not parameterizable.
|
||||
return ep;
|
||||
}
|
||||
case Expression::KindOfObjectPropertyExpression: {
|
||||
return rewriteObjectProperty(
|
||||
static_pointer_cast<ObjectPropertyExpression>(ep));
|
||||
}
|
||||
case Expression::KindOfSimpleFunctionCall: {
|
||||
return rewriteCall(static_pointer_cast<SimpleFunctionCall>(ep));
|
||||
}
|
||||
case Expression::KindOfScalarExpression: {
|
||||
// Leave scalars alone. If the query processor can't handle them
|
||||
// rewriting won't help.
|
||||
return ep;
|
||||
}
|
||||
case Expression::KindOfUnaryOpExpression: {
|
||||
return rewriteUnary(static_pointer_cast<UnaryOpExpression>(ep));
|
||||
}
|
||||
case Expression::KindOfBinaryOpExpression: {
|
||||
return rewriteBinary(static_pointer_cast<BinaryOpExpression>(ep));
|
||||
}
|
||||
case Expression::KindOfSimpleVariable: {
|
||||
return rewriteSimpleVariable(static_pointer_cast<SimpleVariable>(ep));
|
||||
}
|
||||
case Expression::KindOfExpressionList: {
|
||||
return rewriteExpressionList(static_pointer_cast<ExpressionList>(ep));
|
||||
}
|
||||
default: {
|
||||
// If we get here, the expression is not a candidate for evaluation
|
||||
// by the query processor, so just turn it into a query parameter.
|
||||
return newQueryParamRef(ep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the given expression to end of the m_capturedExpressions list
|
||||
* and creates a new expression with the same scope and source location
|
||||
* that represents a reference to a query parameter. Query parameters do
|
||||
* not have a source code equivalent, but inform the query processor that
|
||||
* this expression represents the ith argument value, where i is zero based
|
||||
* and forms the last character of the special string @query_param_i.
|
||||
*/
|
||||
SimpleVariablePtr CaptureExtractor::newQueryParamRef(ExpressionPtr ae) {
|
||||
assert(ae != nullptr);
|
||||
char count = '0' + m_capturedExpressions.size();
|
||||
std::string pname = "@query_param_";
|
||||
pname.push_back(count);
|
||||
SimpleVariablePtr param(
|
||||
new SimpleVariable(ae->getScope(), ae->getLocation(), pname)
|
||||
);
|
||||
m_capturedExpressions.push_back(ae);
|
||||
return param;
|
||||
}
|
||||
|
||||
/**
|
||||
* If one or more of the arguments of the function call depend on query only
|
||||
* state (query local but not a query parameter reference), then rewrite
|
||||
* all of the arguments to be query local and return the rewritten
|
||||
* function call (the query processor has to either figure out a way to call
|
||||
* the function or must cause a runtime error when faced with the call).
|
||||
* Otherwise, rewrite the call as a query parameter reference.
|
||||
*/
|
||||
ExpressionPtr CaptureExtractor::rewriteCall(SimpleFunctionCallPtr sfc) {
|
||||
assert(sfc != nullptr);
|
||||
if (sfc->hadBackslash() ||
|
||||
(sfc->getClass() != nullptr && !sfc->getClassName().empty())) {
|
||||
return newQueryParamRef(sfc);
|
||||
}
|
||||
auto args = sfc->getParams();
|
||||
auto pc = args == nullptr ? 0 : args->getCount();
|
||||
bool isQueryCall = false;
|
||||
for (int i = 0; i < pc; i++) {
|
||||
auto arg = (*args)[i];
|
||||
assert(arg != nullptr);
|
||||
isQueryCall |= this->dependsOnQueryOnlyState(arg);
|
||||
}
|
||||
if (!isQueryCall) return newQueryParamRef(sfc);
|
||||
ExpressionListPtr newArgs(
|
||||
new ExpressionList(args->getScope(), args->getLocation())
|
||||
);
|
||||
bool noRewrites = true;
|
||||
for (int i = 0; i < pc; i++) {
|
||||
auto arg = (*args)[i];
|
||||
auto newArg = rewrite(arg);
|
||||
if (arg != newArg) noRewrites = false;
|
||||
newArgs->addElement(newArg);
|
||||
}
|
||||
if (noRewrites) return sfc;
|
||||
SimpleFunctionCallPtr result(
|
||||
new SimpleFunctionCall(sfc->getScope(), sfc->getLocation(),
|
||||
sfc->getName(), false, newArgs, ExpressionPtr())
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the expression tree rooted at e and returns true if
|
||||
* any node in the tree is a simple variable that references a
|
||||
* name in m_boundVars.
|
||||
*/
|
||||
bool CaptureExtractor::dependsOnQueryOnlyState(ExpressionPtr e) {
|
||||
assert(e != nullptr);
|
||||
if (e->getKindOf() == Expression::KindOfSimpleVariable) {
|
||||
auto sv = static_pointer_cast<SimpleVariable>(e);
|
||||
auto varName = sv->getName();
|
||||
for (auto &boundVar : m_boundVars) {
|
||||
if (varName == boundVar) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
auto numKids = e->getKidCount();
|
||||
for (int i = 0; i < numKids; i++) {
|
||||
auto ei = e->getNthExpr(i);
|
||||
if (ei == nullptr) return false; //Default param
|
||||
if (dependsOnQueryOnlyState(ei)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a simple variable refers to a name bound inside the query
|
||||
* then leave it alone. If not, rewrite it to be reference to
|
||||
* a query parameter.
|
||||
*/
|
||||
SimpleVariablePtr CaptureExtractor::rewriteSimpleVariable(
|
||||
SimpleVariablePtr sv) {
|
||||
assert(sv != nullptr);
|
||||
auto varName = sv->getName();
|
||||
for (auto &boundVar : m_boundVars) {
|
||||
if (varName == boundVar) return sv;
|
||||
}
|
||||
return newQueryParamRef(sv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query expressions introduce a local scope with names introduced
|
||||
* by some of the clauses of the query expression. This needs
|
||||
* special handling so that we can track variables local to the query.
|
||||
*/
|
||||
QueryExpressionPtr CaptureExtractor::rewriteQuery(QueryExpressionPtr qe) {
|
||||
assert(qe != nullptr);
|
||||
auto clauses = qe->getClauses();
|
||||
auto newClauses = rewriteExpressionList(clauses);
|
||||
if (clauses == newClauses) return qe;
|
||||
QueryExpressionPtr result(
|
||||
new QueryExpression(qe->getScope(), qe->getLocation(), newClauses)
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites any expression query clauses in this list of clauses, taking care
|
||||
* to track variables local to the query.
|
||||
*/
|
||||
ExpressionListPtr CaptureExtractor::rewriteExpressionList(ExpressionListPtr l) {
|
||||
int np = 0;
|
||||
int nc = l->getCount();
|
||||
ExpressionListPtr newList(
|
||||
new ExpressionList(l->getScope(), l->getLocation())
|
||||
);
|
||||
bool noRewrites = true;
|
||||
for (int i = 0; i < nc; i++) {
|
||||
auto e = (*l)[i];
|
||||
assert(e != nullptr);
|
||||
auto kind = e->getKindOf();
|
||||
switch (kind) {
|
||||
case Expression::KindOfIntoClause: {
|
||||
// The into expression is in the scope of the into clause
|
||||
SimpleQueryClausePtr qcp(static_pointer_cast<SimpleQueryClause>(e));
|
||||
m_boundVars.push_back(qcp->getIdentifier());
|
||||
np++;
|
||||
break;
|
||||
}
|
||||
case Expression::KindOfJoinClause: {
|
||||
JoinClausePtr jcp(static_pointer_cast<JoinClause>(e));
|
||||
m_boundVars.push_back(jcp->getVar());
|
||||
np++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
auto ne = rewrite(e);
|
||||
if (ne != e) noRewrites = false;
|
||||
newList->addElement(ne);
|
||||
// deal with clauses that introduce names for subsequent clauses
|
||||
switch (kind) {
|
||||
case Expression::KindOfFromClause:
|
||||
case Expression::KindOfLetClause: {
|
||||
SimpleQueryClausePtr qcp(static_pointer_cast<SimpleQueryClause>(e));
|
||||
m_boundVars.push_back(qcp->getIdentifier());
|
||||
np++;
|
||||
break;
|
||||
}
|
||||
case Expression::KindOfJoinClause: {
|
||||
JoinClausePtr jcp(static_pointer_cast<JoinClause>(e));
|
||||
auto groupId = jcp->getGroup();
|
||||
if (!groupId.empty()) {
|
||||
m_boundVars.push_back(groupId);
|
||||
np++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (np-- > 0) m_boundVars.pop_back();
|
||||
if (noRewrites) return l;
|
||||
return newList;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the expression of a simple query clause is query local, then
|
||||
* return the clause as is. Otherwise return a clone of the clause
|
||||
* with the expression rewritten to reference a query parameter.
|
||||
*/
|
||||
SimpleQueryClausePtr CaptureExtractor::rewriteSimpleClause(
|
||||
SimpleQueryClausePtr sc) {
|
||||
assert (sc != nullptr);
|
||||
auto expr = sc->getExpression();
|
||||
auto newExpr = rewrite(expr);
|
||||
if (expr == newExpr) return sc;
|
||||
auto rsc = static_pointer_cast<SimpleQueryClause>(sc->clone());
|
||||
rsc->setExpression(newExpr);
|
||||
return rsc;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the object expression is query local, that is, if it is a simple variable
|
||||
* referring to a name declared in a query clause, or itself a query local
|
||||
* object expression, then if keep this expression as is. If not, then
|
||||
* rewrite this expression into a query parameter reference.
|
||||
*/
|
||||
ExpressionPtr CaptureExtractor::rewriteObjectProperty(
|
||||
ObjectPropertyExpressionPtr ope) {
|
||||
assert(ope != nullptr);
|
||||
auto obj = ope->getObject();
|
||||
if (this->dependsOnQueryOnlyState(obj)) {
|
||||
auto prop = ope->getProperty();
|
||||
if (prop->getKindOf() == Expression::KindOfScalarExpression) {
|
||||
auto scalar = static_pointer_cast<ScalarExpression>(prop);
|
||||
const string &propName = scalar->getLiteralString();
|
||||
if (!propName.empty()) {
|
||||
return ope;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newQueryParamRef(ope);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the unary operation is not PHP specific, but something a query
|
||||
* processor can handle (+ - ! ~), then rewrite the operand to something
|
||||
* the query processor can evaluate (such as a query parameter reference)
|
||||
* and rewrite the entire expression to use the rewritten operand.
|
||||
* If the rewritten operand is the same as the original operand, just
|
||||
* return the expression as is.
|
||||
*/
|
||||
ExpressionPtr CaptureExtractor::rewriteUnary(UnaryOpExpressionPtr ue) {
|
||||
assert (ue != nullptr);
|
||||
if (!ue->getFront()) return nullptr;
|
||||
switch (ue->getOp()) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '!':
|
||||
case '~':
|
||||
break; // Could be something the query processor can handle
|
||||
default:
|
||||
return newQueryParamRef(ue);
|
||||
}
|
||||
auto expr = ue->getExpression();
|
||||
auto newExpr = rewrite(expr);
|
||||
if (expr == newExpr) return ue;
|
||||
UnaryOpExpressionPtr result(
|
||||
new UnaryOpExpression(ue->getScope(), ue->getLocation(),
|
||||
newExpr, ue->getOp(), true)
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the binary operation is not PHP specific, but something a query
|
||||
* processor can handle (+ - * and so on), then rewrite the operands to
|
||||
* something the query processor can evaluate (such as a query parameter
|
||||
* references) and rewrite the entire expression to use the rewritten operands.
|
||||
* If the rewritten operands are the same as the original operands, just
|
||||
* return the expression as is.
|
||||
*/
|
||||
ExpressionPtr CaptureExtractor::rewriteBinary(BinaryOpExpressionPtr be) {
|
||||
assert(be != nullptr);
|
||||
switch (be->getOp()) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '*':
|
||||
case '/':
|
||||
case '%':
|
||||
case '&':
|
||||
case '|':
|
||||
case '^':
|
||||
case T_IS_IDENTICAL:
|
||||
case T_IS_EQUAL:
|
||||
case '>':
|
||||
case '<':
|
||||
case T_IS_GREATER_OR_EQUAL:
|
||||
case T_IS_SMALLER_OR_EQUAL:
|
||||
case T_IS_NOT_IDENTICAL:
|
||||
case T_IS_NOT_EQUAL:
|
||||
case T_BOOLEAN_OR:
|
||||
case T_BOOLEAN_AND:
|
||||
case T_LOGICAL_OR:
|
||||
case T_LOGICAL_AND:
|
||||
case '.':
|
||||
break; // Could be something the query processor can handle
|
||||
|
||||
default:
|
||||
return newQueryParamRef(be);
|
||||
}
|
||||
auto expr1 = be->getExp1();
|
||||
auto expr2 = be->getExp2();
|
||||
auto newExpr1 = rewrite(expr1);
|
||||
auto newExpr2 = rewrite(expr2);
|
||||
if (expr1 == newExpr1 && expr2 == newExpr2) return be;
|
||||
BinaryOpExpressionPtr result(
|
||||
new BinaryOpExpression(be->getScope(), be->getLocation(),
|
||||
newExpr1, newExpr2, be->getOp())
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_CAPTURE_EXTRACTOR_H_
|
||||
#define incl_HPHP_CAPTURE_EXTRACTOR_H_
|
||||
|
||||
#include "hphp/compiler/expression/binary_op_expression.h"
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/expression/object_property_expression.h"
|
||||
#include "hphp/compiler/expression/query_expression.h"
|
||||
#include "hphp/compiler/expression/simple_function_call.h"
|
||||
#include "hphp/compiler/expression/simple_query_clause.h"
|
||||
#include "hphp/compiler/expression/simple_variable.h"
|
||||
#include "hphp/compiler/expression/unary_op_expression.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** A rewriter for query expressions that capture variables that lie
|
||||
* outside of the scope of the query expression. Subexpressions that
|
||||
* contain such references are turned into references to query parameter
|
||||
* variables. The original expressions are collected into the list
|
||||
* returned by getCapturedEpressions. Their runtime values are obtained
|
||||
* before the query is evaluated and are passed as arguments to the query
|
||||
* processor.
|
||||
*/
|
||||
class CaptureExtractor {
|
||||
public:
|
||||
|
||||
ExpressionPtr rewrite(ExpressionPtr ep);
|
||||
|
||||
std::vector<ExpressionPtr> getCapturedExpressions() {
|
||||
return m_capturedExpressions;
|
||||
}
|
||||
|
||||
private:
|
||||
bool dependsOnQueryOnlyState(ExpressionPtr e);
|
||||
SimpleVariablePtr newQueryParamRef(ExpressionPtr ae);
|
||||
ExpressionPtr rewriteBinary(BinaryOpExpressionPtr be);
|
||||
ExpressionPtr rewriteCall(SimpleFunctionCallPtr sfc);
|
||||
ExpressionListPtr rewriteExpressionList(ExpressionListPtr l);
|
||||
ExpressionPtr rewriteObjectProperty(ObjectPropertyExpressionPtr ope);
|
||||
QueryExpressionPtr rewriteQuery(QueryExpressionPtr qe);
|
||||
SimpleQueryClausePtr rewriteSimpleClause(SimpleQueryClausePtr sc);
|
||||
SimpleVariablePtr rewriteSimpleVariable(SimpleVariablePtr sv);
|
||||
ExpressionPtr rewriteUnary(UnaryOpExpressionPtr ue);
|
||||
|
||||
std::vector<ExpressionPtr> m_capturedExpressions;
|
||||
std::vector<std::string> m_boundVars;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // incl_HPHP_CAPTURE_EXTRACTOR_H_
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "hphp/compiler/statement/class_variable.h"
|
||||
#include "hphp/compiler/statement/class_constant.h"
|
||||
#include "hphp/compiler/statement/use_trait_statement.h"
|
||||
#include "hphp/compiler/statement/trait_require_statement.h"
|
||||
#include "hphp/compiler/statement/trait_prec_statement.h"
|
||||
#include "hphp/compiler/statement/trait_alias_statement.h"
|
||||
#include "hphp/runtime/base/zend-string.h"
|
||||
@@ -474,17 +473,6 @@ void ClassScope::addImportTraitMethod(const TraitMethod &traitMethod,
|
||||
m_importMethToTraitMap[methName].push_back(traitMethod);
|
||||
}
|
||||
|
||||
void ClassScope::addTraitRequirement(const string &requiredName,
|
||||
bool isExtends) {
|
||||
assert(isTrait());
|
||||
|
||||
if (isExtends) {
|
||||
m_traitRequiredExtends.insert(requiredName);
|
||||
} else {
|
||||
m_traitRequiredImplements.insert(requiredName);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClassScope::setImportTraitMethodModifiers(const string &methName,
|
||||
ClassScopePtr traitCls,
|
||||
@@ -545,7 +533,6 @@ ClassScope::findTraitMethod(AnalysisResultPtr ar,
|
||||
|
||||
void ClassScope::findTraitMethodsToImport(AnalysisResultPtr ar,
|
||||
ClassScopePtr trait) {
|
||||
assert(Option::WholeProgram);
|
||||
ClassStatementPtr tStmt =
|
||||
dynamic_pointer_cast<ClassStatement>(trait->getStmt());
|
||||
StatementListPtr tStmts = tStmt->getStmts();
|
||||
@@ -562,45 +549,7 @@ void ClassScope::findTraitMethodsToImport(AnalysisResultPtr ar,
|
||||
}
|
||||
}
|
||||
|
||||
void ClassScope::importTraitRequirements(AnalysisResultPtr ar,
|
||||
ClassScopePtr trait) {
|
||||
if (isTrait()) {
|
||||
for (auto const& req : trait->getTraitRequiredExtends()) {
|
||||
addTraitRequirement(req, true);
|
||||
}
|
||||
for (auto const& req : trait->getTraitRequiredImplements()) {
|
||||
addTraitRequirement(req, false);
|
||||
}
|
||||
} else {
|
||||
for (auto const& req : trait->getTraitRequiredExtends()) {
|
||||
if (!derivesFrom(ar, req, true, false)) {
|
||||
getStmt()->analysisTimeFatal(
|
||||
Compiler::InvalidDerivation,
|
||||
Strings::TRAIT_REQ_EXTENDS,
|
||||
m_originalName.c_str(),
|
||||
req.c_str(),
|
||||
trait->getOriginalName().c_str(),
|
||||
"use"
|
||||
);
|
||||
}
|
||||
}
|
||||
for (auto const& req : trait->getTraitRequiredImplements()) {
|
||||
if (!derivesFrom(ar, req, true, false)) {
|
||||
getStmt()->analysisTimeFatal(
|
||||
Compiler::InvalidDerivation,
|
||||
Strings::TRAIT_REQ_IMPLEMENTS,
|
||||
m_originalName.c_str(),
|
||||
req.c_str(),
|
||||
trait->getOriginalName().c_str(),
|
||||
"use"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassScope::applyTraitPrecRule(TraitPrecStatementPtr stmt) {
|
||||
assert(Option::WholeProgram);
|
||||
const string methodName = Util::toLower(stmt->getMethodName());
|
||||
const string selectedTraitName = Util::toLower(stmt->getTraitName());
|
||||
std::set<string> otherTraitNames;
|
||||
@@ -631,20 +580,12 @@ void ClassScope::applyTraitPrecRule(TraitPrecStatementPtr stmt) {
|
||||
|
||||
// Report error if didn't find the selected trait
|
||||
if (!foundSelectedTrait) {
|
||||
stmt->analysisTimeFatal(
|
||||
Compiler::UnknownTrait,
|
||||
Strings::TRAITS_UNKNOWN_TRAIT,
|
||||
selectedTraitName.c_str()
|
||||
);
|
||||
Compiler::Error(Compiler::UnknownTrait, stmt);
|
||||
}
|
||||
|
||||
// Sanity checking: otherTraitNames should be empty now
|
||||
if (otherTraitNames.size()) {
|
||||
stmt->analysisTimeFatal(
|
||||
Compiler::UnknownTrait,
|
||||
Strings::TRAITS_UNKNOWN_TRAIT,
|
||||
selectedTraitName.c_str()
|
||||
);
|
||||
Compiler::Error(Compiler::UnknownTrait, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,7 +596,6 @@ bool ClassScope::hasMethod(const string &methodName) const {
|
||||
ClassScopePtr
|
||||
ClassScope::findSingleTraitWithMethod(AnalysisResultPtr ar,
|
||||
const string &methodName) const {
|
||||
assert(Option::WholeProgram);
|
||||
ClassScopePtr trait = ClassScopePtr();
|
||||
|
||||
for (unsigned i = 0; i < m_usedTraitNames.size(); i++) {
|
||||
@@ -673,7 +613,6 @@ ClassScope::findSingleTraitWithMethod(AnalysisResultPtr ar,
|
||||
}
|
||||
|
||||
void ClassScope::addTraitAlias(TraitAliasStatementPtr aliasStmt) {
|
||||
assert(Option::WholeProgram);
|
||||
const string &traitName = aliasStmt->getTraitName();
|
||||
const string &origMethName = aliasStmt->getMethodName();
|
||||
const string &newMethName = aliasStmt->getNewMethodName();
|
||||
@@ -684,7 +623,6 @@ void ClassScope::addTraitAlias(TraitAliasStatementPtr aliasStmt) {
|
||||
|
||||
void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
|
||||
TraitAliasStatementPtr stmt) {
|
||||
assert(Option::WholeProgram);
|
||||
const string traitName = Util::toLower(stmt->getTraitName());
|
||||
const string origMethName = Util::toLower(stmt->getMethodName());
|
||||
const string newMethName = Util::toLower(stmt->getNewMethodName());
|
||||
@@ -697,11 +635,8 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
|
||||
traitCls = ar->findClass(traitName);
|
||||
}
|
||||
if (!traitCls || !(traitCls->isTrait())) {
|
||||
stmt->analysisTimeFatal(
|
||||
Compiler::UnknownTrait,
|
||||
Strings::TRAITS_UNKNOWN_TRAIT,
|
||||
traitName.empty() ? origMethName.c_str() : traitName.c_str()
|
||||
);
|
||||
Compiler::Error(Compiler::UnknownTrait, stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep record of alias rule
|
||||
@@ -712,10 +647,8 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
|
||||
MethodStatementPtr methStmt = findTraitMethod(ar, traitCls, origMethName,
|
||||
visitedTraits);
|
||||
if (!methStmt) {
|
||||
stmt->analysisTimeFatal(
|
||||
Compiler::UnknownTraitMethod,
|
||||
Strings::TRAITS_UNKNOWN_TRAIT_METHOD, origMethName.c_str()
|
||||
);
|
||||
Compiler::Error(Compiler::UnknownTraitMethod, stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (origMethName == newMethName) {
|
||||
@@ -730,7 +663,6 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
|
||||
}
|
||||
|
||||
void ClassScope::applyTraitRules(AnalysisResultPtr ar) {
|
||||
assert(Option::WholeProgram);
|
||||
ClassStatementPtr classStmt = dynamic_pointer_cast<ClassStatement>(getStmt());
|
||||
assert(classStmt);
|
||||
StatementListPtr stmts = classStmt->getStmts();
|
||||
@@ -763,7 +695,6 @@ void ClassScope::applyTraitRules(AnalysisResultPtr ar) {
|
||||
// 1) implemented by other traits
|
||||
// 2) duplicate
|
||||
void ClassScope::removeSpareTraitAbstractMethods(AnalysisResultPtr ar) {
|
||||
assert(Option::WholeProgram);
|
||||
for (MethodToTraitListMap::iterator iter = m_importMethToTraitMap.begin();
|
||||
iter != m_importMethToTraitMap.end(); iter++) {
|
||||
|
||||
@@ -801,17 +732,9 @@ void ClassScope::removeSpareTraitAbstractMethods(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
|
||||
// Trait flattening is supposed to happen only when we have awareness of
|
||||
// the whole program.
|
||||
assert(Option::WholeProgram);
|
||||
|
||||
if (m_traitStatus == FLATTENED) return;
|
||||
if (m_traitStatus == BEING_FLATTENED) {
|
||||
getStmt()->analysisTimeFatal(
|
||||
Compiler::CyclicDependentTraits,
|
||||
"Cyclic dependency between traits involving %s",
|
||||
getOriginalName().c_str()
|
||||
);
|
||||
Compiler::Error(Compiler::CyclicDependentTraits, getStmt());
|
||||
return;
|
||||
}
|
||||
if (m_usedTraitNames.size() == 0) {
|
||||
@@ -828,53 +751,18 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
if (isTrait()) {
|
||||
for (auto const& req : getTraitRequiredExtends()) {
|
||||
ClassScopePtr rCls = ar->findClass(req);
|
||||
if (!rCls || rCls->isFinal() || rCls->isInterface()) {
|
||||
getStmt()->analysisTimeFatal(
|
||||
Compiler::InvalidDerivation,
|
||||
Strings::TRAIT_BAD_REQ_EXTENDS,
|
||||
m_originalName.c_str(),
|
||||
req.c_str(),
|
||||
req.c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
for (auto const& req : getTraitRequiredImplements()) {
|
||||
ClassScopePtr rCls = ar->findClass(req);
|
||||
if (!rCls || !(rCls->isInterface())) {
|
||||
getStmt()->analysisTimeFatal(
|
||||
Compiler::InvalidDerivation,
|
||||
Strings::TRAIT_BAD_REQ_IMPLEMENTS,
|
||||
m_originalName.c_str(),
|
||||
req.c_str(),
|
||||
req.c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find trait methods to be imported
|
||||
for (unsigned i = 0; i < m_usedTraitNames.size(); i++) {
|
||||
ClassScopePtr tCls = ar->findClass(m_usedTraitNames[i]);
|
||||
if (!tCls || !(tCls->isTrait())) {
|
||||
setAttribute(UsesUnknownTrait); // XXX: is this useful ... for anything?
|
||||
getStmt()->analysisTimeFatal(
|
||||
Compiler::UnknownTrait,
|
||||
Strings::TRAITS_UNKNOWN_TRAIT,
|
||||
m_usedTraitNames[i].c_str()
|
||||
);
|
||||
setAttribute(UsesUnknownTrait);
|
||||
Compiler::Error(Compiler::UnknownTrait, getStmt());
|
||||
continue;
|
||||
}
|
||||
// First, make sure the used trait is flattened
|
||||
tCls->importUsedTraits(ar);
|
||||
|
||||
findTraitMethodsToImport(ar, tCls);
|
||||
|
||||
// Import any interfaces implemented
|
||||
tCls->getInterfaces(ar, m_bases, false);
|
||||
|
||||
importTraitRequirements(ar, tCls);
|
||||
}
|
||||
|
||||
// Apply rules
|
||||
@@ -894,7 +782,7 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
std::map<string, MethodStatementPtr> importedTraitMethods;
|
||||
std::vector<std::pair<string,const TraitMethod*>> importedTraitsWithOrigName;
|
||||
std::vector<std::pair<string,const TraitMethod*> > importedTraitsWithOrigName;
|
||||
|
||||
// Actually import the methods
|
||||
for (MethodToTraitListMap::const_iterator
|
||||
@@ -908,11 +796,7 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
|
||||
}
|
||||
// Consistency checking: each name must only refer to one imported method
|
||||
if (iter->second.size() > 1) {
|
||||
getStmt()->analysisTimeFatal(
|
||||
Compiler::MethodInMultipleTraits,
|
||||
Strings::METHOD_IN_MULTIPLE_TRAITS,
|
||||
iter->first.c_str()
|
||||
);
|
||||
Compiler::Error(Compiler::MethodInMultipleTraits, getStmt());
|
||||
} else {
|
||||
TraitMethodList::const_iterator traitMethIter = iter->second.begin();
|
||||
if ((traitMethIter->m_modifiers ? traitMethIter->m_modifiers :
|
||||
@@ -923,6 +807,13 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (traitMethIter->m_modifiers &&
|
||||
traitMethIter->m_modifiers->isStatic()) {
|
||||
Compiler::Error(Compiler::InvalidAccessModifier,
|
||||
traitMethIter->m_modifiers);
|
||||
continue;
|
||||
}
|
||||
|
||||
string sourceName = traitMethIter->m_ruleStmt ?
|
||||
Util::toLower(((TraitAliasStatement*)traitMethIter->m_ruleStmt.get())->
|
||||
getMethodName()) : iter->first;
|
||||
@@ -1243,7 +1134,8 @@ void ClassScope::getInterfaces(AnalysisResultConstPtr ar,
|
||||
if (cls && cls->isRedeclaring()) {
|
||||
cls = self->findExactClass(cls);
|
||||
}
|
||||
names.push_back(cls ? cls->getDocName() : *it);
|
||||
if (cls) names.push_back(cls->getDocName());
|
||||
else names.push_back(*it);
|
||||
if (cls && recursive) {
|
||||
cls->getInterfaces(ar, names, true);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,8 @@
|
||||
#include "hphp/compiler/statement/trait_prec_statement.h"
|
||||
#include "hphp/compiler/statement/trait_alias_statement.h"
|
||||
#include "hphp/compiler/expression/user_attribute.h"
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/functional.h"
|
||||
#include "hphp/util/hash-map-typedefs.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/util/case-insensitive.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
|
||||
namespace HPHP {
|
||||
@@ -174,7 +173,6 @@ public:
|
||||
* Get/set attributes.
|
||||
*/
|
||||
void setSystem();
|
||||
bool isSystem() const { return m_attribute & System; }
|
||||
void setAttribute(Attribute attr) { m_attribute |= attr;}
|
||||
void clearAttribute(Attribute attr) { m_attribute &= ~attr;}
|
||||
bool getAttribute(Attribute attr) const {
|
||||
@@ -303,29 +301,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const boost::container::flat_set<std::string>& getTraitRequiredExtends()
|
||||
const {
|
||||
return m_traitRequiredExtends;
|
||||
}
|
||||
|
||||
const boost::container::flat_set<std::string>& getTraitRequiredImplements()
|
||||
const {
|
||||
return m_traitRequiredImplements;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &getUsedTraitNames() const {
|
||||
return m_usedTraitNames;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, std::string>>& getTraitAliases()
|
||||
const std::vector<std::pair<std::string, std::string> > &getTraitAliases()
|
||||
const {
|
||||
return m_traitAliases;
|
||||
}
|
||||
|
||||
void addTraitAlias(TraitAliasStatementPtr aliasStmt);
|
||||
|
||||
void addTraitRequirement(const std::string &requiredName, bool isExtends);
|
||||
|
||||
void importUsedTraits(AnalysisResultPtr ar);
|
||||
|
||||
/**
|
||||
@@ -383,16 +369,6 @@ public:
|
||||
bool canSkipCreateMethod(AnalysisResultConstPtr ar) const;
|
||||
bool checkHasPropTable(AnalysisResultConstPtr ar);
|
||||
|
||||
const StringData* getFatalMessage() const {
|
||||
return m_fatal_error_msg;
|
||||
}
|
||||
|
||||
void setFatal(const AnalysisTimeFatalException& fatal) {
|
||||
assert(m_fatal_error_msg == nullptr);
|
||||
m_fatal_error_msg = makeStaticString(fatal.getMessage());
|
||||
assert(m_fatal_error_msg != nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
// need to maintain declaration order for ClassInfo map
|
||||
FunctionScopePtrVec m_functionsVec;
|
||||
@@ -402,8 +378,6 @@ private:
|
||||
UserAttributeMap m_userAttributes;
|
||||
|
||||
std::vector<std::string> m_usedTraitNames;
|
||||
boost::container::flat_set<std::string> m_traitRequiredExtends;
|
||||
boost::container::flat_set<std::string> m_traitRequiredImplements;
|
||||
// m_traitAliases is used to support ReflectionClass::getTraitAliases
|
||||
std::vector<std::pair<std::string, std::string> > m_traitAliases;
|
||||
|
||||
@@ -453,9 +427,6 @@ private:
|
||||
// bases 32 through n are all known.
|
||||
unsigned m_knownBases;
|
||||
|
||||
// holds the fact that accessing this class declaration is a fatal error
|
||||
const StringData* m_fatal_error_msg = nullptr;
|
||||
|
||||
void addImportTraitMethod(const TraitMethod &traitMethod,
|
||||
const std::string &methName);
|
||||
void informClosuresAboutScopeClone(ConstructPtr root,
|
||||
@@ -476,8 +447,6 @@ private:
|
||||
|
||||
void findTraitMethodsToImport(AnalysisResultPtr ar, ClassScopePtr trait);
|
||||
|
||||
void importTraitRequirements(AnalysisResultPtr ar, ClassScopePtr trait);
|
||||
|
||||
MethodStatementPtr findTraitMethod(AnalysisResultPtr ar,
|
||||
ClassScopePtr trait,
|
||||
const std::string &methodName,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define incl_HPHP_COMPILER_ERROR_H_
|
||||
|
||||
#include "hphp/compiler/analysis/type.h"
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/json.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -245,7 +245,6 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
|
||||
Statement::KindOf stype = s->getKindOf();
|
||||
switch (stype) {
|
||||
case Statement::KindOfUseTraitStatement:
|
||||
case Statement::KindOfTraitRequireStatement:
|
||||
case Statement::KindOfTraitPrecStatement:
|
||||
case Statement::KindOfTraitAliasStatement:
|
||||
not_reached();
|
||||
|
||||
@@ -37,6 +37,7 @@ CODE_ERROR_ENTRY(InvalidAttribute)
|
||||
CODE_ERROR_ENTRY(UnknownTrait)
|
||||
CODE_ERROR_ENTRY(MethodInMultipleTraits)
|
||||
CODE_ERROR_ENTRY(UnknownTraitMethod)
|
||||
CODE_ERROR_ENTRY(InvalidAccessModifier)
|
||||
CODE_ERROR_ENTRY(CyclicDependentTraits)
|
||||
CODE_ERROR_ENTRY(InvalidTraitStatement)
|
||||
CODE_ERROR_ENTRY(RedeclaredTrait)
|
||||
@@ -44,4 +45,3 @@ CODE_ERROR_ENTRY(InvalidInstantiation)
|
||||
CODE_ERROR_ENTRY(InvalidYield)
|
||||
CODE_ERROR_ENTRY(InvalidAwait)
|
||||
CODE_ERROR_ENTRY(BadDefaultValueType)
|
||||
CODE_ERROR_ENTRY(InvalidMethodDefinition)
|
||||
|
||||
+617
-1727
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -20,7 +20,6 @@
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/statement/statement.h"
|
||||
#include "hphp/compiler/statement/use_trait_statement.h"
|
||||
#include "hphp/compiler/statement/trait_require_statement.h"
|
||||
#include "hphp/compiler/statement/trait_prec_statement.h"
|
||||
#include "hphp/compiler/statement/trait_alias_statement.h"
|
||||
#include "hphp/compiler/statement/typedef_statement.h"
|
||||
@@ -29,9 +28,6 @@
|
||||
#include "hphp/runtime/vm/unit.h"
|
||||
#include "hphp/util/hash.h"
|
||||
|
||||
#include <deque>
|
||||
#include <utility>
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
DECLARE_BOOST_TYPES(ClosureExpression);
|
||||
@@ -99,7 +95,6 @@ public:
|
||||
IterKind kind;
|
||||
Id id;
|
||||
};
|
||||
|
||||
#define O(name, imm, pop, push, flags) \
|
||||
void name(imm);
|
||||
#define NA
|
||||
@@ -111,7 +106,7 @@ public:
|
||||
typ1 a1, typ2 a2, typ3 a3
|
||||
#define FOUR(typ1, typ2, typ3, typ4) \
|
||||
typ1 a1, typ2 a2, typ3 a3, typ4 a4
|
||||
#define MA std::vector<unsigned char>
|
||||
#define MA std::vector<uchar>
|
||||
#define BLA std::vector<Label*>&
|
||||
#define SLA std::vector<StrOff>&
|
||||
#define ILA std::vector<IterPair>&
|
||||
@@ -123,8 +118,7 @@ public:
|
||||
#define SA const StringData*
|
||||
#define AA ArrayData*
|
||||
#define BA Label&
|
||||
#define OA(type) type
|
||||
#define VSA std::vector<std::string>&
|
||||
#define OA unsigned char
|
||||
OPCODES
|
||||
#undef O
|
||||
#undef NA
|
||||
@@ -145,7 +139,6 @@ public:
|
||||
#undef AA
|
||||
#undef BA
|
||||
#undef OA
|
||||
#undef VSA
|
||||
private:
|
||||
ConstructPtr m_node;
|
||||
UnitEmitter& m_ue;
|
||||
@@ -323,137 +316,14 @@ public:
|
||||
|
||||
class Funclet {
|
||||
public:
|
||||
explicit Funclet(Thunklet* body)
|
||||
: m_body(body) {
|
||||
}
|
||||
Funclet(Thunklet* body, Label* entry) : m_body(body), m_entry(entry) {}
|
||||
Thunklet* m_body;
|
||||
Label m_entry;
|
||||
};
|
||||
|
||||
DECLARE_BOOST_TYPES(ControlTarget);
|
||||
/*
|
||||
* The structure represents a code path that potentially requires
|
||||
* running finally blocks. A code path has an assigned state ID that
|
||||
* is used inside switch statements emitted at the end of finally
|
||||
* blocks. It also has an optional label (the destination to jump
|
||||
* to after all the required finally blocks are run).
|
||||
*/
|
||||
struct ControlTarget {
|
||||
static const int k_unsetState;
|
||||
explicit ControlTarget(EmitterVisitor* router);
|
||||
~ControlTarget();
|
||||
// Manage state ID reuse.
|
||||
bool isRegistered();
|
||||
EmitterVisitor* m_visitor;
|
||||
// The target to jump to once all the necessary finally blocks are run.
|
||||
Label m_label;
|
||||
// The state ID that identifies this control target inside finally
|
||||
// epilogues. This ID assigned to the "state" unnamed local variable.
|
||||
int m_state;
|
||||
};
|
||||
|
||||
struct ControlTargetInfo {
|
||||
ControlTargetInfo() : used(false) {}
|
||||
ControlTargetInfo(ControlTargetPtr t, bool b) : target(t), used(b) {}
|
||||
ControlTargetPtr target;
|
||||
bool used;
|
||||
};
|
||||
|
||||
DECLARE_BOOST_TYPES(Region);
|
||||
/*
|
||||
* Region represents a single level of the unified stack
|
||||
* of constructs that are meaningful from the point of view of finally
|
||||
* implementation. The levels are used to keep track of the information
|
||||
* such as the control targets that can be taken inside a block.
|
||||
*/
|
||||
class Region {
|
||||
public:
|
||||
enum Kind {
|
||||
// Top-level (global) context.
|
||||
Global,
|
||||
// Function body / method body entry.
|
||||
FuncBody,
|
||||
// Entry for finally fault funclets emitted after the body of
|
||||
// a function
|
||||
FaultFunclet,
|
||||
// Region by a finally clause
|
||||
TryFinally,
|
||||
// Finally block entry (begins after catches ends after finally)
|
||||
Finally,
|
||||
// Loop or switch statement.
|
||||
LoopOrSwitch,
|
||||
};
|
||||
|
||||
typedef Emitter::IterPair IterPair;
|
||||
typedef std::vector<IterPair> IterVec;
|
||||
|
||||
Region(Region::Kind kind, RegionPtr parent);
|
||||
|
||||
// Helper for establishing the maximal depth of break / continue
|
||||
// control targets that are allocated.
|
||||
int getBreakContinueDepth();
|
||||
|
||||
// Returns the maximal break / continue depth admissable (aka the
|
||||
// number of nested loops).
|
||||
int getMaxBreakContinueDepth();
|
||||
|
||||
int getMaxState();
|
||||
|
||||
// The number of cases to be emitted. This is a helper used in
|
||||
// establishing whether one of the optimized cases can be used.
|
||||
int getCaseCount();
|
||||
|
||||
bool isForeach() { return m_iterId != -1; }
|
||||
bool isTryFinally() { return m_kind == Region::Kind::TryFinally; }
|
||||
bool isFinally() { return m_kind == Region::Kind::Finally; }
|
||||
|
||||
bool isBreakUsed(int i) {
|
||||
auto it = m_breakTargets.find(i);
|
||||
if (it == m_breakTargets.end()) return false;
|
||||
return it->second.used;
|
||||
}
|
||||
|
||||
bool isContinueUsed(int i) {
|
||||
auto it = m_continueTargets.find(i);
|
||||
if (it == m_continueTargets.end()) return false;
|
||||
return it->second.used;
|
||||
}
|
||||
|
||||
Region::Kind m_kind;
|
||||
// Only used for loop / break kind of entries.
|
||||
Id m_iterId;
|
||||
IterKind m_iterKind;
|
||||
// Because of a bug in code emission, functions sometimes have
|
||||
// inconsistent return flavors. Therefore instead of a single
|
||||
// return control target, there need to be one return control
|
||||
// target per flavor used. Once the bug is removed, this code
|
||||
// can be simplified.
|
||||
std::map<char, ControlTargetInfo> m_returnTargets;
|
||||
// Break and continue control targets identified by their depth.
|
||||
std::map<int, ControlTargetInfo> m_breakTargets;
|
||||
std::map<int, ControlTargetInfo> m_continueTargets;
|
||||
// Goto control targets. Each goto control target is identified
|
||||
// by the name of the destination label.
|
||||
std::map<StringData*, ControlTargetInfo, string_data_lt> m_gotoTargets;
|
||||
// A set of goto labels occurrning inside the statement represented
|
||||
// by this entry. This value is used for establishing whether
|
||||
// a finally block needs to be executed when performing gotos.
|
||||
std::set<StringData*, string_data_lt> m_gotoLabels;
|
||||
// The label denoting the beginning of a finally block inside the
|
||||
// current try. Only used when the entry kind is a try statement.
|
||||
Label m_finallyLabel;
|
||||
// The parent entry.
|
||||
RegionPtr m_parent;
|
||||
Label* m_entry;
|
||||
};
|
||||
|
||||
class EmitterVisitor {
|
||||
friend class UnsetUnnamedLocalThunklet;
|
||||
friend class FuncFinisher;
|
||||
public:
|
||||
typedef std::vector<int> IndexChain;
|
||||
typedef Emitter::IterPair IterPair;
|
||||
typedef std::vector<IterPair> IterVec;
|
||||
|
||||
explicit EmitterVisitor(UnitEmitter& ue);
|
||||
~EmitterVisitor();
|
||||
|
||||
@@ -462,10 +332,9 @@ public:
|
||||
void visitKids(ConstructPtr c);
|
||||
void visit(FileScopePtr file);
|
||||
void assignLocalVariableIds(FunctionScopePtr fs);
|
||||
void assignFinallyVariableIds();
|
||||
void fixReturnType(Emitter& e, FunctionCallPtr fn,
|
||||
Func* builtinFunc = nullptr);
|
||||
|
||||
typedef std::vector<int> IndexChain;
|
||||
void visitListAssignmentLHS(Emitter& e, ExpressionPtr exp,
|
||||
IndexChain& indexChain,
|
||||
std::vector<IndexChain*>& chainList);
|
||||
@@ -480,7 +349,7 @@ public:
|
||||
bool evalStackIsUnknown() { return m_evalStackIsUnknown; }
|
||||
void popEvalStack(char symFlavor, int arg = -1, int pos = -1);
|
||||
void popSymbolicLocal(Op opcode, int arg = -1, int pos = -1);
|
||||
void popEvalStackMMany();
|
||||
void popEvalStackLMany();
|
||||
void popEvalStackMany(int len, char symFlavor);
|
||||
void popEvalStackCVMany(int len);
|
||||
void pushEvalStack(char symFlavor);
|
||||
@@ -501,15 +370,6 @@ public:
|
||||
|| isJumpTarget(m_ue.bcPos())
|
||||
|| (instrFlags(getPrevOpcode()) & TF) == 0);
|
||||
}
|
||||
FuncEmitter* getFuncEmitter() { return m_curFunc; }
|
||||
Id getStateLocal() {
|
||||
assert(m_stateLocal >= 0);
|
||||
return m_stateLocal;
|
||||
}
|
||||
Id getRetLocal() {
|
||||
assert(m_retLocal >= 0);
|
||||
return m_retLocal;
|
||||
}
|
||||
|
||||
class IncludeTimeFatalException : public Exception {
|
||||
public:
|
||||
@@ -579,11 +439,36 @@ private:
|
||||
FuncEmitter* m_fe;
|
||||
};
|
||||
|
||||
class CatchRegion {
|
||||
class ControlTargets {
|
||||
public:
|
||||
CatchRegion(Offset start, Offset end) : m_start(start),
|
||||
ControlTargets(Id itId, bool itRef, Label& brkTarg, Label& cntTarg)
|
||||
: m_itId(itId), m_itRef(itRef), m_brkTarg(brkTarg), m_cntTarg(cntTarg)
|
||||
{}
|
||||
Id m_itId;
|
||||
bool m_itRef;
|
||||
Label& m_brkTarg; // Jump here for "break;" (after doing IterFree)
|
||||
Label& m_cntTarg; // Jump here for "continue;"
|
||||
};
|
||||
|
||||
class ControlTargetPusher {
|
||||
public:
|
||||
ControlTargetPusher(EmitterVisitor* e, Id itId, bool itRef, Label& brkTarg,
|
||||
Label& cntTarg) : m_e(e) {
|
||||
e->m_controlTargets.push_front(ControlTargets(itId, itRef, brkTarg,
|
||||
cntTarg));
|
||||
}
|
||||
~ControlTargetPusher() {
|
||||
m_e->m_controlTargets.pop_front();
|
||||
}
|
||||
private:
|
||||
EmitterVisitor* m_e;
|
||||
};
|
||||
|
||||
class ExnHandlerRegion {
|
||||
public:
|
||||
ExnHandlerRegion(Offset start, Offset end) : m_start(start),
|
||||
m_end(end) {}
|
||||
~CatchRegion() {
|
||||
~ExnHandlerRegion() {
|
||||
for (std::vector<std::pair<StringData*, Label*> >::const_iterator it =
|
||||
m_catchLabels.begin(); it != m_catchLabels.end(); it++) {
|
||||
delete it->second;
|
||||
@@ -597,22 +482,18 @@ private:
|
||||
|
||||
class FaultRegion {
|
||||
public:
|
||||
FaultRegion(Offset start,
|
||||
Offset end,
|
||||
Label* func,
|
||||
Id iterId,
|
||||
IterKind kind)
|
||||
FaultRegion(Offset start, Offset end, Id iterId, IterKind kind)
|
||||
: m_start(start)
|
||||
, m_end(end)
|
||||
, m_func(func)
|
||||
, m_iterId(iterId)
|
||||
, m_iterKind(kind) {}
|
||||
, m_iterKind(kind)
|
||||
{}
|
||||
|
||||
Offset m_start;
|
||||
Offset m_end;
|
||||
Label* m_func;
|
||||
Id m_iterId;
|
||||
IterKind m_iterKind;
|
||||
Label m_func; // note: a pointer to this is handed out to the Funclet
|
||||
};
|
||||
|
||||
class FPIRegion {
|
||||
@@ -660,33 +541,23 @@ private:
|
||||
typedef tbb::concurrent_hash_map<const StringData*, int,
|
||||
StringDataHashCompare> EmittedClosures;
|
||||
static EmittedClosures s_emittedClosures;
|
||||
std::deque<Funclet*> m_funclets;
|
||||
std::map<StatementPtr, Funclet*> m_memoizedFunclets;
|
||||
std::deque<CatchRegion*> m_catchRegions;
|
||||
std::deque<ControlTargets> m_controlTargets;
|
||||
std::deque<Funclet> m_funclets;
|
||||
std::deque<ExnHandlerRegion*> m_exnHandlers;
|
||||
std::deque<FaultRegion*> m_faultRegions;
|
||||
std::deque<FPIRegion*> m_fpiRegions;
|
||||
std::vector<Array> m_staticArrays;
|
||||
std::set<std::string,stdltistr> m_hoistables;
|
||||
LocationPtr m_tempLoc;
|
||||
std::map<StringData*, Label, string_data_lt> m_gotoLabels;
|
||||
std::vector<Label> m_yieldLabels;
|
||||
|
||||
// The stack of all Regions that this EmitterVisitor is currently inside
|
||||
std::vector<RegionPtr> m_regions;
|
||||
// The state IDs currently allocated for the "finally router" logic.
|
||||
// See FIXME above the registerControlTarget() method.
|
||||
std::set<int> m_states;
|
||||
// Unnamed local variables used by the "finally router" logic
|
||||
Id m_stateLocal;
|
||||
Id m_retLocal;
|
||||
|
||||
MetaInfoBuilder m_metaInfo;
|
||||
|
||||
public:
|
||||
bool checkIfStackEmpty(const char* forInstruction) const;
|
||||
void unexpectedStackSym(char sym, const char* where) const;
|
||||
|
||||
int scanStackForLocation(int iLast);
|
||||
void buildVectorImm(std::vector<unsigned char>& vectorImm,
|
||||
void buildVectorImm(std::vector<uchar>& vectorImm,
|
||||
int iFirst, int iLast, bool allowW,
|
||||
Emitter& e);
|
||||
enum class PassByRefKind {
|
||||
@@ -698,20 +569,26 @@ public:
|
||||
void emitAGet(Emitter& e);
|
||||
void emitCGetL2(Emitter& e);
|
||||
void emitCGetL3(Emitter& e);
|
||||
void emitPushL(Emitter& e);
|
||||
void emitCGet(Emitter& e);
|
||||
void emitVGet(Emitter& e);
|
||||
void emitIsset(Emitter& e);
|
||||
void emitIsType(Emitter& e, IsTypeOp op);
|
||||
void emitIsNull(Emitter& e);
|
||||
void emitIsArray(Emitter& e);
|
||||
void emitIsObject(Emitter& e);
|
||||
void emitIsString(Emitter& e);
|
||||
void emitIsInt(Emitter& e);
|
||||
void emitIsDouble(Emitter& e);
|
||||
void emitIsBool(Emitter& e);
|
||||
void emitEmpty(Emitter& e);
|
||||
void emitUnset(Emitter& e, ExpressionPtr exp = ExpressionPtr());
|
||||
void emitVisitAndUnset(Emitter& e, ExpressionPtr exp);
|
||||
void emitSet(Emitter& e);
|
||||
void emitSetOp(Emitter& e, int op);
|
||||
void emitBind(Emitter& e);
|
||||
void emitIncDec(Emitter& e, IncDecOp cop);
|
||||
void emitIncDec(Emitter& e, unsigned char cop);
|
||||
void emitPop(Emitter& e);
|
||||
void emitConvertToCell(Emitter& e);
|
||||
void emitFreePendingIters(Emitter& e);
|
||||
void emitConvertToCellIfVar(Emitter& e);
|
||||
void emitConvertToCellOrLoc(Emitter& e);
|
||||
void emitConvertSecondToCell(Emitter& e);
|
||||
@@ -732,6 +609,7 @@ public:
|
||||
void emitStringSwitch(Emitter& e, SwitchStatementPtr s,
|
||||
std::vector<Label>& caseLabels, Label& done,
|
||||
const SwitchState& state);
|
||||
void emitIterBreak(Emitter& e, uint64_t n, Label& targ);
|
||||
|
||||
void markElem(Emitter& e);
|
||||
void markNewElem(Emitter& e);
|
||||
@@ -797,90 +675,34 @@ public:
|
||||
|
||||
bool emitCallUserFunc(Emitter& e, SimpleFunctionCallPtr node);
|
||||
Func* canEmitBuiltinCall(const std::string& name, int numParams);
|
||||
void emitFuncCall(Emitter& e, FunctionCallPtr node,
|
||||
const char* nameOverride = nullptr,
|
||||
ExpressionListPtr paramsOverride = nullptr);
|
||||
void emitFuncCall(Emitter& e, FunctionCallPtr node);
|
||||
void emitFuncCallArg(Emitter& e, ExpressionPtr exp, int paramId);
|
||||
void emitBuiltinCallArg(Emitter& e, ExpressionPtr exp, int paramId,
|
||||
bool byRef);
|
||||
void emitBuiltinDefaultArg(Emitter& e, Variant& v, DataType t, int paramId);
|
||||
void emitClass(Emitter& e, ClassScopePtr cNode, bool topLevel);
|
||||
void emitTypedef(Emitter& e, TypedefStatementPtr);
|
||||
void emitForeachListAssignment(Emitter& e,
|
||||
ListAssignmentPtr la,
|
||||
void emitForeachListAssignment(Emitter& e, ListAssignmentPtr la,
|
||||
int vLocalId);
|
||||
void emitForeach(Emitter& e, ForEachStatementPtr fe);
|
||||
void emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc);
|
||||
void emitMakeUnitFatal(Emitter& e,
|
||||
const char* msg,
|
||||
FatalOp k = FatalOp::Runtime);
|
||||
FatalKind k = FatalKind::Runtime,
|
||||
bool skipFrame = false);
|
||||
|
||||
// Emits a Jmp or IterBreak instruction to the specified target, freeing
|
||||
// the specified iterator variables. emitJump() cannot be used to leave a
|
||||
// try region, except if it jumps to the m_finallyLabel of the try region.
|
||||
void emitJump(Emitter& e, IterVec& iters, Label& target);
|
||||
|
||||
// These methods handle the return, break, continue, and goto operations.
|
||||
// These methods are aware of try/finally blocks and foreach blocks and
|
||||
// will free iterators and jump to finally epilogues as appropriate.
|
||||
void emitReturn(Emitter& e, char sym, StatementPtr s);
|
||||
void emitBreak(Emitter& e, int depth, StatementPtr s);
|
||||
void emitContinue(Emitter& e, int depth, StatementPtr s);
|
||||
void emitGoto(Emitter& e, StringData* name, StatementPtr s);
|
||||
|
||||
// Helper methods for emitting IterFree instructions
|
||||
void emitIterFree(Emitter& e, IterVec& iters);
|
||||
void emitIterFreeForReturn(Emitter& e);
|
||||
|
||||
// A "finally epilogue" is a blob of bytecode that comes after an inline
|
||||
// copy of a "finally" clause body. Finally epilogues are used to ensure
|
||||
// that that the bodies of finally clauses are executed whenever a return,
|
||||
// break, continue, or goto operation jumps out of their corresponding
|
||||
// "try" blocks.
|
||||
void emitFinallyEpilogue(Emitter& e, Region* entry);
|
||||
void emitReturnTrampoline(Emitter& e, Region* entry,
|
||||
std::vector<Label*>& cases, char sym);
|
||||
void emitBreakTrampoline(Emitter& e, Region* entry,
|
||||
std::vector<Label*>& cases, int depth);
|
||||
void emitContinueTrampoline(Emitter& e, Region* entry,
|
||||
std::vector<Label*>& cases, int depth);
|
||||
void emitGotoTrampoline(Emitter& e, Region* entry,
|
||||
std::vector<Label*>& cases, StringData* name);
|
||||
|
||||
Funclet* addFunclet(Thunklet* body);
|
||||
Funclet* addFunclet(StatementPtr stmt,
|
||||
Thunklet* body);
|
||||
Funclet* getFunclet(StatementPtr stmt);
|
||||
void addFunclet(Thunklet* body, Label* entry);
|
||||
void emitFunclets(Emitter& e);
|
||||
|
||||
struct FaultIterInfo {
|
||||
Id iterId;
|
||||
IterKind kind;
|
||||
};
|
||||
|
||||
void newFaultRegion(Offset start,
|
||||
Offset end,
|
||||
Label* entry,
|
||||
void newFaultRegion(Offset start, Offset end, Thunklet* t,
|
||||
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
|
||||
void newFaultRegion(StatementPtr stmt,
|
||||
Offset start,
|
||||
Offset end,
|
||||
Label* entry,
|
||||
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
|
||||
void
|
||||
newFaultRegionAndFunclet(Offset start,
|
||||
Offset end,
|
||||
Thunklet* t,
|
||||
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
|
||||
void
|
||||
newFaultRegionAndFunclet(StatementPtr stmt,
|
||||
Offset start,
|
||||
Offset end,
|
||||
Thunklet* t,
|
||||
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
|
||||
|
||||
void newFPIRegion(Offset start, Offset end, Offset fpOff);
|
||||
void copyOverCatchAndFaultRegions(FuncEmitter* fe);
|
||||
void copyOverExnHandlers(FuncEmitter* fe);
|
||||
void copyOverFPIRegions(FuncEmitter* fe);
|
||||
void saveMaxStackCells(FuncEmitter* fe);
|
||||
void finishFunc(Emitter& e, FuncEmitter* fe);
|
||||
@@ -892,37 +714,11 @@ public:
|
||||
void emitClassTraitAliasRule(PreClassEmitter* pce,
|
||||
TraitAliasStatementPtr rule);
|
||||
void emitClassUseTrait(PreClassEmitter* pce, UseTraitStatementPtr useStmt);
|
||||
|
||||
// Helper function for creating entries.
|
||||
RegionPtr createRegion(StatementPtr s, Region::Kind kind);
|
||||
// Enter/leave the passed in entry. Note that entries sometimes need be
|
||||
// to be constructed before they are entered, or need to be accessed
|
||||
// after they are left. This especially applies to constructs such
|
||||
// as loops and try blocks.
|
||||
void enterRegion(RegionPtr);
|
||||
void leaveRegion(RegionPtr);
|
||||
|
||||
// Functions used for handling state IDs allocation.
|
||||
// FIXME (#3275259): This should be moved into global / func
|
||||
// body / fault funclet entries in order to optimize state
|
||||
// allocation. See the task description for more details.
|
||||
void registerControlTarget(ControlTarget* t);
|
||||
void unregisterControlTarget(ControlTarget* t);
|
||||
|
||||
void registerReturn(StatementPtr s, Region* entry, char sym);
|
||||
void registerYieldAwait(ExpressionPtr e);
|
||||
ControlTargetPtr registerBreak(StatementPtr s, Region* entry, int depth,
|
||||
bool alloc);
|
||||
ControlTargetPtr registerContinue(StatementPtr s, Region* entry, int depth,
|
||||
bool alloc);
|
||||
ControlTargetPtr registerGoto(StatementPtr s, Region* entry,
|
||||
StringData* name, bool alloc);
|
||||
};
|
||||
|
||||
void emitAllHHBC(AnalysisResultPtr ar);
|
||||
|
||||
extern "C" {
|
||||
String hphp_compiler_serialize_code_model_for(String code, String prefix);
|
||||
Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
|
||||
const char* filename);
|
||||
Unit* hphp_build_native_func_unit(const HhbcExtFuncInfo* builtinFuncs,
|
||||
|
||||
@@ -13,13 +13,9 @@
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "folly/ScopeGuard.h"
|
||||
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/compiler/analysis/lambda_names.h"
|
||||
#include "hphp/compiler/analysis/analysis_result.h"
|
||||
#include "hphp/compiler/analysis/class_scope.h"
|
||||
#include "hphp/compiler/statement/statement_list.h"
|
||||
@@ -27,10 +23,11 @@
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/analysis/constant_table.h"
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
#include <sys/stat.h>
|
||||
#include "hphp/compiler/parser/parser.h"
|
||||
#include "hphp/util/logger.h"
|
||||
#include "hphp/util/util.h"
|
||||
#include "hphp/util/deprecated/base.h"
|
||||
#include "hphp/util/base.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/compiler/statement/function_statement.h"
|
||||
#include "hphp/compiler/analysis/variable_table.h"
|
||||
@@ -39,14 +36,15 @@
|
||||
#include "hphp/compiler/expression/user_attribute.h"
|
||||
#include "hphp/runtime/base/complex-types.h"
|
||||
|
||||
namespace HPHP {
|
||||
using namespace HPHP;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FileScope::FileScope(const string &fileName, int fileSize, const MD5 &md5)
|
||||
: BlockScope("", "", StatementPtr(), BlockScope::FileScope),
|
||||
m_size(fileSize), m_md5(md5), m_includeState(0), m_system(false),
|
||||
m_fileName(fileName), m_redeclaredFunctions(0) {
|
||||
m_size(fileSize), m_md5(md5), m_module(false), m_privateInclude(false),
|
||||
m_externInclude(false),
|
||||
m_includeState(0), m_fileName(fileName), m_redeclaredFunctions(0) {
|
||||
pushAttribute(); // for global scope
|
||||
}
|
||||
|
||||
@@ -68,11 +66,6 @@ void FileScope::setFileLevel(StatementListPtr stmtList) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileScope::setSystem() {
|
||||
m_fileName = "/:" + m_fileName;
|
||||
m_system = true;
|
||||
}
|
||||
|
||||
FunctionScopePtr FileScope::setTree(AnalysisResultConstPtr ar,
|
||||
StatementListPtr tree) {
|
||||
m_tree = tree;
|
||||
@@ -105,7 +98,6 @@ void makeFatalMeth(FileScope& file,
|
||||
int line,
|
||||
Meth meth) {
|
||||
LocationPtr loc(new Location());
|
||||
LabelScopePtr labelScope(new LabelScope());
|
||||
loc->file = file.getName().c_str();
|
||||
loc->first(line, 0);
|
||||
loc->last(line, 0);
|
||||
@@ -116,8 +108,8 @@ void makeFatalMeth(FileScope& file,
|
||||
new SimpleFunctionCall(scope, loc, "throw_fatal", false, args,
|
||||
ExpressionPtr()));
|
||||
meth(e);
|
||||
ExpStatementPtr exp(new ExpStatement(scope, labelScope, loc, e));
|
||||
StatementListPtr stmts(new StatementList(scope, labelScope, loc));
|
||||
ExpStatementPtr exp(new ExpStatement(scope, loc, e));
|
||||
StatementListPtr stmts(new StatementList(scope, loc));
|
||||
stmts->addElement(exp);
|
||||
|
||||
FunctionScopePtr fs = file.setTree(ar, stmts);
|
||||
@@ -262,10 +254,9 @@ void FileScope::addConstantDependency(AnalysisResultPtr ar,
|
||||
}
|
||||
|
||||
void FileScope::analyzeProgram(AnalysisResultPtr ar) {
|
||||
if (!m_pseudoMain) return;
|
||||
m_pseudoMain->getStmt()->analyzeProgram(ar);
|
||||
|
||||
resolve_lambda_names(ar, shared_from_this());
|
||||
if (m_pseudoMain) {
|
||||
m_pseudoMain->getStmt()->analyzeProgram(ar);
|
||||
}
|
||||
}
|
||||
|
||||
ClassScopeRawPtr FileScope::resolveClass(ClassScopeRawPtr cls) {
|
||||
@@ -330,80 +321,80 @@ bool FileScope::insertClassUtil(AnalysisResultPtr ar,
|
||||
|
||||
void FileScope::analyzeIncludesHelper(AnalysisResultPtr ar) {
|
||||
m_includeState = 1;
|
||||
SCOPE_EXIT { m_includeState = 2; };
|
||||
if (m_pseudoMain) {
|
||||
StatementList &stmts = *getStmt();
|
||||
bool hoistOnly = false;
|
||||
for (int i = 0, n = stmts.getCount(); i < n; i++) {
|
||||
StatementPtr s = stmts[i];
|
||||
if (!s) continue;
|
||||
if (s->is(Statement::KindOfClassStatement) ||
|
||||
s->is(Statement::KindOfInterfaceStatement)) {
|
||||
|
||||
if (!m_pseudoMain) return;
|
||||
|
||||
StatementList &stmts = *getStmt();
|
||||
bool hoistOnly = false;
|
||||
|
||||
for (int i = 0, n = stmts.getCount(); i < n; i++) {
|
||||
StatementPtr s = stmts[i];
|
||||
if (!s) continue;
|
||||
|
||||
if (s->is(Statement::KindOfClassStatement) ||
|
||||
s->is(Statement::KindOfInterfaceStatement)) {
|
||||
ClassScopeRawPtr cls(
|
||||
static_pointer_cast<InterfaceStatement>(s)->getClassScope());
|
||||
if (hoistOnly) {
|
||||
const string &parent = cls->getOriginalParent();
|
||||
if (cls->getBases().size() > (parent.empty() ? 0 : 1)) {
|
||||
continue;
|
||||
ClassScopeRawPtr cls(
|
||||
static_pointer_cast<InterfaceStatement>(s)->getClassScope());
|
||||
if (hoistOnly) {
|
||||
const string &parent = cls->getOriginalParent();
|
||||
if (cls->getBases().size() > (parent.empty() ? 0 : 1)) {
|
||||
continue;
|
||||
}
|
||||
if (!parent.empty()) {
|
||||
ClassScopeRawPtr c = ar->findClass(parent);
|
||||
if (!c || (c->isVolatile() &&
|
||||
!resolveClass(c) && !checkClass(parent))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!parent.empty()) {
|
||||
ClassScopeRawPtr c = ar->findClass(parent);
|
||||
if (!c || (c->isVolatile() &&
|
||||
!resolveClass(c) && !checkClass(parent))) {
|
||||
if (cls->isVolatile()) {
|
||||
insertClassUtil(ar, cls, true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (s->is(Statement::KindOfFunctionStatement)) {
|
||||
FunctionScopeRawPtr func(
|
||||
static_pointer_cast<FunctionStatement>(s)->getFunctionScope());
|
||||
if (func->isVolatile()) m_providedDefs.insert(func);
|
||||
continue;
|
||||
}
|
||||
if (!hoistOnly && s->is(Statement::KindOfExpStatement)) {
|
||||
ExpressionRawPtr exp(
|
||||
static_pointer_cast<ExpStatement>(s)->getExpression());
|
||||
if (exp && exp->is(Expression::KindOfIncludeExpression)) {
|
||||
FileScopeRawPtr fs(
|
||||
static_pointer_cast<IncludeExpression>(exp)->getIncludedFile(ar));
|
||||
if (fs && fs->m_includeState != 1) {
|
||||
if (!fs->m_includeState) {
|
||||
if (m_module && fs->m_privateInclude) {
|
||||
BOOST_FOREACH(BlockScopeRawPtr bs, m_providedDefs) {
|
||||
fs->m_providedDefs.insert(bs);
|
||||
}
|
||||
}
|
||||
fs->analyzeIncludesHelper(ar);
|
||||
}
|
||||
BOOST_FOREACH(BlockScopeRawPtr bs, fs->m_providedDefs) {
|
||||
m_providedDefs.insert(bs);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cls->isVolatile()) {
|
||||
insertClassUtil(ar, cls, true);
|
||||
}
|
||||
continue;
|
||||
hoistOnly = true;
|
||||
}
|
||||
|
||||
if (s->is(Statement::KindOfFunctionStatement)) {
|
||||
FunctionScopeRawPtr func(
|
||||
static_pointer_cast<FunctionStatement>(s)->getFunctionScope());
|
||||
if (func->isVolatile()) m_providedDefs.insert(func);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hoistOnly && s->is(Statement::KindOfExpStatement)) {
|
||||
ExpressionRawPtr exp(
|
||||
static_pointer_cast<ExpStatement>(s)->getExpression());
|
||||
if (exp && exp->is(Expression::KindOfIncludeExpression)) {
|
||||
FileScopeRawPtr fs(
|
||||
static_pointer_cast<IncludeExpression>(exp)->getIncludedFile(ar));
|
||||
if (fs && fs->m_includeState != 1) {
|
||||
if (!fs->m_includeState) {
|
||||
fs->analyzeIncludesHelper(ar);
|
||||
}
|
||||
BOOST_FOREACH(BlockScopeRawPtr bs, fs->m_providedDefs) {
|
||||
m_providedDefs.insert(bs);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hoistOnly = true;
|
||||
}
|
||||
|
||||
m_includeState = 2;
|
||||
}
|
||||
|
||||
void FileScope::analyzeIncludes(AnalysisResultPtr ar) {
|
||||
if (!m_includeState) {
|
||||
if (!m_privateInclude && !m_includeState) {
|
||||
analyzeIncludesHelper(ar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileScope::visit(AnalysisResultPtr ar,
|
||||
void (*cb)(AnalysisResultPtr, StatementPtr, void*),
|
||||
void *data) {
|
||||
void *data)
|
||||
{
|
||||
if (m_pseudoMain) {
|
||||
cb(ar, m_pseudoMain->getStmt(), data);
|
||||
}
|
||||
@@ -418,11 +409,8 @@ const string &FileScope::pseudoMainName() {
|
||||
|
||||
FunctionScopePtr FileScope::createPseudoMain(AnalysisResultConstPtr ar) {
|
||||
StatementListPtr st = m_tree;
|
||||
LabelScopePtr labelScope(new LabelScope());
|
||||
FunctionStatementPtr f
|
||||
(new FunctionStatement(BlockScopePtr(),
|
||||
labelScope,
|
||||
LocationPtr(),
|
||||
(new FunctionStatement(BlockScopePtr(), LocationPtr(),
|
||||
ModifierExpressionPtr(),
|
||||
false, pseudoMainName(),
|
||||
ExpressionListPtr(), TypeAnnotationPtr(),
|
||||
@@ -458,18 +446,24 @@ string FileScope::outputFilebase() const {
|
||||
|
||||
static void getFuncScopesSet(BlockScopeRawPtrQueue &v,
|
||||
const StringToFunctionScopePtrMap &funcMap) {
|
||||
for (const auto& iter : funcMap) {
|
||||
FunctionScopePtr f = iter.second;
|
||||
if (f->getStmt()) {
|
||||
for (StringToFunctionScopePtrMap::const_iterator
|
||||
iter = funcMap.begin(), end = funcMap.end();
|
||||
iter != end; ++iter) {
|
||||
FunctionScopePtr f = iter->second;
|
||||
if (f->isUserFunction()) {
|
||||
v.push_back(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileScope::getScopesSet(BlockScopeRawPtrQueue &v) {
|
||||
for (const auto& clsVec : getClasses()) {
|
||||
for (const auto cls : clsVec.second) {
|
||||
if (cls->getStmt()) {
|
||||
const StringToClassScopePtrVecMap &classes = getClasses();
|
||||
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin(),
|
||||
end = classes.end(); iter != end; ++iter) {
|
||||
for (ClassScopePtrVec::const_iterator it = iter->second.begin(),
|
||||
e = iter->second.end(); it != e; ++it) {
|
||||
ClassScopePtr cls = *it;
|
||||
if (cls->isUserClass()) {
|
||||
v.push_back(cls);
|
||||
getFuncScopesSet(v, cls->getFunctions());
|
||||
}
|
||||
@@ -477,17 +471,20 @@ void FileScope::getScopesSet(BlockScopeRawPtrQueue &v) {
|
||||
}
|
||||
|
||||
getFuncScopesSet(v, getFunctions());
|
||||
if (const auto redec = m_redeclaredFunctions) {
|
||||
for (const auto& funcVec : *redec) {
|
||||
auto i = funcVec.second.begin(), e = funcVec.second.end();
|
||||
if (const StringToFunctionScopePtrVecMap *redec = m_redeclaredFunctions) {
|
||||
for (StringToFunctionScopePtrVecMap::const_iterator iter = redec->begin(),
|
||||
end = redec->end(); iter != end; ++iter) {
|
||||
FunctionScopePtrVec::const_iterator i = iter->second.begin(),
|
||||
e = iter->second.end();
|
||||
v.insert(v.end(), ++i, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileScope::getClassesFlattened(ClassScopePtrVec &classes) const {
|
||||
for (const auto& clsVec : m_classes) {
|
||||
for (auto cls : clsVec.second) {
|
||||
for (StringToClassScopePtrVecMap::const_iterator it = m_classes.begin();
|
||||
it != m_classes.end(); ++it) {
|
||||
BOOST_FOREACH(ClassScopePtr cls, it->second) {
|
||||
classes.push_back(cls);
|
||||
}
|
||||
}
|
||||
@@ -510,4 +507,3 @@ void FileScope::serialize(JSON::DocTarget::OutputStream &out) const {
|
||||
ms.done();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,16 +17,14 @@
|
||||
#ifndef incl_HPHP_FILE_SCOPE_H_
|
||||
#define incl_HPHP_FILE_SCOPE_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "hphp/compiler/analysis/block_scope.h"
|
||||
#include "hphp/compiler/analysis/function_container.h"
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/compiler/code_generator.h"
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/util/md5.h"
|
||||
|
||||
namespace HPHP {
|
||||
@@ -64,7 +62,6 @@ public:
|
||||
IsFoldable = 0x1000,// function can be constant folded
|
||||
NeedsActRec = 0x2000,// builtin function needs ActRec
|
||||
AllowOverride = 0x4000,// allow override of systemlib or builtin
|
||||
NeedsFinallyLocals = 0x8000,
|
||||
};
|
||||
|
||||
typedef boost::adjacency_list<boost::setS, boost::vecS> Graph;
|
||||
@@ -80,7 +77,6 @@ public:
|
||||
|
||||
const std::string &getName() const { return m_fileName;}
|
||||
const MD5& getMd5() const { return m_md5; }
|
||||
void setMd5(const MD5& md5) { m_md5 = md5; }
|
||||
StatementListPtr getStmt() const { return m_tree;}
|
||||
const StringToClassScopePtrVecMap &getClasses() const {
|
||||
return m_classes;
|
||||
@@ -145,12 +141,8 @@ public:
|
||||
const std::string &decname);
|
||||
|
||||
void addClassAlias(const std::string& target, const std::string& alias) {
|
||||
m_classAliasMap.insert(
|
||||
std::make_pair(
|
||||
boost::to_lower_copy(target),
|
||||
boost::to_lower_copy(alias)
|
||||
)
|
||||
);
|
||||
m_classAliasMap.insert(std::make_pair(Util::toLower(target),
|
||||
Util::toLower(alias)));
|
||||
}
|
||||
|
||||
std::multimap<std::string,std::string> const& getClassAliases() const {
|
||||
@@ -158,7 +150,7 @@ public:
|
||||
}
|
||||
|
||||
void addTypeAliasName(const std::string& name) {
|
||||
m_typeAliasNames.insert(boost::to_lower_copy(name));
|
||||
m_typeAliasNames.insert(Util::toLower(name));
|
||||
}
|
||||
|
||||
std::set<std::string> const& getTypeAliasNames() const {
|
||||
@@ -173,8 +165,10 @@ public:
|
||||
m_vertex = vertex;
|
||||
}
|
||||
|
||||
void setSystem();
|
||||
bool isSystem() const { return m_system; }
|
||||
void setModule() { m_module = true; }
|
||||
void setPrivateInclude() { m_privateInclude = true; }
|
||||
bool isPrivateInclude() const { return m_privateInclude && !m_externInclude; }
|
||||
void setExternInclude() { m_externInclude = true; }
|
||||
|
||||
void analyzeProgram(AnalysisResultPtr ar);
|
||||
void analyzeIncludes(AnalysisResultPtr ar);
|
||||
@@ -204,8 +198,10 @@ public:
|
||||
private:
|
||||
int m_size;
|
||||
MD5 m_md5;
|
||||
unsigned m_module : 1;
|
||||
unsigned m_privateInclude : 1;
|
||||
unsigned m_externInclude : 1;
|
||||
unsigned m_includeState : 2;
|
||||
unsigned m_system : 1;
|
||||
|
||||
std::vector<int> m_attributes;
|
||||
std::string m_fileName;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace HPHP {
|
||||
|
||||
class CodeGenerator;
|
||||
DECLARE_BOOST_TYPES(AnalysisResult);
|
||||
DECLARE_EXTENDED_BOOST_TYPES(FunctionScope);
|
||||
DECLARE_BOOST_TYPES(FunctionScope);
|
||||
DECLARE_BOOST_TYPES(ClassScope);
|
||||
DECLARE_BOOST_TYPES(FunctionContainer);
|
||||
|
||||
|
||||
@@ -292,8 +292,7 @@ bool FunctionScope::hasUserAttr(const char *attr) const {
|
||||
}
|
||||
|
||||
bool FunctionScope::isZendParamMode() const {
|
||||
return m_attributeClassInfo &
|
||||
(ClassInfo::ZendParamModeNull | ClassInfo::ZendParamModeFalse);
|
||||
return m_attributeClassInfo & ClassInfo::ZendParamMode;
|
||||
}
|
||||
|
||||
bool FunctionScope::isPublic() const {
|
||||
@@ -355,11 +354,6 @@ bool FunctionScope::needsActRec() const {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FunctionScope::needsFinallyLocals() const {
|
||||
bool res = (m_attribute & FileScope::NeedsFinallyLocals);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FunctionScope::mayContainThis() {
|
||||
return inPseudoMain() || getContainingClass() ||
|
||||
(isClosure() && !m_modifiers->isStatic());
|
||||
@@ -848,14 +842,11 @@ bool FunctionScope::popReturnType() {
|
||||
m_prevReturn.reset();
|
||||
return false;
|
||||
}
|
||||
Logger::Verbose("Corrected %s's return type %s -> %s",
|
||||
getFullName().c_str(),
|
||||
m_prevReturn->toString().c_str(),
|
||||
m_returnType->toString().c_str());
|
||||
} else {
|
||||
Logger::Verbose("Set %s's return type %s",
|
||||
getFullName().c_str(),
|
||||
m_returnType->toString().c_str());
|
||||
if (!isFirstPass()) {
|
||||
Logger::Verbose("Corrected function return type %s -> %s",
|
||||
m_prevReturn->toString().c_str(),
|
||||
m_returnType->toString().c_str());
|
||||
}
|
||||
}
|
||||
} else if (!m_prevReturn) {
|
||||
return false;
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
#include "hphp/compiler/expression/user_attribute.h"
|
||||
#include "hphp/compiler/analysis/block_scope.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/json.h"
|
||||
|
||||
#include "hphp/util/hash-map-typedefs.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/parser/parser.h"
|
||||
|
||||
namespace HPHP {
|
||||
@@ -96,7 +95,6 @@ public:
|
||||
* What kind of function this is.
|
||||
*/
|
||||
bool isUserFunction() const { return !m_system && !isNative(); }
|
||||
bool isSystem() const { return m_system; }
|
||||
bool isDynamic() const { return m_dynamic; }
|
||||
bool isPublic() const;
|
||||
bool isProtected() const;
|
||||
@@ -228,8 +226,6 @@ public:
|
||||
bool allowOverride() const;
|
||||
void setAllowOverride();
|
||||
|
||||
bool needsFinallyLocals() const;
|
||||
|
||||
/**
|
||||
* Whether this function is a runtime helper function
|
||||
*/
|
||||
@@ -389,7 +385,7 @@ public:
|
||||
|
||||
ReadWriteMutex &getInlineMutex() { return m_inlineMutex; }
|
||||
|
||||
DECLARE_EXTENDED_BOOST_TYPES(FunctionInfo);
|
||||
DECLARE_BOOST_TYPES(FunctionInfo);
|
||||
|
||||
static void RecordFunctionInfo(std::string fname, FunctionScopePtr func);
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_LABEL_SCOPE_H_
|
||||
#define incl_HPHP_LABEL_SCOPE_H_
|
||||
|
||||
#include "hphp/compiler/hphp.h"
|
||||
#include "hphp/util/deprecated/base.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Statement;
|
||||
|
||||
DECLARE_BOOST_TYPES(Statement);
|
||||
|
||||
class LabelScope {
|
||||
public:
|
||||
class LabelInfo {
|
||||
public:
|
||||
LabelInfo(StatementPtr s, const std::string& name)
|
||||
: m_stmt(s), m_name(name) {}
|
||||
|
||||
StatementPtr getStatement() const { return m_stmt; }
|
||||
const std::string& getName() const { return m_name; }
|
||||
|
||||
private:
|
||||
StatementPtr m_stmt;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
const std::vector<LabelInfo>& getLabels() const { return m_labels; }
|
||||
void addLabel(StatementPtr s, const std::string& label) {
|
||||
m_labels.push_back(LabelInfo(s, label));
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<LabelInfo> m_labels;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
#endif // incl_HPHP_LABEL_SCOPE_H_
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
#include "hphp/compiler/analysis/lambda_names.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "folly/ScopeGuard.h"
|
||||
|
||||
#include "hphp/compiler/analysis/variable_table.h"
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
#include "hphp/compiler/statement/method_statement.h"
|
||||
#include "hphp/compiler/statement/function_statement.h"
|
||||
#include "hphp/compiler/expression/closure_expression.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
|
||||
struct NameScope {
|
||||
NameScope* const prev;
|
||||
VariableTablePtr const vars;
|
||||
};
|
||||
|
||||
struct Walker {
|
||||
explicit Walker(AnalysisResultPtr ar)
|
||||
: m_curScope{nullptr}
|
||||
, m_ar{ar}
|
||||
{}
|
||||
|
||||
void walk_functions(const FunctionContainer& funcCont) {
|
||||
for (auto& kv : funcCont.getFunctions()) {
|
||||
walk_function(kv.second);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void visit_closure(ClosureExpressionPtr ce) {
|
||||
auto const cfunc = ce->getClosureFunction();
|
||||
|
||||
with_scope(
|
||||
cfunc->getScope()->getVariables(),
|
||||
[&] {
|
||||
walk_ast(cfunc->getStmts());
|
||||
}
|
||||
);
|
||||
|
||||
if (ce->type() != ClosureType::Short) return;
|
||||
if (ce->captureState() == ClosureExpression::CaptureState::Known) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto const paramNames = ce->collectParamNames();
|
||||
std::set<std::string> mentioned;
|
||||
cfunc->getScope()->getVariables()->getNames(mentioned);
|
||||
|
||||
std::set<std::string> toCapture;
|
||||
|
||||
for (auto& m : mentioned) {
|
||||
if (paramNames.count(m)) continue;
|
||||
if (m == "this") {
|
||||
toCapture.insert("this");
|
||||
continue;
|
||||
}
|
||||
for (auto scope = m_curScope; scope; scope = scope->prev) {
|
||||
if (scope->vars->getSymbol(m)) {
|
||||
toCapture.insert(m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cfunc->getFunctionScope()->containsThis()) {
|
||||
toCapture.insert("this");
|
||||
}
|
||||
|
||||
ce->setCaptureList(m_ar, toCapture);
|
||||
}
|
||||
|
||||
void walk_ast(ConstructPtr node) {
|
||||
if (!node) return;
|
||||
|
||||
if (dynamic_pointer_cast<MethodStatement>(node)) {
|
||||
// Don't descend into nested non-closure functions, or functions
|
||||
// in the psuedo-main.
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto ce = dynamic_pointer_cast<ClosureExpression>(node)) {
|
||||
visit_closure(ce);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < node->getKidCount(); ++i) {
|
||||
walk_ast(node->getNthKid(i));
|
||||
}
|
||||
}
|
||||
|
||||
void walk_function(const FunctionScopePtr& fscope) {
|
||||
if (fscope->isClosure()) return;
|
||||
auto ms = dynamic_pointer_cast<MethodStatement>(fscope->getStmt());
|
||||
|
||||
ConstructPtr node(ms->getStmts());
|
||||
with_scope(
|
||||
fscope->getVariables(),
|
||||
[&] {
|
||||
walk_ast(node);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
template<class Func>
|
||||
void with_scope(const VariableTablePtr& scopeVars, Func func) {
|
||||
auto newScope = NameScope { m_curScope, scopeVars };
|
||||
m_curScope = &newScope;
|
||||
SCOPE_EXIT { m_curScope = m_curScope->prev; };
|
||||
func();
|
||||
}
|
||||
|
||||
private:
|
||||
NameScope* m_curScope;
|
||||
AnalysisResultPtr m_ar;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void resolve_lambda_names(AnalysisResultPtr ar, const FileScopePtr& fscope) {
|
||||
Walker walker(ar);
|
||||
|
||||
ClassScopePtrVec classScopes;
|
||||
fscope->getClassesFlattened(classScopes);
|
||||
for (auto& cls : classScopes) {
|
||||
walker.walk_functions(*cls);
|
||||
}
|
||||
walker.walk_functions(*fscope);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_COMPILER_ANALYSIS_LAMBDA_NAMES_H_
|
||||
#define incl_HPHP_COMPILER_ANALYSIS_LAMBDA_NAMES_H_
|
||||
|
||||
#include "hphp/compiler/statement/statement_list.h"
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
#include "hphp/compiler/analysis/analysis_result.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* After the first analysis pass over a file, this pass must run to
|
||||
* resolve names for lambda expressions and determine their automatic
|
||||
* capture lists.
|
||||
*/
|
||||
void resolve_lambda_names(AnalysisResultPtr ar, const FileScopePtr&);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -623,8 +623,7 @@ public:
|
||||
e->setLocation(sub->getLocation());
|
||||
e->setBlockScope(sub->getScope());
|
||||
ExpStatementPtr exp(
|
||||
new ExpStatement(sub->getScope(), sub->getLabelScope(),
|
||||
sub->getLocation(), e));
|
||||
new ExpStatement(sub->getScope(), sub->getLocation(), e));
|
||||
sl->insertElement(exp, ix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace HPHP { namespace Compiler {
|
||||
static void collapseJmp(Offset* offsetPtr, Op* instr, Op* start) {
|
||||
if (offsetPtr) {
|
||||
Op* dest = instr + *offsetPtr;
|
||||
while (isUnconditionalJmp(*dest) && dest != instr) {
|
||||
while (*dest == OpJmp && dest != instr) {
|
||||
dest = start + instrJumpTarget(start, dest - start);
|
||||
}
|
||||
*offsetPtr = dest - instr;
|
||||
@@ -91,10 +91,10 @@ Peephole::Peephole(UnitEmitter &ue, MetaInfoBuilder& metaInfo)
|
||||
// fallthrough
|
||||
|
||||
incDecOp:
|
||||
if (static_cast<IncDecOp>(imm->u_OA) == IncDecOp::PostInc) {
|
||||
imm->u_OA = static_cast<unsigned char>(IncDecOp::PreInc);
|
||||
} else if (static_cast<IncDecOp>(imm->u_OA) == IncDecOp::PostDec) {
|
||||
imm->u_OA = static_cast<unsigned char>(IncDecOp::PreDec);
|
||||
if (imm->u_OA == PostInc) {
|
||||
imm->u_OA = PreInc;
|
||||
} else if (imm->u_OA == PostDec) {
|
||||
imm->u_OA = PreDec;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -18,10 +18,9 @@
|
||||
#define incl_HPHP_SYMBOL_TABLE_H_
|
||||
|
||||
#include "hphp/compiler/hphp.h"
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/util/util.h"
|
||||
#include "hphp/util/lock.h"
|
||||
#include "hphp/util/hash-map-typedefs.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -30,7 +29,7 @@ class BlockScope;
|
||||
class CodeGenerator;
|
||||
class Variant;
|
||||
DECLARE_BOOST_TYPES(Construct);
|
||||
DECLARE_EXTENDED_BOOST_TYPES(Type);
|
||||
DECLARE_BOOST_TYPES(Type);
|
||||
DECLARE_BOOST_TYPES(AnalysisResult);
|
||||
DECLARE_BOOST_TYPES(SymbolTable);
|
||||
DECLARE_BOOST_TYPES(FunctionScope);
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/runtime/base/builtin-functions.h"
|
||||
#include "hphp/runtime/vm/runtime.h"
|
||||
#include <boost/format.hpp>
|
||||
|
||||
using namespace HPHP;
|
||||
@@ -71,8 +70,6 @@ void Type::InitTypeHintMap() {
|
||||
s_HHTypeHintTypes["double"] = Type::Double;
|
||||
s_HHTypeHintTypes["float"] = Type::Double;
|
||||
s_HHTypeHintTypes["string"] = Type::String;
|
||||
// Type::Numeric doesn't include numeric strings; this is intentional
|
||||
s_HHTypeHintTypes["num"] = Type::Numeric;
|
||||
s_HHTypeHintTypes["resource"] = Type::Resource;
|
||||
s_HHTypeHintTypes["callable"] = Type::Variant;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
#define incl_HPHP_TYPE_H_
|
||||
|
||||
#include "hphp/compiler/hphp.h"
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/functional.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/util/case-insensitive.h"
|
||||
#include "hphp/runtime/base/types.h"
|
||||
|
||||
|
||||
|
||||
@@ -428,9 +428,7 @@ TypePtr VariableTable::add(Symbol *sym, TypePtr type,
|
||||
type = setType(ar, sym, type, true);
|
||||
if (sym->isParameter()) {
|
||||
auto p = dynamic_pointer_cast<ParameterExpression>(construct);
|
||||
if (p) {
|
||||
sym->setDeclaration(construct);
|
||||
}
|
||||
if (p) sym->setDeclaration(construct);
|
||||
} else {
|
||||
sym->setDeclaration(construct);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "hphp/compiler/analysis/symbol_table.h"
|
||||
#include "hphp/compiler/statement/statement.h"
|
||||
#include "hphp/compiler/analysis/class_scope.h"
|
||||
#include "hphp/util/hash-map-typedefs.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -297,7 +296,7 @@ public:
|
||||
* GlobalVariables class to make ThreadLocal<GlobalVaribles> work.
|
||||
* This data structure is only needed by global scope.
|
||||
*/
|
||||
DECLARE_EXTENDED_BOOST_TYPES(StaticGlobalInfo);
|
||||
DECLARE_BOOST_TYPES(StaticGlobalInfo);
|
||||
struct StaticGlobalInfo {
|
||||
Symbol *sym;
|
||||
VariableTable *variables; // where this variable was from
|
||||
|
||||
@@ -50,7 +50,8 @@ using namespace HPHP;
|
||||
|
||||
bool BuiltinSymbols::Loaded = false;
|
||||
StringBag BuiltinSymbols::s_strings;
|
||||
AnalysisResultPtr BuiltinSymbols::s_systemAr;
|
||||
|
||||
StringToFunctionScopePtrMap BuiltinSymbols::s_functions;
|
||||
|
||||
const char *const BuiltinSymbols::GlobalNames[] = {
|
||||
"HTTP_RAW_POST_DATA",
|
||||
@@ -85,7 +86,12 @@ const char *BuiltinSymbols::SystemClasses[] = {
|
||||
nullptr
|
||||
};
|
||||
|
||||
StringToClassScopePtrMap BuiltinSymbols::s_classes;
|
||||
VariableTablePtr BuiltinSymbols::s_variables;
|
||||
ConstantTablePtr BuiltinSymbols::s_constants;
|
||||
StringToTypePtrMap BuiltinSymbols::s_superGlobals;
|
||||
AnalysisResultPtr BuiltinSymbols::s_systemAr;
|
||||
void *BuiltinSymbols::s_handle_main = nullptr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -212,6 +218,7 @@ FunctionScopePtr BuiltinSymbols::ImportFunctionScopePtr(AnalysisResultPtr ar,
|
||||
}
|
||||
|
||||
void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
|
||||
StringToFunctionScopePtrMap &map,
|
||||
ClassInfo *cls) {
|
||||
const ClassInfo::MethodVec &methods = cls->getMethodsVec();
|
||||
for (auto it = methods.begin(); it != methods.end(); ++it) {
|
||||
@@ -221,13 +228,14 @@ void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
|
||||
}
|
||||
|
||||
FunctionScopePtr f = ImportFunctionScopePtr(ar, cls, *it);
|
||||
ar->addSystemFunction(f);
|
||||
assert(!map[f->getName()]);
|
||||
map[f->getName()] = f;
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltinSymbols::ImportExtMethods(AnalysisResultPtr ar,
|
||||
FunctionScopePtrVec &vec,
|
||||
ClassInfo *cls) {
|
||||
void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
|
||||
FunctionScopePtrVec &vec,
|
||||
ClassInfo *cls) {
|
||||
const ClassInfo::MethodVec &methods = cls->getMethodsVec();
|
||||
for (auto it = methods.begin(); it != methods.end(); ++it) {
|
||||
FunctionScopePtr f = ImportFunctionScopePtr(ar, cls, *it);
|
||||
@@ -279,7 +287,7 @@ void BuiltinSymbols::ImportExtConstants(AnalysisResultPtr ar,
|
||||
ClassScopePtr BuiltinSymbols::ImportClassScopePtr(AnalysisResultPtr ar,
|
||||
ClassInfo *cls) {
|
||||
FunctionScopePtrVec methods;
|
||||
ImportExtMethods(ar, methods, cls);
|
||||
ImportExtFunctions(ar, methods, cls);
|
||||
|
||||
ClassInfo::InterfaceVec ifaces = cls->getInterfacesVec();
|
||||
String parent = cls->getParentClass();
|
||||
@@ -317,7 +325,8 @@ void BuiltinSymbols::ImportExtClasses(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
ClassScopePtr cl = ImportClassScopePtr(ar, it->second);
|
||||
ar->addSystemClass(cl);
|
||||
assert(!s_classes[cl->getName()]);
|
||||
s_classes[cl->getName()] = cl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,11 +338,13 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
|
||||
ClassInfo::Load();
|
||||
|
||||
// load extension functions first, so system/php may call them
|
||||
ImportExtFunctions(ar, ClassInfo::GetSystem());
|
||||
ImportExtFunctions(ar, s_functions, ClassInfo::GetSystem());
|
||||
AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult());
|
||||
s_variables = VariableTablePtr(new VariableTable(*ar2.get()));
|
||||
s_constants = ConstantTablePtr(new ConstantTable(*ar2.get()));
|
||||
|
||||
ConstantTablePtr cns = ar->getConstants();
|
||||
// load extension constants, classes and dynamics
|
||||
ImportExtConstants(ar, cns, ClassInfo::GetSystem());
|
||||
ImportExtConstants(ar, s_constants, ClassInfo::GetSystem());
|
||||
ImportExtClasses(ar);
|
||||
|
||||
Array constants = ClassInfo::GetSystemConstants();
|
||||
@@ -342,11 +353,11 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
|
||||
CVarRef key = it.first();
|
||||
if (!key.isString()) continue;
|
||||
std::string name = key.toCStrRef().data();
|
||||
if (cns->getSymbol(name)) continue;
|
||||
if (s_constants->getSymbol(name)) continue;
|
||||
if (name == "true" || name == "false" || name == "null") continue;
|
||||
CVarRef value = it.secondRef();
|
||||
if (!value.isInitialized() || value.isObject()) continue;
|
||||
ExpressionPtr e = Expression::MakeScalarExpression(ar, ar, loc, value);
|
||||
ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value);
|
||||
TypePtr t =
|
||||
value.isNull() ? Type::Null :
|
||||
value.isBoolean() ? Type::Boolean :
|
||||
@@ -354,47 +365,122 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
|
||||
value.isDouble() ? Type::Double :
|
||||
value.isArray() ? Type::Array : Type::Variant;
|
||||
|
||||
cns->add(key.toCStrRef().data(), t, e, ar, e);
|
||||
s_constants->add(key.toCStrRef().data(), t, e, ar2, e);
|
||||
}
|
||||
s_variables = ar2->getVariables();
|
||||
for (int i = 0, n = NumGlobalNames(); i < n; ++i) {
|
||||
ar->getVariables()->add(GlobalNames[i], Type::Variant, false, ar,
|
||||
ConstructPtr(), ModifierExpressionPtr());
|
||||
s_variables->add(GlobalNames[i], Type::Variant, false, ar,
|
||||
ConstructPtr(), ModifierExpressionPtr());
|
||||
}
|
||||
|
||||
cns->setDynamic(ar, "PHP_BINARY", true);
|
||||
cns->setDynamic(ar, "PHP_BINDIR", true);
|
||||
cns->setDynamic(ar, "PHP_OS", true);
|
||||
cns->setDynamic(ar, "PHP_SAPI", true);
|
||||
cns->setDynamic(ar, "SID", true);
|
||||
s_constants->setDynamic(ar, "PHP_BINARY", true);
|
||||
s_constants->setDynamic(ar, "PHP_BINDIR", true);
|
||||
s_constants->setDynamic(ar, "PHP_OS", true);
|
||||
s_constants->setDynamic(ar, "PHP_SAPI", true);
|
||||
s_constants->setDynamic(ar, "SID", true);
|
||||
|
||||
// Systemlib files were all parsed by hphp_process_init
|
||||
// parse all PHP files under system/php
|
||||
s_systemAr = ar = AnalysisResultPtr(new AnalysisResult());
|
||||
ar->loadBuiltins();
|
||||
string slib = get_systemlib();
|
||||
|
||||
Scanner scanner(slib.c_str(), slib.size(),
|
||||
Option::GetScannerType(), "systemlib.php");
|
||||
Compiler::Parser parser(scanner, "systemlib.php", ar);
|
||||
if (!parser.parse()) {
|
||||
Logger::Error("Unable to parse systemlib.php: %s",
|
||||
parser.getMessage().c_str());
|
||||
assert(false);
|
||||
}
|
||||
|
||||
ar->analyzeProgram(true);
|
||||
ar->inferTypes();
|
||||
const StringToFileScopePtrMap &files = ar->getAllFiles();
|
||||
for (const auto& file : files) {
|
||||
file.second->setSystem();
|
||||
|
||||
const auto& classes = file.second->getClasses();
|
||||
for (const auto& clsVec : classes) {
|
||||
assert(clsVec.second.size() == 1);
|
||||
auto cls = clsVec.second[0];
|
||||
cls->setSystem();
|
||||
ar->addSystemClass(cls);
|
||||
for (const auto& func : cls->getFunctions()) {
|
||||
FunctionScope::RecordFunctionInfo(func.first, func.second);
|
||||
}
|
||||
for (StringToFileScopePtrMap::const_iterator iterFile = files.begin();
|
||||
iterFile != files.end(); iterFile++) {
|
||||
const StringToClassScopePtrVecMap &classes =
|
||||
iterFile->second->getClasses();
|
||||
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
|
||||
iter != classes.end(); ++iter) {
|
||||
assert(iter->second.size() == 1);
|
||||
iter->second[0]->setSystem();
|
||||
assert(!s_classes[iter->first]);
|
||||
s_classes[iter->first] = iter->second[0];
|
||||
}
|
||||
|
||||
const auto& functions = file.second->getFunctions();
|
||||
for (const auto& func : functions) {
|
||||
func.second->setSystem();
|
||||
ar->addSystemFunction(func.second);
|
||||
FunctionScope::RecordFunctionInfo(func.first, func.second);
|
||||
const StringToFunctionScopePtrMap &functions =
|
||||
iterFile->second->getFunctions();
|
||||
for (StringToFunctionScopePtrMap::const_iterator iter = functions.begin();
|
||||
iter != functions.end(); ++iter) {
|
||||
iter->second->setSystem();
|
||||
s_functions[iter->first] = iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AnalysisResultPtr BuiltinSymbols::LoadGlobalSymbols(const char *fileName) {
|
||||
AnalysisResultPtr ar(new AnalysisResult());
|
||||
string phpBaseName = "/system/globals/";
|
||||
phpBaseName += fileName;
|
||||
string phpFileName = Option::GetSystemRoot() + phpBaseName;
|
||||
const char *baseName = s_strings.add(phpBaseName.c_str());
|
||||
fileName = s_strings.add(phpFileName.c_str());
|
||||
|
||||
try {
|
||||
Scanner scanner(fileName, Option::GetScannerType());
|
||||
Compiler::Parser parser(scanner, baseName, ar);
|
||||
if (!parser.parse()) {
|
||||
assert(false);
|
||||
Logger::Error("Unable to parse file %s: %s", fileName,
|
||||
parser.getMessage().c_str());
|
||||
}
|
||||
} catch (FileOpenException &e) {
|
||||
Logger::Error("%s", e.getMessage().c_str());
|
||||
}
|
||||
ar->analyzeProgram(true);
|
||||
ar->inferTypes();
|
||||
return ar;
|
||||
}
|
||||
|
||||
void BuiltinSymbols::LoadFunctions(AnalysisResultPtr ar,
|
||||
StringToFunctionScopePtrMap &functions) {
|
||||
assert(Loaded);
|
||||
functions.insert(s_functions.begin(), s_functions.end());
|
||||
}
|
||||
|
||||
void BuiltinSymbols::LoadClasses(AnalysisResultPtr ar,
|
||||
StringToClassScopePtrMap &classes) {
|
||||
assert(Loaded);
|
||||
classes.insert(s_classes.begin(), s_classes.end());
|
||||
}
|
||||
|
||||
void BuiltinSymbols::LoadVariables(AnalysisResultPtr ar,
|
||||
VariableTablePtr variables) {
|
||||
assert(Loaded);
|
||||
if (s_variables) {
|
||||
variables->import(s_variables);
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltinSymbols::LoadConstants(AnalysisResultPtr ar,
|
||||
ConstantTablePtr constants) {
|
||||
assert(Loaded);
|
||||
if (s_constants) {
|
||||
constants->import(s_constants);
|
||||
}
|
||||
}
|
||||
|
||||
ConstantTablePtr BuiltinSymbols::LoadSystemConstants() {
|
||||
AnalysisResultPtr ar = LoadGlobalSymbols("constants.php");
|
||||
const auto &fileScopes = ar->getAllFilesVector();
|
||||
if (!fileScopes.empty()) {
|
||||
return fileScopes[0]->getConstants();
|
||||
}
|
||||
throw std::runtime_error("LoadSystemConstants failed");
|
||||
}
|
||||
|
||||
void BuiltinSymbols::LoadSuperGlobals() {
|
||||
if (s_superGlobals.empty()) {
|
||||
s_superGlobals["_SERVER"] = Type::Variant;
|
||||
|
||||
@@ -24,17 +24,16 @@
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_EXTENDED_BOOST_TYPES(Type);
|
||||
DECLARE_BOOST_TYPES(Type);
|
||||
DECLARE_BOOST_TYPES(AnalysisResult);
|
||||
DECLARE_EXTENDED_BOOST_TYPES(FunctionScope);
|
||||
DECLARE_EXTENDED_BOOST_TYPES(ClassScope);
|
||||
DECLARE_BOOST_TYPES(FunctionScope);
|
||||
DECLARE_BOOST_TYPES(ClassScope);
|
||||
DECLARE_BOOST_TYPES(VariableTable);
|
||||
DECLARE_BOOST_TYPES(ConstantTable);
|
||||
|
||||
class BuiltinSymbols {
|
||||
public:
|
||||
static bool Loaded;
|
||||
static AnalysisResultPtr s_systemAr;
|
||||
|
||||
static bool Load(AnalysisResultPtr ar);
|
||||
|
||||
@@ -47,6 +46,11 @@ public:
|
||||
static void LoadConstants(AnalysisResultPtr ar,
|
||||
ConstantTablePtr constants);
|
||||
|
||||
/*
|
||||
* Load system/globals/constants.php.
|
||||
*/
|
||||
static ConstantTablePtr LoadSystemConstants();
|
||||
|
||||
/**
|
||||
* Testing whether a variable is a PHP superglobal.
|
||||
*/
|
||||
@@ -56,24 +60,35 @@ public:
|
||||
static bool IsDeclaredDynamic(const std::string& name);
|
||||
static void LoadSuperGlobals();
|
||||
|
||||
static StringToFunctionScopePtrMap s_functions;
|
||||
static StringToClassScopePtrMap s_classes;
|
||||
static VariableTablePtr s_variables;
|
||||
static ConstantTablePtr s_constants;
|
||||
static AnalysisResultPtr s_systemAr;
|
||||
|
||||
static const char *const GlobalNames[];
|
||||
static int NumGlobalNames();
|
||||
private:
|
||||
static StringBag s_strings;
|
||||
static const char *SystemClasses[];
|
||||
|
||||
static AnalysisResultPtr LoadGlobalSymbols(const char *fileName);
|
||||
|
||||
static StringToTypePtrMap s_superGlobals;
|
||||
|
||||
static std::set<std::string> s_declaredDynamic;
|
||||
|
||||
static void *s_handle_main;
|
||||
|
||||
static FunctionScopePtr ImportFunctionScopePtr(AnalysisResultPtr ar,
|
||||
ClassInfo *cls,
|
||||
ClassInfo::MethodInfo *method);
|
||||
static void ImportExtFunctions(AnalysisResultPtr ar,
|
||||
StringToFunctionScopePtrMap &map,
|
||||
ClassInfo *cls);
|
||||
static void ImportExtFunctions(AnalysisResultPtr ar,
|
||||
FunctionScopePtrVec &vec,
|
||||
ClassInfo *cls);
|
||||
static void ImportExtMethods(AnalysisResultPtr ar,
|
||||
FunctionScopePtrVec &vec,
|
||||
ClassInfo *cls);
|
||||
static void ImportExtProperties(AnalysisResultPtr ar,
|
||||
VariableTablePtr dest,
|
||||
ClassInfo *cls);
|
||||
|
||||
@@ -14,16 +14,15 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "hphp/compiler/code_generator.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/compiler/statement/statement_list.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
#include "hphp/compiler/analysis/analysis_result.h"
|
||||
#include "hphp/compiler/analysis/variable_table.h"
|
||||
#include "hphp/runtime/base/zend-printf.h"
|
||||
#include "hphp/util/util.h"
|
||||
#include "hphp/util/hash.h"
|
||||
#include <boost/format.hpp>
|
||||
@@ -425,171 +424,3 @@ int CodeGenerator::ClassScopeCompare::cmp(const ClassScopeRawPtr &p1,
|
||||
if (d) return d;
|
||||
return strcasecmp(p1->getName().c_str(), p2->getName().c_str());
|
||||
}
|
||||
|
||||
void CodeGenerator::printObjectHeader(const std::string className,
|
||||
int numProperties) {
|
||||
std::string prefixedClassName;
|
||||
prefixedClassName.append(m_astPrefix);
|
||||
prefixedClassName.append(className);
|
||||
m_astClassNames.push_back(prefixedClassName);
|
||||
printf("O:%d:\"%s\":%d:{",
|
||||
(int)prefixedClassName.length(), prefixedClassName.c_str(), numProperties);
|
||||
}
|
||||
|
||||
void CodeGenerator::printObjectFooter() {
|
||||
printf("}");
|
||||
m_astClassNames.pop_back();
|
||||
}
|
||||
|
||||
void CodeGenerator::printPropertyHeader(const std::string propertyName) {
|
||||
auto prefixedClassName = m_astClassNames.back();
|
||||
auto len = 2+prefixedClassName.length()+propertyName.length();
|
||||
printf("s:%d:\"", (int)len);
|
||||
*m_out << (char)0;
|
||||
printf("%s", prefixedClassName.c_str());
|
||||
*m_out << (char)0;
|
||||
printf("%s\";", propertyName.c_str());
|
||||
}
|
||||
|
||||
void CodeGenerator::printNull() {
|
||||
printf("N;");
|
||||
}
|
||||
|
||||
void CodeGenerator::printBool(bool value) {
|
||||
printf("b:%d;", value ? 1 : 0);
|
||||
}
|
||||
|
||||
void CodeGenerator::printValue(double v) {
|
||||
*m_out << "d:";
|
||||
if (std::isnan(v)) {
|
||||
*m_out << "NAN";
|
||||
} else if (std::isinf(v)) {
|
||||
if (v < 0) *m_out << '-';
|
||||
*m_out << "INF";
|
||||
} else {
|
||||
char *buf;
|
||||
if (v == 0.0) v = 0.0; // so to avoid "-0" output
|
||||
vspprintf(&buf, 0, "%.*H", 14, v);
|
||||
m_out->write(buf, strlen(buf));
|
||||
free(buf);
|
||||
}
|
||||
*m_out << ';';
|
||||
}
|
||||
|
||||
void CodeGenerator::printValue(int32_t value) {
|
||||
printf("i:%d;", value);
|
||||
}
|
||||
|
||||
void CodeGenerator::printValue(int64_t value) {
|
||||
printf("i:%" PRId64 ";", value);
|
||||
}
|
||||
|
||||
void CodeGenerator::printValue(std::string value) {
|
||||
printf("s:%d:\"", (int)value.length());
|
||||
getStream()->write(value.c_str(), value.length());
|
||||
printf("\";");
|
||||
}
|
||||
|
||||
void CodeGenerator::printModifierVector(std::string value) {
|
||||
printf("V:9:\"HH\\Vector\":1:{");
|
||||
printObjectHeader("Modifier", 1);
|
||||
printPropertyHeader("name");
|
||||
printValue(value);
|
||||
printObjectFooter();
|
||||
printf("}");
|
||||
}
|
||||
|
||||
void CodeGenerator::printTypeExpression(std::string value) {
|
||||
printObjectHeader("TypeExpression", 1);
|
||||
printPropertyHeader("name");
|
||||
printValue(value);
|
||||
printObjectFooter();
|
||||
}
|
||||
|
||||
void CodeGenerator::printExpression(ExpressionPtr expression, bool isRef) {
|
||||
if (isRef) {
|
||||
printObjectHeader("UnaryOpExpression", 3);
|
||||
printPropertyHeader("expression");
|
||||
expression->outputCodeModel(*this);
|
||||
printPropertyHeader("operation");
|
||||
printValue(PHP_REFERENCE_OP);
|
||||
printPropertyHeader("sourceLocation");
|
||||
printLocation(expression->getLocation());
|
||||
printObjectFooter();
|
||||
} else {
|
||||
expression->outputCodeModel(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::printExpressionVector(ExpressionListPtr el) {
|
||||
auto count = el == nullptr ? 0 : el->getCount();
|
||||
printf("V:9:\"HH\\Vector\":%d:{", count);
|
||||
if (count > 0) {
|
||||
el->outputCodeModel(*this);
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
|
||||
void CodeGenerator::printExpressionVector(ExpressionPtr e) {
|
||||
if (e->is(Expression::KindOfExpressionList)) {
|
||||
auto sl = static_pointer_cast<ExpressionList>(e);
|
||||
printExpressionVector(sl);
|
||||
} else {
|
||||
printf("V:9:\"HH\\Vector\":1:{");
|
||||
e->outputCodeModel(*this);
|
||||
printf("}");
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::printAsBlock(StatementPtr s) {
|
||||
if (s != nullptr && s->is(Statement::KindOfBlockStatement)) {
|
||||
s->outputCodeModel(*this);
|
||||
} else {
|
||||
auto numProps = s == nullptr ? 1 : 2;
|
||||
printObjectHeader("BlockStatement", numProps);
|
||||
printPropertyHeader("statements");
|
||||
printStatementVector(s);
|
||||
if (s != nullptr) {
|
||||
printPropertyHeader("sourceLocation");
|
||||
printLocation(s->getLocation());
|
||||
}
|
||||
printObjectFooter();
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::printStatementVector(StatementListPtr sl) {
|
||||
printf("V:9:\"HH\\Vector\":%d:{", sl->getCount());
|
||||
if (sl->getCount() > 0) {
|
||||
sl->outputCodeModel(*this);
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
|
||||
void CodeGenerator::printStatementVector(StatementPtr s) {
|
||||
if (s == nullptr) {
|
||||
printf("V:9:\"HH\\Vector\":0:{}");
|
||||
} else if (s->is(Statement::KindOfStatementList)) {
|
||||
auto sl = static_pointer_cast<StatementList>(s);
|
||||
printStatementVector(sl);
|
||||
} else {
|
||||
printf("V:9:\"HH\\Vector\":1:{");
|
||||
s->outputCodeModel(*this);
|
||||
printf("}");
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::printLocation(LocationPtr location) {
|
||||
if (location == nullptr) return;
|
||||
printObjectHeader("SourceLocation", 4);
|
||||
printPropertyHeader("startLine");
|
||||
printValue(location->line0);
|
||||
printPropertyHeader("endLine");
|
||||
printValue(location->line1);
|
||||
printPropertyHeader("startColumn");
|
||||
printValue(location->char0);
|
||||
printPropertyHeader("endColumn");
|
||||
printValue(location->char1);
|
||||
printObjectFooter();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,16 +24,12 @@ namespace HPHP {
|
||||
|
||||
DECLARE_BOOST_TYPES(AnalysisResult);
|
||||
DECLARE_BOOST_TYPES(Statement);
|
||||
DECLARE_BOOST_TYPES(StatementList);
|
||||
DECLARE_BOOST_TYPES(Construct);
|
||||
DECLARE_BOOST_TYPES(BlockScope);
|
||||
DECLARE_EXTENDED_BOOST_TYPES(ClassScope);
|
||||
DECLARE_BOOST_TYPES(ClassScope);
|
||||
DECLARE_BOOST_TYPES(FunctionScope);
|
||||
DECLARE_BOOST_TYPES(FileScope);
|
||||
DECLARE_BOOST_TYPES(LoopStatement);
|
||||
DECLARE_BOOST_TYPES(Location);
|
||||
DECLARE_BOOST_TYPES(Expression);
|
||||
DECLARE_BOOST_TYPES(ExpressionList);
|
||||
|
||||
class CodeGenerator {
|
||||
public:
|
||||
@@ -49,7 +45,6 @@ public:
|
||||
SystemCPP, // special mode for generating builtin classes
|
||||
TextHHBC, // HHBC dump in human-readable format
|
||||
BinaryHHBC, // serialized HHBC
|
||||
CodeModel, // serialized Code Model classes
|
||||
};
|
||||
|
||||
enum Stream {
|
||||
@@ -270,37 +265,12 @@ public:
|
||||
FileScopeRawPtr getLiteralScope() const {
|
||||
return m_literalScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for printing AST nodes in PHP serialize() format.
|
||||
*/
|
||||
void printObjectHeader(const std::string className, int numProperties);
|
||||
void printPropertyHeader(const std::string propertyName);
|
||||
void printObjectFooter();
|
||||
void printNull();
|
||||
void printBool(bool value);
|
||||
void printValue(double value);
|
||||
void printValue(int32_t value);
|
||||
void printValue(int64_t value);
|
||||
void printValue(std::string value);
|
||||
void printModifierVector(std::string value);
|
||||
void printTypeExpression(std::string value);
|
||||
void printExpression(ExpressionPtr expression, bool isRef);
|
||||
void printExpressionVector(ExpressionListPtr el);
|
||||
void printExpressionVector(ExpressionPtr e);
|
||||
void printAsBlock(StatementPtr s);
|
||||
void printStatementVector(StatementListPtr sl);
|
||||
void printStatementVector(StatementPtr s);
|
||||
void printLocation(LocationPtr location);
|
||||
void setAstClassPrefix(const std::string &prefix) { m_astPrefix = prefix; }
|
||||
private:
|
||||
std::string m_filename;
|
||||
Stream m_curStream;
|
||||
std::ostream *m_streams[StreamCount];
|
||||
std::ostream *m_out;
|
||||
Output m_output;
|
||||
std::string m_astPrefix;
|
||||
std::vector<std::string> m_astClassNames;
|
||||
bool m_verbose;
|
||||
|
||||
int m_indentation[StreamCount];
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
// This file is @generated by tools/code-model/GenerateEnums.sh
|
||||
|
||||
#ifndef incl_HPHP_CODE_MODEL_ENUMS_H_
|
||||
#define incl_HPHP_CODE_MODEL_ENUMS_H_
|
||||
|
||||
namespace HPHP {
|
||||
/** The kinds of operations that IBinaryOpExpressions can perform. */
|
||||
enum CodeModelBinaryOperator {
|
||||
PHP_AND_ASSIGN = 1,
|
||||
PHP_AND = 2,
|
||||
PHP_ARRAY_ELEMENT = 3,
|
||||
PHP_ARRAY_PAIR = 4,
|
||||
PHP_ASSIGNMENT = 5,
|
||||
PHP_BOOLEAN_AND = 6,
|
||||
PHP_BOOLEAN_OR = 7,
|
||||
PHP_CAST = 8,
|
||||
PHP_CONCAT_ASSIGN = 9,
|
||||
PHP_CONCAT = 10,
|
||||
PHP_DIVIDE_ASSIGN = 11,
|
||||
PHP_DIVIDE = 12,
|
||||
PHP_INSTANCEOF = 13,
|
||||
PHP_IS_EQUAL = 14,
|
||||
PHP_IS_GREATER = 15,
|
||||
PHP_IS_GREATER_OR_EQUAL = 16,
|
||||
PHP_IS_IDENTICAL = 17,
|
||||
PHP_IS_NOT_IDENTICAL = 18,
|
||||
PHP_IS_NOT_EQUAL = 19,
|
||||
PHP_IS_SMALLER = 20,
|
||||
PHP_IS_SMALLER_OR_EQUAL = 21,
|
||||
PHP_LOGICAL_AND = 22,
|
||||
PHP_LOGICAL_OR = 23,
|
||||
PHP_LOGICAL_XOR = 24,
|
||||
PHP_MINUS_ASSIGN = 25,
|
||||
PHP_MINUS = 26,
|
||||
PHP_MODULUS_ASSIGN = 27,
|
||||
PHP_MODULUS = 28,
|
||||
PHP_MULTIPLY_ASSIGN = 29,
|
||||
PHP_MULTIPLY = 30,
|
||||
PHP_OR_ASSIGN = 31,
|
||||
PHP_OR = 32,
|
||||
PHP_PLUS_ASSIGN = 33,
|
||||
PHP_PLUS = 34,
|
||||
PHP_SHIFT_LEFT_ASSIGN = 35,
|
||||
PHP_SHIFT_LEFT = 36,
|
||||
PHP_SHIFT_RIGHT_ASSIGN = 37,
|
||||
PHP_SHIFT_RIGHT = 38,
|
||||
PHP_XOR_ASSIGN = 39,
|
||||
PHP_XOR = 40,
|
||||
};
|
||||
|
||||
/** The kinds of operations that IUnaryOpExpressions can perform. */
|
||||
enum CodeModelUnaryOperator {
|
||||
PHP_ARRAY_CAST_OP = 1,
|
||||
PHP_ARRAY_APPEND_POINT_OP = 2,
|
||||
PHP_AWAIT_OP = 3,
|
||||
PHP_BOOL_CAST_OP = 4,
|
||||
PHP_BITWISE_NOT_OP = 5,
|
||||
PHP_CLONE_OP = 6,
|
||||
PHP_DYNAMIC_VARIABLE_OP = 7,
|
||||
PHP_ERROR_CONTROL_OP = 8,
|
||||
PHP_FLOAT_CAST_OP = 9,
|
||||
PHP_INCLUDE_OP = 10,
|
||||
PHP_INCLUDE_ONCE_OP = 11,
|
||||
PHP_INT_CAST_OP = 12,
|
||||
PHP_MINUS_OP = 13,
|
||||
PHP_NOT_OP = 14,
|
||||
PHP_OBJECT_CAST_OP = 15,
|
||||
PHP_PLUS_OP = 16,
|
||||
PHP_POST_DECREMENT_OP = 17,
|
||||
PHP_POST_INCREMENT_OP = 18,
|
||||
PHP_PRE_DECREMENT_OP = 19,
|
||||
PHP_PRE_INCREMENT_OP = 20,
|
||||
PHP_PRINT_OP = 21,
|
||||
PHP_REFERENCE_OP = 22,
|
||||
PHP_REQUIRE_OP = 23,
|
||||
PHP_REQUIRE_ONCE_OP = 24,
|
||||
PHP_STRING_CAST_OP = 25,
|
||||
PHP_UNSET_CAST_OP = 26,
|
||||
};
|
||||
|
||||
/** Enumerates the kinds of trait require statements. */
|
||||
enum CodeModelRequireKind {
|
||||
PHP_EXTENDS = 1,
|
||||
PHP_IMPLEMENTS = 2,
|
||||
};
|
||||
|
||||
/** Enumerates the kinds of type declaration statements. */
|
||||
enum CodeModelTypeKind {
|
||||
PHP_CLASS = 1,
|
||||
PHP_INTERFACE = 2,
|
||||
PHP_TRAIT = 3,
|
||||
};
|
||||
|
||||
/** The sort order to use when grouping query results */
|
||||
enum CodeModelOrder {
|
||||
PHP_NOT_SPECIFIED = 1,
|
||||
PHP_ASCENDING = 2,
|
||||
PHP_DESCENDING = 3,
|
||||
};
|
||||
|
||||
}
|
||||
#endif // incl_HPHP_CODE_MODEL_ENUMS_H_
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/parser/parser.h"
|
||||
#include "hphp/compiler/builtin_symbols.h"
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/util/logger.h"
|
||||
#include "hphp/util/db-conn.h"
|
||||
#include "hphp/util/exception.h"
|
||||
@@ -344,8 +344,8 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
if (vm.count("version")) {
|
||||
#ifdef HHVM_VERSION
|
||||
#undef HHVM_VERSION
|
||||
#ifdef HPHP_VERSION
|
||||
#undef HPHP_VERSION
|
||||
#endif
|
||||
|
||||
#ifdef HPHP_COMPILER_STR
|
||||
@@ -358,7 +358,7 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
|
||||
#define HPHP_COMPILER_STR "HipHop Compiler v"
|
||||
#endif
|
||||
|
||||
#define HHVM_VERSION(v) cout << HPHP_COMPILER_STR #v << "\n";
|
||||
#define HPHP_VERSION(v) cout << HPHP_COMPILER_STR #v << "\n";
|
||||
#include "../version" // nolint
|
||||
|
||||
cout << "Compiler: " << kCompilerId << "\n";
|
||||
@@ -484,8 +484,6 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
|
||||
Option::ParseTimeOpts = false;
|
||||
}
|
||||
|
||||
initialize_hhbbc_options();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -542,12 +540,6 @@ int process(const CompilerOptions &po) {
|
||||
|
||||
bool isPickledPHP = (po.target == "php" && po.format == "pickled");
|
||||
if (!isPickledPHP) {
|
||||
bool wp = Option::WholeProgram;
|
||||
Option::WholeProgram = false;
|
||||
BuiltinSymbols::s_systemAr = ar;
|
||||
hphp_process_init();
|
||||
BuiltinSymbols::s_systemAr.reset();
|
||||
Option::WholeProgram = wp;
|
||||
if (po.target == "hhbc" && !Option::WholeProgram) {
|
||||
// We're trying to produce the same bytecode as runtime parsing.
|
||||
// There's nothing to do.
|
||||
@@ -555,7 +547,9 @@ int process(const CompilerOptions &po) {
|
||||
if (!BuiltinSymbols::Load(ar)) {
|
||||
return false;
|
||||
}
|
||||
ar->loadBuiltins();
|
||||
}
|
||||
hphp_process_init();
|
||||
}
|
||||
|
||||
{
|
||||
@@ -602,7 +596,6 @@ int process(const CompilerOptions &po) {
|
||||
return 1;
|
||||
}
|
||||
if (Option::WholeProgram || po.target == "analyze") {
|
||||
Timer timer(Timer::WallTime, "analyzeProgram");
|
||||
ar->analyzeProgram();
|
||||
}
|
||||
}
|
||||
@@ -807,7 +800,6 @@ void hhbcTargetInit(const CompilerOptions &po, AnalysisResultPtr ar) {
|
||||
if (po.format.find("exe") != string::npos) {
|
||||
RuntimeOption::RepoCentralPath += ".hhbc";
|
||||
}
|
||||
unlink(RuntimeOption::RepoCentralPath.c_str());
|
||||
RuntimeOption::RepoLocalMode = "--";
|
||||
RuntimeOption::RepoDebugInfo = Option::RepoDebugInfo;
|
||||
RuntimeOption::RepoJournal = "memory";
|
||||
@@ -923,8 +915,6 @@ int runTarget(const CompilerOptions &po) {
|
||||
|
||||
cmd += buf;
|
||||
cmd += " -vRepo.Authoritative=true";
|
||||
if (getenv("HPHP_DUMP_BYTECODE")) cmd += " -vEval.DumpBytecode=1";
|
||||
if (getenv("HPHP_INTERP")) cmd += " -vEval.Jit=0";
|
||||
cmd += " -vRepo.Local.Mode=r- -vRepo.Local.Path=";
|
||||
}
|
||||
cmd += po.outputDir + '/' + po.program;
|
||||
|
||||
@@ -469,23 +469,9 @@ void Construct::parseTimeFatal(Compiler::ErrorType err, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
string msg;
|
||||
string_vsnprintf(msg, fmt, ap);
|
||||
Util::string_vsnprintf(msg, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (err != Compiler::NoError) Compiler::Error(err, shared_from_this());
|
||||
throw ParseTimeFatalException(m_loc->file, m_loc->line0, "%s", msg.c_str());
|
||||
}
|
||||
|
||||
void Construct::analysisTimeFatal(Compiler::ErrorType err,
|
||||
const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
string msg;
|
||||
string_vsnprintf(msg, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
assert(err != Compiler::NoError);
|
||||
Compiler::Error(err, shared_from_this());
|
||||
throw AnalysisTimeFatalException(m_loc->file, m_loc->line0,
|
||||
"%s [analysis]", msg.c_str());
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef incl_HPHP_CONSTRUCT_H_
|
||||
#define incl_HPHP_CONSTRUCT_H_
|
||||
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/compiler/code_generator.h"
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/compiler/analysis/block_scope.h"
|
||||
@@ -166,6 +166,10 @@ public:
|
||||
void clearKilled() { m_flags.killed = false; }
|
||||
bool isKilled() const { return m_flags.killed; }
|
||||
|
||||
void setChildOfYield() { m_flags.childOfYield = true; }
|
||||
void clearChildOfYield() { m_flags.childOfYield = false; }
|
||||
bool isChildOfYield() const { return m_flags.childOfYield; }
|
||||
|
||||
BlockScopeRawPtr getScope() const { return m_blockScope; }
|
||||
void setBlockScope(BlockScopeRawPtr scope) { m_blockScope = scope; }
|
||||
FileScopeRawPtr getFileScope() const {
|
||||
@@ -180,8 +184,6 @@ public:
|
||||
void resetScope(BlockScopeRawPtr scope, bool resetOrigScope=false);
|
||||
void parseTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
|
||||
ATTRIBUTE_PRINTF(3,4);
|
||||
void analysisTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
|
||||
ATTRIBUTE_PRINTF(3,4);
|
||||
virtual int getLocalEffects() const { return UnknownEffect;}
|
||||
int getChildrenEffects() const;
|
||||
int getContainedEffects() const;
|
||||
@@ -197,8 +199,7 @@ public:
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::shared_ptr<T> Clone(std::shared_ptr<T> constr,
|
||||
BlockScopePtr scope) {
|
||||
std::shared_ptr<T> Clone(std::shared_ptr<T> constr, BlockScopePtr scope) {
|
||||
if (constr) {
|
||||
constr = constr->clone();
|
||||
constr->resetScope(scope);
|
||||
@@ -246,11 +247,6 @@ public:
|
||||
const AstWalkerStateVec &start,
|
||||
ConstructPtr endBefore, ConstructPtr endAfter);
|
||||
|
||||
/**
|
||||
* Generates a serialized Code Model corresponding to this AST.
|
||||
*/
|
||||
virtual void outputCodeModel(CodeGenerator &cg) = 0;
|
||||
|
||||
/**
|
||||
* Called when generating code.
|
||||
*/
|
||||
@@ -303,6 +299,7 @@ private:
|
||||
unsigned killed : 1;
|
||||
unsigned refCounted : 2; // high bit indicates whether its valid
|
||||
unsigned inited : 2; // high bit indicates whether its valid
|
||||
unsigned childOfYield : 1; // parent node is yield
|
||||
} m_flags;
|
||||
};
|
||||
protected:
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "hphp/compiler/expression/scalar_expression.h"
|
||||
#include "hphp/compiler/analysis/variable_table.h"
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/expression/static_member_expression.h"
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
@@ -389,42 +388,6 @@ ExpressionPtr ArrayElementExpression::unneeded() {
|
||||
return Expression::unneeded();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ArrayElementExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
if (Option::ConvertSuperGlobals && m_global && !m_dynamicGlobal &&
|
||||
getScope() && (getScope()->is(BlockScope::ProgramScope) ||
|
||||
getScope()-> getVariables()->
|
||||
isConvertibleSuperGlobal(m_globalName))) {
|
||||
cg.printObjectHeader("SimpleVariableExpression", 2);
|
||||
cg.printPropertyHeader("name");
|
||||
cg.printValue(m_globalName);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
} else if (m_offset) {
|
||||
cg.printObjectHeader("BinaryOpExpression", 4);
|
||||
cg.printPropertyHeader("expression1");
|
||||
m_variable->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("expression2");
|
||||
cg.printExpression(m_offset, false);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_ARRAY_ELEMENT);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
} else {
|
||||
cg.printObjectHeader("UnaryOpExpression", 3);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_variable->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_ARRAY_APPEND_POINT_OP);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "hphp/compiler/expression/array_pair_expression.h"
|
||||
#include "hphp/compiler/expression/scalar_expression.h"
|
||||
#include "hphp/compiler/expression/unary_op_expression.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/parser/hphp.tab.hpp"
|
||||
|
||||
using namespace HPHP;
|
||||
@@ -123,25 +122,6 @@ bool ArrayPairExpression::canonCompare(ExpressionPtr e) const {
|
||||
return m_ref == a->m_ref;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ArrayPairExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
if (m_name) {
|
||||
cg.printObjectHeader("BinaryOpExpression", 4);
|
||||
cg.printPropertyHeader("expression1");
|
||||
m_name->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("expression2");
|
||||
cg.printExpression(m_value, m_ref);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_ARRAY_PAIR);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
} else {
|
||||
cg.printExpression(m_value, m_ref);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
#include "hphp/compiler/expression/unary_op_expression.h"
|
||||
#include "hphp/parser/hphp.tab.hpp"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/analysis/class_scope.h"
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
@@ -307,21 +306,6 @@ TypePtr AssignmentExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return inferAssignmentTypes(ar, type, coerce, m_variable, m_value);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AssignmentExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("BinaryOpExpression", 4);
|
||||
cg.printPropertyHeader("expression1");
|
||||
m_variable->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("expression2");
|
||||
cg.printExpression(m_value, m_ref);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_ASSIGNMENT);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "hphp/compiler/expression/await_expression.h"
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
@@ -83,18 +82,6 @@ TypePtr AwaitExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return Type::Variant;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AwaitExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("UnaryOpExpression", 3);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_AWAIT_OP);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "hphp/parser/hphp.tab.hpp"
|
||||
#include "hphp/compiler/expression/scalar_expression.h"
|
||||
#include "hphp/compiler/expression/constant_expression.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/runtime/base/complex-types.h"
|
||||
#include "hphp/runtime/base/type-conversions.h"
|
||||
#include "hphp/runtime/base/builtin-functions.h"
|
||||
@@ -33,7 +32,6 @@
|
||||
#include "hphp/compiler/expression/simple_variable.h"
|
||||
#include "hphp/compiler/statement/loop_statement.h"
|
||||
#include "hphp/runtime/base/tv-arith.h"
|
||||
#include "hphp/runtime/vm/runtime.h"
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
@@ -67,7 +65,7 @@ BinaryOpExpression::BinaryOpExpression
|
||||
break;
|
||||
case T_COLLECTION: {
|
||||
std::string s = m_exp1->getLiteralString();
|
||||
Collection::Type cType = Collection::InvalidType;
|
||||
int cType = 0;
|
||||
if (strcasecmp(s.c_str(), "vector") == 0) {
|
||||
cType = Collection::VectorType;
|
||||
} else if (strcasecmp(s.c_str(), "map") == 0) {
|
||||
@@ -78,12 +76,6 @@ BinaryOpExpression::BinaryOpExpression
|
||||
cType = Collection::SetType;
|
||||
} else if (strcasecmp(s.c_str(), "pair") == 0) {
|
||||
cType = Collection::PairType;
|
||||
} else if (strcasecmp(s.c_str(), "frozenvector") == 0) {
|
||||
cType = Collection::FrozenVectorType;
|
||||
} else if (strcasecmp(s.c_str(), "frozenmap") == 0) {
|
||||
cType = Collection::FrozenMapType;
|
||||
} else if (strcasecmp(s.c_str(), "frozenset") == 0) {
|
||||
cType = Collection::FrozenSetType;
|
||||
}
|
||||
ExpressionListPtr el = static_pointer_cast<ExpressionList>(m_exp2);
|
||||
el->setCollectionType(cType);
|
||||
@@ -484,9 +476,6 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
|
||||
ExpressionPtr aExp = m_exp1;
|
||||
ExpressionPtr bExp = binOpExp->m_exp1;
|
||||
ExpressionPtr cExp = binOpExp->m_exp2;
|
||||
if (aExp->isArray() || bExp->isArray() || cExp->isArray()) {
|
||||
break;
|
||||
}
|
||||
m_exp1 = binOpExp = Clone(binOpExp);
|
||||
m_exp2 = cExp;
|
||||
binOpExp->m_exp1 = aExp;
|
||||
@@ -547,9 +536,6 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
|
||||
*result.asCell() = cellBitXor(*v1.asCell(), *v2.asCell());
|
||||
break;
|
||||
case '.':
|
||||
if (v1.isArray() || v2.isArray()) {
|
||||
return ExpressionPtr();
|
||||
}
|
||||
result = concat(v1.toString(), v2.toString());
|
||||
break;
|
||||
case T_IS_IDENTICAL:
|
||||
@@ -816,7 +802,7 @@ TypePtr BinaryOpExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
case T_COLLECTION:
|
||||
et1 = Type::Any;
|
||||
et2 = Type::Any;
|
||||
rt = Type::CreateObjectType(m_exp1->getLiteralString());
|
||||
rt = Type::Object;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
@@ -925,76 +911,6 @@ TypePtr BinaryOpExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return rt;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BinaryOpExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
if (m_op == T_COLLECTION) {
|
||||
cg.printObjectHeader("CollectionInitializerExpression", 3);
|
||||
cg.printPropertyHeader("collection");
|
||||
m_exp1->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("arguments");
|
||||
cg.printExpressionVector(static_pointer_cast<ExpressionList>(m_exp2));
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
return;
|
||||
}
|
||||
|
||||
cg.printObjectHeader("BinaryOpExpression", 4);
|
||||
cg.printPropertyHeader("expression1");
|
||||
m_exp1->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("expression2");
|
||||
m_exp2->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("operation");
|
||||
|
||||
int op = 0;
|
||||
switch (m_op) {
|
||||
case T_PLUS_EQUAL: op = PHP_PLUS_ASSIGN; break;
|
||||
case T_MINUS_EQUAL: op = PHP_MINUS_ASSIGN; break;
|
||||
case T_MUL_EQUAL: op = PHP_MULTIPLY_ASSIGN; break;
|
||||
case T_DIV_EQUAL: op = PHP_DIVIDE_ASSIGN; break;
|
||||
case T_CONCAT_EQUAL: op = PHP_CONCAT_ASSIGN; break;
|
||||
case T_MOD_EQUAL: op = PHP_MODULUS_ASSIGN; break;
|
||||
case T_AND_EQUAL: op = PHP_AND_ASSIGN; break;
|
||||
case T_OR_EQUAL: op = PHP_OR_ASSIGN; break;
|
||||
case T_XOR_EQUAL: op = PHP_XOR_ASSIGN; break;
|
||||
case T_SL_EQUAL: op = PHP_SHIFT_LEFT_ASSIGN; break;
|
||||
case T_SR_EQUAL: op = PHP_SHIFT_RIGHT_ASSIGN; break;
|
||||
case T_BOOLEAN_OR: op = PHP_BOOLEAN_OR; break;
|
||||
case T_BOOLEAN_AND: op = PHP_BOOLEAN_AND; break;
|
||||
case T_LOGICAL_OR: op = PHP_LOGICAL_OR; break;
|
||||
case T_LOGICAL_AND: op = PHP_LOGICAL_AND; break;
|
||||
case T_LOGICAL_XOR: op = PHP_LOGICAL_XOR; break;
|
||||
case '|': op = PHP_OR; break;
|
||||
case '&': op = PHP_AND; break;
|
||||
case '^': op = PHP_XOR; break;
|
||||
case '.': op = PHP_CONCAT; break;
|
||||
case '+': op = PHP_PLUS; break;
|
||||
case '-': op = PHP_MINUS; break;
|
||||
case '*': op = PHP_MULTIPLY; break;
|
||||
case '/': op = PHP_DIVIDE; break;
|
||||
case '%': op = PHP_MODULUS; break;
|
||||
case T_SL: op = PHP_SHIFT_LEFT; break;
|
||||
case T_SR: op = PHP_SHIFT_RIGHT; break;
|
||||
case T_IS_IDENTICAL: op = PHP_IS_IDENTICAL; break;
|
||||
case T_IS_NOT_IDENTICAL: op = PHP_IS_NOT_IDENTICAL; break;
|
||||
case T_IS_EQUAL: op = PHP_IS_EQUAL; break;
|
||||
case T_IS_NOT_EQUAL: op = PHP_IS_NOT_EQUAL; break;
|
||||
case '<': op = PHP_IS_SMALLER; break;
|
||||
case T_IS_SMALLER_OR_EQUAL: op = PHP_IS_SMALLER_OR_EQUAL; break;
|
||||
case '>': op = PHP_IS_GREATER; break;
|
||||
case T_IS_GREATER_OR_EQUAL: op = PHP_IS_GREATER_OR_EQUAL; break;
|
||||
case T_INSTANCEOF: op = PHP_INSTANCEOF; break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
cg.printValue(op);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -1075,3 +991,4 @@ bool BinaryOpExpression::isOpEqual() {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -221,18 +221,6 @@ bool ClassConstantExpression::canonCompare(ExpressionPtr e) const {
|
||||
m_className == static_cast<ClassConstantExpression*>(e.get())->m_className;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ClassConstantExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ClassPropertyExpression", 3);
|
||||
cg.printPropertyHeader("className");
|
||||
StaticClassName::outputCodeModel(cg);
|
||||
cg.printPropertyHeader("propertyName");
|
||||
cg.printValue(m_varName);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -46,7 +46,6 @@ public:
|
||||
bool isValid() const { return m_valid; }
|
||||
bool isDynamic() const;
|
||||
bool hasClass() const { return m_defScope != 0; }
|
||||
bool isColonColonClass() const { return m_varName == "class"; }
|
||||
private:
|
||||
std::string m_varName;
|
||||
BlockScope *m_defScope;
|
||||
|
||||
@@ -13,11 +13,8 @@
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/expression/closure_expression.h"
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include "folly/ScopeGuard.h"
|
||||
|
||||
#include "hphp/compiler/expression/parameter_expression.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/compiler/expression/simple_variable.h"
|
||||
@@ -27,79 +24,68 @@
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
using namespace HPHP;
|
||||
|
||||
TypePtr ClosureExpression::s_ClosureType =
|
||||
Type::CreateObjectType("closure"); // needs lower case
|
||||
|
||||
ClosureExpression::ClosureExpression(
|
||||
EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ClosureType type,
|
||||
FunctionStatementPtr func,
|
||||
ExpressionListPtr vars)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression))
|
||||
, m_type(type)
|
||||
, m_func(func)
|
||||
, m_captureState(m_type == ClosureType::Short ? CaptureState::Unknown
|
||||
: CaptureState::Known)
|
||||
{
|
||||
switch (m_type) {
|
||||
case ClosureType::Short:
|
||||
break;
|
||||
case ClosureType::Long:
|
||||
if (vars) initializeFromUseList(vars);
|
||||
break;
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constructors/destructors
|
||||
|
||||
void ClosureExpression::initializeFromUseList(ExpressionListPtr vars) {
|
||||
m_vars = ExpressionListPtr(
|
||||
new ExpressionList(vars->getScope(), vars->getLocation()));
|
||||
ClosureExpression::ClosureExpression
|
||||
(EXPRESSION_CONSTRUCTOR_PARAMETERS, FunctionStatementPtr func,
|
||||
ExpressionListPtr vars)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression)),
|
||||
m_func(func) {
|
||||
|
||||
// Because PHP is insane you can have a use variable with the same
|
||||
// name as a param name.
|
||||
// In that case, params win (which is different than zend but much easier)
|
||||
auto seenBefore = collectParamNames();
|
||||
if (vars) {
|
||||
m_vars = ExpressionListPtr
|
||||
(new ExpressionList(vars->getScope(), vars->getLocation()));
|
||||
// push the vars in reverse order, not retaining duplicates
|
||||
std::set<string> seenBefore;
|
||||
|
||||
for (int i = vars->getCount() - 1; i >= 0; i--) {
|
||||
ParameterExpressionPtr param(
|
||||
dynamic_pointer_cast<ParameterExpression>((*vars)[i]));
|
||||
assert(param);
|
||||
if (param->getName() == "this") {
|
||||
// "this" is automatically included.
|
||||
// Once we get rid of all the callsites, make this an error
|
||||
continue;
|
||||
// Because PHP is insane you can have a use variable with the same
|
||||
// name as a param name.
|
||||
// In that case, params win (which is different than zend but much easier)
|
||||
ExpressionListPtr bodyParams = m_func->getParams();
|
||||
if (bodyParams) {
|
||||
int nParams = bodyParams->getCount();
|
||||
for (int i = 0; i < nParams; i++) {
|
||||
ParameterExpressionPtr par(
|
||||
static_pointer_cast<ParameterExpression>((*bodyParams)[i]));
|
||||
seenBefore.insert(par->getName());
|
||||
}
|
||||
}
|
||||
if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
|
||||
seenBefore.insert(param->getName().c_str());
|
||||
m_vars->insertElement(param);
|
||||
|
||||
for (int i = vars->getCount() - 1; i >= 0; i--) {
|
||||
ParameterExpressionPtr param(
|
||||
dynamic_pointer_cast<ParameterExpression>((*vars)[i]));
|
||||
assert(param);
|
||||
if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
|
||||
seenBefore.insert(param->getName().c_str());
|
||||
m_vars->insertElement(param);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_vars) {
|
||||
m_values = ExpressionListPtr
|
||||
(new ExpressionList(m_vars->getScope(), m_vars->getLocation()));
|
||||
for (int i = 0; i < m_vars->getCount(); i++) {
|
||||
ParameterExpressionPtr param =
|
||||
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
|
||||
const string &name = param->getName();
|
||||
|
||||
SimpleVariablePtr var(new SimpleVariable(param->getScope(),
|
||||
param->getLocation(),
|
||||
name));
|
||||
if (param->isRef()) {
|
||||
var->setContext(RefValue);
|
||||
}
|
||||
m_values->addElement(var);
|
||||
}
|
||||
assert(m_vars->getCount() == m_values->getCount());
|
||||
}
|
||||
}
|
||||
|
||||
initializeValuesFromVars();
|
||||
}
|
||||
|
||||
void ClosureExpression::initializeValuesFromVars() {
|
||||
if (!m_vars) return;
|
||||
|
||||
m_values = ExpressionListPtr
|
||||
(new ExpressionList(m_vars->getScope(), m_vars->getLocation()));
|
||||
for (int i = 0; i < m_vars->getCount(); i++) {
|
||||
ParameterExpressionPtr param =
|
||||
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
|
||||
const string &name = param->getName();
|
||||
|
||||
SimpleVariablePtr var(new SimpleVariable(param->getScope(),
|
||||
param->getLocation(),
|
||||
name));
|
||||
if (param->isRef()) {
|
||||
var->setContext(RefValue);
|
||||
}
|
||||
m_values->addElement(var);
|
||||
}
|
||||
assert(m_vars->getCount() == m_values->getCount());
|
||||
}
|
||||
|
||||
ExpressionPtr ClosureExpression::clone() {
|
||||
@@ -146,65 +132,62 @@ void ClosureExpression::setNthKid(int n, ConstructPtr cp) {
|
||||
|
||||
void ClosureExpression::analyzeProgram(AnalysisResultPtr ar) {
|
||||
m_func->analyzeProgram(ar);
|
||||
if (m_vars) {
|
||||
m_values->analyzeProgram(ar);
|
||||
|
||||
if (m_vars) analyzeVars(ar);
|
||||
if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
|
||||
getFunctionScope()->addUse(m_func->getFunctionScope(),
|
||||
BlockScope::UseKindClosure);
|
||||
m_func->getFunctionScope()->setClosureVars(m_vars);
|
||||
|
||||
FunctionScopeRawPtr container =
|
||||
// closure function's variable table (not containing function's)
|
||||
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
|
||||
VariableTablePtr containing = getFunctionScope()->getVariables();
|
||||
for (int i = 0; i < m_vars->getCount(); i++) {
|
||||
ParameterExpressionPtr param =
|
||||
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
|
||||
const string &name = param->getName();
|
||||
{
|
||||
Symbol *containingSym = containing->addDeclaredSymbol(name, param);
|
||||
containingSym->setPassClosureVar();
|
||||
|
||||
Symbol *sym = variables->addDeclaredSymbol(name, param);
|
||||
sym->setClosureVar();
|
||||
sym->setDeclaration(ConstructPtr());
|
||||
if (param->isRef()) {
|
||||
sym->setRefClosureVar();
|
||||
sym->setUsed();
|
||||
} else {
|
||||
sym->clearRefClosureVar();
|
||||
sym->clearUsed();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
|
||||
// closure function's variable table (not containing function's)
|
||||
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
|
||||
for (int i = 0; i < m_vars->getCount(); i++) {
|
||||
ParameterExpressionPtr param =
|
||||
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
|
||||
const string &name = param->getName();
|
||||
|
||||
// so we can assign values to them, instead of seeing CVarRef
|
||||
Symbol *sym = variables->getSymbol(name);
|
||||
if (sym && sym->isParameter()) {
|
||||
sym->setLvalParam();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FunctionScopeRawPtr container =
|
||||
getFunctionScope()->getContainingNonClosureFunction();
|
||||
if (container && container->isStatic()) {
|
||||
m_func->getModifiers()->add(T_STATIC);
|
||||
}
|
||||
}
|
||||
|
||||
void ClosureExpression::analyzeVars(AnalysisResultPtr ar) {
|
||||
m_values->analyzeProgram(ar);
|
||||
|
||||
if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
|
||||
getFunctionScope()->addUse(m_func->getFunctionScope(),
|
||||
BlockScope::UseKindClosure);
|
||||
m_func->getFunctionScope()->setClosureVars(m_vars);
|
||||
|
||||
// closure function's variable table (not containing function's)
|
||||
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
|
||||
VariableTablePtr containing = getFunctionScope()->getVariables();
|
||||
for (int i = 0; i < m_vars->getCount(); i++) {
|
||||
ParameterExpressionPtr param =
|
||||
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
|
||||
const string &name = param->getName();
|
||||
{
|
||||
Symbol *containingSym = containing->addDeclaredSymbol(name, param);
|
||||
containingSym->setPassClosureVar();
|
||||
|
||||
Symbol *sym = variables->addDeclaredSymbol(name, param);
|
||||
sym->setClosureVar();
|
||||
sym->setDeclaration(ConstructPtr());
|
||||
if (param->isRef()) {
|
||||
sym->setRefClosureVar();
|
||||
sym->setUsed();
|
||||
} else {
|
||||
sym->clearRefClosureVar();
|
||||
sym->clearUsed();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
|
||||
// closure function's variable table (not containing function's)
|
||||
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
|
||||
for (int i = 0; i < m_vars->getCount(); i++) {
|
||||
ParameterExpressionPtr param =
|
||||
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
|
||||
const string &name = param->getName();
|
||||
|
||||
// so we can assign values to them, instead of seeing CVarRef
|
||||
Symbol *sym = variables->getSymbol(name);
|
||||
if (sym && sym->isParameter()) {
|
||||
sym->setLvalParam();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
@@ -268,72 +251,6 @@ TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return s_ClosureType;
|
||||
}
|
||||
|
||||
void ClosureExpression::setCaptureList(
|
||||
AnalysisResultPtr ar,
|
||||
const std::set<std::string>& captureNames) {
|
||||
assert(m_captureState == CaptureState::Unknown);
|
||||
m_captureState = CaptureState::Known;
|
||||
|
||||
bool usedThis = false;
|
||||
SCOPE_EXIT {
|
||||
/*
|
||||
* TODO: closures in a non-class scope should be neither static
|
||||
* nor non-static, but right now we don't really have this idea.
|
||||
*
|
||||
* This would allow not having to check for a $this or late bound
|
||||
* class in the closure object or on the ActRec when returning
|
||||
* from those closures.
|
||||
*
|
||||
* (We could also mark closures that don't use late static binding
|
||||
* with this flag to avoid checks on closures in member functions
|
||||
* when they use neither $this nor static::)
|
||||
*/
|
||||
if (!usedThis) m_func->getModifiers()->add(T_STATIC);
|
||||
};
|
||||
|
||||
if (captureNames.empty()) return;
|
||||
|
||||
m_vars = ExpressionListPtr(
|
||||
new ExpressionList(getOriginalScope(), getLocation()));
|
||||
|
||||
for (auto const& name : captureNames) {
|
||||
if (name == "this") {
|
||||
usedThis = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto expr = ParameterExpressionPtr(new ParameterExpression(
|
||||
BlockScopePtr(getOriginalScope()),
|
||||
getLocation(),
|
||||
TypeAnnotationPtr(),
|
||||
true /* hhType */,
|
||||
name,
|
||||
false /* ref */,
|
||||
0 /* token modifier thing */,
|
||||
ExpressionPtr(),
|
||||
ExpressionPtr()
|
||||
));
|
||||
m_vars->insertElement(expr);
|
||||
}
|
||||
|
||||
initializeValuesFromVars();
|
||||
analyzeVars(ar);
|
||||
}
|
||||
|
||||
std::set<std::string> ClosureExpression::collectParamNames() const {
|
||||
std::set<std::string> ret;
|
||||
|
||||
auto bodyParams = m_func->getParams();
|
||||
if (!bodyParams) return ret;
|
||||
|
||||
int nParams = bodyParams->getCount();
|
||||
for (int i = 0; i < nParams; i++) {
|
||||
auto par = static_pointer_cast<ParameterExpression>((*bodyParams)[i]);
|
||||
ret.insert(par->getName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ClosureExpression::hasStaticLocals() {
|
||||
ConstructPtr cons(m_func);
|
||||
return hasStaticLocalsImpl(cons);
|
||||
@@ -362,22 +279,6 @@ bool ClosureExpression::hasStaticLocalsImpl(ConstructPtr root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ClosureExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = m_vars != nullptr && m_vars->getCount() > 0 ? 3 : 2;
|
||||
cg.printObjectHeader("ClosureExpression", numProps);
|
||||
cg.printPropertyHeader("ffunction");
|
||||
m_func->outputCodeModel(cg);
|
||||
if (m_vars != nullptr && m_vars->getCount() > 0) {
|
||||
cg.printPropertyHeader("capturedVariables");
|
||||
cg.printExpressionVector(m_vars);
|
||||
}
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -390,5 +291,3 @@ void ClosureExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
}
|
||||
m_func->outputPHPBody(cg, ar);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define incl_HPHP_CLOSURE_EXPRESSION_H_
|
||||
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/parser/parser.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -30,20 +29,10 @@ DECLARE_BOOST_TYPES(ExpressionList);
|
||||
class ClosureExpression : public Expression {
|
||||
public:
|
||||
ClosureExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ClosureType type,
|
||||
FunctionStatementPtr func,
|
||||
ExpressionListPtr vars);
|
||||
FunctionStatementPtr func, ExpressionListPtr vars);
|
||||
|
||||
DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS;
|
||||
|
||||
// Flag for whether we have already determined the capture list for
|
||||
// this lambda.
|
||||
enum class CaptureState {
|
||||
Unknown,
|
||||
Known,
|
||||
};
|
||||
CaptureState captureState() const { return m_captureState; }
|
||||
|
||||
virtual ConstructPtr getNthKid(int n) const;
|
||||
virtual void setNthKid(int n, ConstructPtr cp);
|
||||
virtual int getKidCount() const;
|
||||
@@ -54,35 +43,17 @@ public:
|
||||
StringData* getClosureClassName() { return m_closureClassName; }
|
||||
void setClosureClassName(StringData* value) { m_closureClassName = value; }
|
||||
bool hasStaticLocals();
|
||||
ClosureType type() const { return m_type; }
|
||||
std::set<std::string> collectParamNames() const;
|
||||
|
||||
/*
|
||||
* Initialize the capture list for a closure that uses automatic
|
||||
* captures.
|
||||
*
|
||||
* Pre: captureState() == CaptureState::Unknown.
|
||||
*/
|
||||
void setCaptureList(AnalysisResultPtr ar,
|
||||
const std::set<std::string>&);
|
||||
|
||||
private:
|
||||
static TypePtr s_ClosureType;
|
||||
|
||||
private:
|
||||
void initializeFromUseList(ExpressionListPtr vars);
|
||||
void initializeValuesFromVars();
|
||||
void analyzeVars(AnalysisResultPtr);
|
||||
bool hasStaticLocalsImpl(ConstructPtr root);
|
||||
|
||||
private:
|
||||
ClosureType m_type;
|
||||
FunctionStatementPtr m_func;
|
||||
ExpressionListPtr m_vars;
|
||||
ExpressionListPtr m_values;
|
||||
StringData* m_closureClassName;
|
||||
std::set<std::string> m_unboundNames;
|
||||
CaptureState m_captureState;
|
||||
|
||||
static TypePtr s_ClosureType;
|
||||
|
||||
bool hasStaticLocalsImpl(ConstructPtr root);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -273,17 +273,6 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return actualType;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ConstantExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("SimpleVariableExpression", 2);
|
||||
cg.printPropertyHeader("variableName");
|
||||
cg.printValue(m_origName);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -113,26 +113,6 @@ TypePtr DynamicFunctionCall::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return Type::Variant;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DynamicFunctionCall::outputCodeModel(CodeGenerator &cg) {
|
||||
if (m_class || !m_className.empty()) {
|
||||
cg.printObjectHeader("ClassMethodCallExpression", 4);
|
||||
cg.printPropertyHeader("className");
|
||||
StaticClassName::outputCodeModel(cg);
|
||||
cg.printPropertyHeader("methodExpression");
|
||||
} else {
|
||||
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
|
||||
cg.printPropertyHeader("functionExpression");
|
||||
}
|
||||
m_nameExp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("arguments");
|
||||
cg.printExpressionVector(m_params);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(m_nameExp->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
void DynamicFunctionCall::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/compiler/analysis/variable_table.h"
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
@@ -88,19 +87,6 @@ TypePtr DynamicVariable::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return m_implementedType = Type::Variant;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DynamicVariable::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("UnaryOpExpression", 3);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_DYNAMIC_VARIABLE_OP) ;
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -119,19 +119,6 @@ bool EncapsListExpression::canonCompare(ExpressionPtr e) const {
|
||||
return m_type == el->m_type;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EncapsListExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("EncapsListExpression", 3);
|
||||
cg.printPropertyHeader("delimiter");
|
||||
cg.printValue(m_type);
|
||||
cg.printPropertyHeader("expressions");
|
||||
cg.printExpressionVector(m_exps);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ ExpressionPtr Expression::replaceValue(ExpressionPtr rep) {
|
||||
rep->clearContext(AssignmentRHS);
|
||||
rep = el;
|
||||
}
|
||||
if (isChildOfYield()) rep->setChildOfYield();
|
||||
if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) {
|
||||
static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash();
|
||||
}
|
||||
|
||||
@@ -17,12 +17,9 @@
|
||||
#ifndef incl_HPHP_EXPRESSION_H_
|
||||
#define incl_HPHP_EXPRESSION_H_
|
||||
|
||||
#include "hphp/util/deprecated/declare-boost-types.h"
|
||||
#include "hphp/util/hash-map-typedefs.h"
|
||||
#include "hphp/compiler/construct.h"
|
||||
#include "hphp/compiler/analysis/type.h"
|
||||
#include "hphp/compiler/analysis/analysis_result.h"
|
||||
#include "hphp/util/hash-map-typedefs.h"
|
||||
|
||||
#define EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS \
|
||||
BlockScopePtr scope, LocationPtr loc, Expression::KindOf kindOf
|
||||
@@ -39,7 +36,6 @@
|
||||
virtual ExpressionPtr clone(); \
|
||||
virtual TypePtr inferTypes(AnalysisResultPtr ar, TypePtr type, \
|
||||
bool coerce); \
|
||||
virtual void outputCodeModel(CodeGenerator &cg); \
|
||||
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
|
||||
#define DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS \
|
||||
DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS; \
|
||||
@@ -51,7 +47,7 @@ namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_BOOST_TYPES(Statement);
|
||||
DECLARE_EXTENDED_BOOST_TYPES(Expression);
|
||||
DECLARE_BOOST_TYPES(Expression);
|
||||
class Variant;
|
||||
|
||||
#define DECLARE_EXPRESSION_TYPES(x) \
|
||||
@@ -81,17 +77,7 @@ class Variant;
|
||||
x(ClosureExpression, None), \
|
||||
x(YieldExpression, None), \
|
||||
x(AwaitExpression, None), \
|
||||
x(UserAttribute, None), \
|
||||
x(QueryExpression, None), \
|
||||
x(FromClause, None), \
|
||||
x(LetClause, None), \
|
||||
x(WhereClause, None), \
|
||||
x(SelectClause, None), \
|
||||
x(IntoClause, None), \
|
||||
x(JoinClause, None), \
|
||||
x(GroupClause, None), \
|
||||
x(OrderbyClause, None), \
|
||||
x(Ordering, None)
|
||||
x(UserAttribute, None)
|
||||
|
||||
class Expression : public Construct {
|
||||
public:
|
||||
@@ -363,10 +349,6 @@ public:
|
||||
return isNoRemove() && m_assertedType;
|
||||
}
|
||||
|
||||
virtual bool allowCellByRef() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static ExpressionPtr MakeConstant(AnalysisResultConstPtr ar,
|
||||
BlockScopePtr scope,
|
||||
LocationPtr loc,
|
||||
|
||||
@@ -33,6 +33,7 @@ using namespace HPHP;
|
||||
ExpressionList::ExpressionList(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ListKind kind)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ExpressionList)),
|
||||
m_outputCount(-1),
|
||||
m_arrayElements(false), m_collectionType(0), m_kind(kind) {
|
||||
}
|
||||
|
||||
@@ -239,17 +240,28 @@ void ExpressionList::stripConcat() {
|
||||
BinaryOpExpressionPtr b
|
||||
(static_pointer_cast<BinaryOpExpression>(e));
|
||||
if (b->getOp() == '.') {
|
||||
if(!b->getExp1()->isArray() && !b->getExp2()->isArray()) {
|
||||
e = b->getExp1();
|
||||
el.insertElement(b->getExp2(), i + 1);
|
||||
continue;
|
||||
}
|
||||
e = b->getExp1();
|
||||
el.insertElement(b->getExp2(), i + 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionList::setOutputCount(int count) {
|
||||
assert(count >= 0 && count <= (int)m_exps.size());
|
||||
m_outputCount = count;
|
||||
}
|
||||
|
||||
int ExpressionList::getOutputCount() const {
|
||||
return m_outputCount < 0 ? m_exps.size() : m_outputCount;
|
||||
}
|
||||
|
||||
void ExpressionList::resetOutputCount() {
|
||||
m_outputCount = -1;
|
||||
}
|
||||
|
||||
void ExpressionList::markParam(int p, bool noRefWrapper) {
|
||||
ExpressionPtr param = (*this)[p];
|
||||
if (param->hasContext(Expression::InvokeArgument)) {
|
||||
@@ -274,7 +286,7 @@ void ExpressionList::markParams(bool noRefWrapper) {
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionList::setCollectionType(Collection::Type cType) {
|
||||
void ExpressionList::setCollectionType(int cType) {
|
||||
m_arrayElements = true;
|
||||
m_collectionType = cType;
|
||||
}
|
||||
@@ -466,19 +478,6 @@ bool ExpressionList::canonCompare(ExpressionPtr e) const {
|
||||
m_kind == l->m_kind;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ExpressionList::outputCodeModel(CodeGenerator &cg) {
|
||||
for (unsigned int i = 0; i < m_exps.size(); i++) {
|
||||
ExpressionPtr exp = m_exps[i];
|
||||
if (exp) {
|
||||
cg.printExpression(exp, exp->hasContext(RefParameter));
|
||||
} else {
|
||||
cg.printNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -514,3 +513,4 @@ unsigned int ExpressionList::checkLitstrKeys() const {
|
||||
}
|
||||
return keys.size();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,15 @@ public:
|
||||
void markParam(int p, bool noRefWrapper);
|
||||
void markParams(bool noRefWrapper);
|
||||
|
||||
void setCollectionType(Collection::Type cType);
|
||||
void setCollectionType(int cType);
|
||||
|
||||
/**
|
||||
* When a function call has too many arguments, we only want to output
|
||||
* max number of arguments, by limiting output count of subexpressions.
|
||||
*/
|
||||
void setOutputCount(int count);
|
||||
int getOutputCount() const;
|
||||
void resetOutputCount();
|
||||
|
||||
virtual bool canonCompare(ExpressionPtr e) const;
|
||||
|
||||
@@ -89,6 +97,7 @@ private:
|
||||
unsigned int checkLitstrKeys() const;
|
||||
|
||||
ExpressionPtrVec m_exps;
|
||||
int m_outputCount;
|
||||
bool m_arrayElements;
|
||||
int m_collectionType;
|
||||
ListKind m_kind;
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/expression/group_clause.h"
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/runtime/base/complex-types.h"
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constructors/destructors
|
||||
|
||||
GroupClause::GroupClause
|
||||
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr coll, ExpressionPtr key)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(GroupClause)),
|
||||
m_coll(coll), m_key(key) {
|
||||
}
|
||||
|
||||
ExpressionPtr GroupClause::clone() {
|
||||
GroupClausePtr exp(new GroupClause(*this));
|
||||
Expression::deepCopy(exp);
|
||||
exp->m_coll = Clone(m_coll);
|
||||
exp->m_key = Clone(m_key);
|
||||
return exp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// parser functions
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static analysis functions
|
||||
|
||||
void GroupClause::analyzeProgram(AnalysisResultPtr ar) {
|
||||
m_coll->analyzeProgram(ar);
|
||||
m_key->analyzeProgram(ar);
|
||||
}
|
||||
|
||||
ConstructPtr GroupClause::getNthKid(int n) const {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return m_coll;
|
||||
case 1:
|
||||
return m_key;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return ConstructPtr();
|
||||
}
|
||||
|
||||
int GroupClause::getKidCount() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
void GroupClause::setNthKid(int n, ConstructPtr cp) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
m_coll = dynamic_pointer_cast<Expression>(cp);
|
||||
break;
|
||||
case 1:
|
||||
m_key = dynamic_pointer_cast<Expression>(cp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr GroupClause::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
bool coerce) {
|
||||
m_coll->inferAndCheck(ar, Type::Some, false);
|
||||
m_key->inferAndCheck(ar, Type::Some, false);
|
||||
return Type::Object;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GroupClause::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("GroupClause", 3);
|
||||
cg.printPropertyHeader("collection");
|
||||
m_coll->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("key");
|
||||
m_key->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
void GroupClause::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
cg_printf("group ");
|
||||
m_coll->outputPHP(cg, ar);
|
||||
cg_printf(" by ");
|
||||
m_key->outputPHP(cg, ar);
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_GROUP_CLAUSE_H_
|
||||
#define incl_HPHP_GROUP_CLAUSE_H_
|
||||
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_BOOST_TYPES(GroupClause);
|
||||
|
||||
class GroupClause : public Expression {
|
||||
public:
|
||||
GroupClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr coll, ExpressionPtr key);
|
||||
|
||||
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
|
||||
|
||||
ExpressionPtr getColl() { return m_coll; }
|
||||
ExpressionPtr getKey() { return m_key; }
|
||||
private:
|
||||
ExpressionPtr m_coll;
|
||||
ExpressionPtr m_key;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
#endif // incl_HPHP_GROUP_CLAUSE_H_
|
||||
@@ -283,12 +283,6 @@ TypePtr IncludeExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return UnaryOpExpression::inferTypes(ar, type, coerce);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IncludeExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
UnaryOpExpression::outputCodeModel(cg);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/expression/join_clause.h"
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/runtime/base/complex-types.h"
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constructors/destructors
|
||||
|
||||
JoinClause::JoinClause
|
||||
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
const std::string &var, ExpressionPtr coll, ExpressionPtr left,
|
||||
ExpressionPtr right, const std::string &group)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(JoinClause)),
|
||||
m_var(var), m_coll(coll), m_left(left),
|
||||
m_right(right), m_group(group) {
|
||||
}
|
||||
|
||||
ExpressionPtr JoinClause::clone() {
|
||||
JoinClausePtr exp(new JoinClause(*this));
|
||||
Expression::deepCopy(exp);
|
||||
exp->m_var = m_var;
|
||||
exp->m_coll = Clone(m_coll);
|
||||
exp->m_left = Clone(m_left);
|
||||
exp->m_right = Clone(m_right);
|
||||
exp->m_group = m_group;
|
||||
return exp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// parser functions
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static analysis functions
|
||||
|
||||
void JoinClause::analyzeProgram(AnalysisResultPtr ar) {
|
||||
m_coll->analyzeProgram(ar);
|
||||
m_left->analyzeProgram(ar);
|
||||
m_right->analyzeProgram(ar);
|
||||
}
|
||||
|
||||
ConstructPtr JoinClause::getNthKid(int n) const {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return m_coll;
|
||||
case 1:
|
||||
return m_left;
|
||||
case 2:
|
||||
return m_right;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return ConstructPtr();
|
||||
}
|
||||
|
||||
int JoinClause::getKidCount() const {
|
||||
return 3;
|
||||
}
|
||||
|
||||
void JoinClause::setNthKid(int n, ConstructPtr cp) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
m_coll = dynamic_pointer_cast<Expression>(cp);
|
||||
break;
|
||||
case 1:
|
||||
m_left = dynamic_pointer_cast<Expression>(cp);
|
||||
break;
|
||||
case 2:
|
||||
m_right = dynamic_pointer_cast<Expression>(cp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr JoinClause::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
bool coerce) {
|
||||
m_coll->inferAndCheck(ar, Type::Some, false);
|
||||
m_left->inferAndCheck(ar, Type::Some, false);
|
||||
m_right->inferAndCheck(ar, Type::Some, false);
|
||||
return Type::Object;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JoinClause::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 5;
|
||||
if (!m_group.empty()) numProps++;
|
||||
cg.printObjectHeader("JoinClause", numProps);
|
||||
cg.printPropertyHeader("variable");
|
||||
cg.printValue(m_var);
|
||||
cg.printPropertyHeader("collection");
|
||||
m_coll->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("left");
|
||||
m_left->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("right");
|
||||
m_right->outputCodeModel(cg);
|
||||
if (!m_group.empty()) {
|
||||
cg.printPropertyHeader("group");
|
||||
cg.printValue(m_group);
|
||||
}
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
void JoinClause::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
cg_printf("join %s in ", m_var.c_str());
|
||||
m_coll->outputPHP(cg, ar);
|
||||
cg_printf(" on ");
|
||||
m_left->outputPHP(cg, ar);
|
||||
cg_printf(" equals ");
|
||||
m_right->outputPHP(cg, ar);
|
||||
if (!m_group.empty()) {
|
||||
cg_printf(" into %s", m_group.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_JOIN_CLAUSE_H_
|
||||
#define incl_HPHP_JOIN_CLAUSE_H_
|
||||
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_BOOST_TYPES(JoinClause);
|
||||
|
||||
class JoinClause : public Expression {
|
||||
public:
|
||||
JoinClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
const std::string &var, ExpressionPtr coll, ExpressionPtr left,
|
||||
ExpressionPtr right, const std::string &group);
|
||||
|
||||
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
|
||||
|
||||
std::string getVar() const { return m_var; }
|
||||
ExpressionPtr getColl() { return m_coll; }
|
||||
ExpressionPtr getLeft() { return m_left; }
|
||||
ExpressionPtr getRight() { return m_right; }
|
||||
std::string getGroup() { return m_group; }
|
||||
private:
|
||||
std::string m_var;
|
||||
ExpressionPtr m_coll;
|
||||
ExpressionPtr m_left;
|
||||
ExpressionPtr m_right;
|
||||
std::string m_group;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
#endif // incl_HPHP_JOIN_CLAUSE_H_
|
||||
@@ -31,7 +31,7 @@ using namespace HPHP;
|
||||
// constructors/destructors
|
||||
|
||||
/*
|
||||
Determine whether the rhs behaves normally, or abnormally.
|
||||
Determine whether the rhs behaves normall, or abnormally.
|
||||
|
||||
1) If the expression is the silence operator, recurse on the inner expression.
|
||||
2) If the expression is a list assignment expression, recurse on the
|
||||
@@ -77,7 +77,6 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
|
||||
case Expression::KindOfIncludeExpression:
|
||||
case Expression::KindOfYieldExpression:
|
||||
case Expression::KindOfAwaitExpression:
|
||||
case Expression::KindOfQueryExpression:
|
||||
return ListAssignment::Regular;
|
||||
|
||||
case Expression::KindOfListAssignment:
|
||||
@@ -119,15 +118,6 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
|
||||
case Expression::KindOfParameterExpression:
|
||||
case Expression::KindOfModifierExpression:
|
||||
case Expression::KindOfUserAttribute:
|
||||
case Expression::KindOfFromClause:
|
||||
case Expression::KindOfLetClause:
|
||||
case Expression::KindOfWhereClause:
|
||||
case Expression::KindOfSelectClause:
|
||||
case Expression::KindOfIntoClause:
|
||||
case Expression::KindOfJoinClause:
|
||||
case Expression::KindOfGroupClause:
|
||||
case Expression::KindOfOrderbyClause:
|
||||
case Expression::KindOfOrdering:
|
||||
always_assert(false);
|
||||
|
||||
// non-arrays
|
||||
@@ -283,22 +273,6 @@ TypePtr ListAssignment::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return m_array->inferAndCheck(ar, Type::Variant, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ListAssignment::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = m_array != nullptr ? 3 : 2;
|
||||
cg.printObjectHeader("ListAssignmentExpression", numProps);
|
||||
cg.printPropertyHeader("variables");
|
||||
cg.printExpressionVector(m_variables);
|
||||
if (m_array != nullptr) {
|
||||
cg.printPropertyHeader("expression");
|
||||
m_array->outputCodeModel(cg);
|
||||
}
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -118,20 +118,6 @@ bool ModifierExpression::validForClosure() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* In the context of a trait alias rule, only method access and visibility
|
||||
* modifiers are allowed
|
||||
*/
|
||||
bool ModifierExpression::validForTraitAliasRule() const {
|
||||
for (auto const& mod: m_modifiers) {
|
||||
if (mod != T_PUBLIC && mod != T_PRIVATE && mod != T_PROTECTED
|
||||
&& mod != T_FINAL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static analysis functions
|
||||
|
||||
@@ -145,29 +131,6 @@ TypePtr ModifierExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return TypePtr();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ModifierExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printf("V:9:\"HH\\Vector\":%d:{", (int)m_modifiers.size());
|
||||
for (unsigned int i = 0; i < m_modifiers.size(); i++) {
|
||||
cg.printObjectHeader("Modifier", 1);
|
||||
cg.printPropertyHeader("name");
|
||||
switch (m_modifiers[i]) {
|
||||
case T_PUBLIC: cg.printValue("public"); break;
|
||||
case T_PROTECTED: cg.printValue("protected"); break;
|
||||
case T_PRIVATE: cg.printValue("private"); break;
|
||||
case T_STATIC: cg.printValue("static"); break;
|
||||
case T_ABSTRACT: cg.printValue("abstract"); break;
|
||||
case T_FINAL: cg.printValue("final"); break;
|
||||
case T_ASYNC: cg.printValue("async"); break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
cg.printf("}");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ public:
|
||||
|
||||
bool validForFunction() const;
|
||||
bool validForClosure() const;
|
||||
bool validForTraitAliasRule() const;
|
||||
|
||||
void setHasPrivacy(bool f) { m_hasPrivacy = f; }
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
if (getScope()->isFirstPass()) {
|
||||
Compiler::Error(Compiler::BadConstructorCall, self);
|
||||
}
|
||||
m_params->setOutputCount(0);
|
||||
}
|
||||
m_params->inferAndCheck(ar, Type::Some, false);
|
||||
}
|
||||
@@ -152,25 +153,6 @@ TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return Type::Object;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void NewObjectExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("NewObjectExpression", m_params == nullptr ? 2 : 3);
|
||||
if (m_nameExp->is(Expression::KindOfScalarExpression)) {
|
||||
cg.printPropertyHeader("className");
|
||||
} else {
|
||||
cg.printPropertyHeader("classExpression");
|
||||
}
|
||||
m_nameExp->outputCodeModel(cg);
|
||||
if (m_params != nullptr) {
|
||||
cg.printPropertyHeader("arguments");
|
||||
cg.printExpressionVector(m_params);
|
||||
}
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ void ObjectMethodExpression::setInvokeParams(AnalysisResultPtr ar) {
|
||||
for (int i = 0; i < m_params->getCount(); i++) {
|
||||
(*m_params)[i]->inferAndCheck(ar, Type::Variant, false);
|
||||
}
|
||||
m_params->resetOutputCount();
|
||||
}
|
||||
|
||||
ExpressionPtr ObjectMethodExpression::preOptimize(AnalysisResultConstPtr ar) {
|
||||
@@ -277,28 +278,6 @@ TypePtr ObjectMethodExpression::inferAndCheck(AnalysisResultPtr ar,
|
||||
return checkParamsAndReturn(ar, type, coerce, func, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ObjectMethodExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ObjectMethodCallExpression",
|
||||
m_params == nullptr ? 3 : 4);
|
||||
cg.printPropertyHeader("object");
|
||||
m_object->outputCodeModel(cg);
|
||||
if (m_nameExp->is(Expression::KindOfScalarExpression)) {
|
||||
cg.printPropertyHeader("methodName");
|
||||
} else {
|
||||
cg.printPropertyHeader("methodExpression");
|
||||
}
|
||||
m_nameExp->outputCodeModel(cg);
|
||||
if (m_params != nullptr) {
|
||||
cg.printPropertyHeader("arguments");
|
||||
cg.printExpressionVector(m_params);
|
||||
}
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -332,23 +332,6 @@ ObjectPropertyExpression::postOptimize(AnalysisResultConstPtr ar) {
|
||||
ExpressionPtr();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ObjectPropertyExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ObjectPropertyExpression", 3);
|
||||
cg.printPropertyHeader("object");
|
||||
m_object->outputCodeModel(cg);
|
||||
if (m_property->is(Expression::KindOfScalarExpression)) {
|
||||
cg.printPropertyHeader("propertyName");
|
||||
} else {
|
||||
cg.printPropertyHeader("propertyExpression");
|
||||
}
|
||||
m_property->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/expression/ordering.h"
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/runtime/base/complex-types.h"
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constructors/destructors
|
||||
|
||||
Ordering::Ordering
|
||||
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr key, TokenID direction)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(Ordering)),
|
||||
m_key(key), m_direction(direction){
|
||||
}
|
||||
|
||||
ExpressionPtr Ordering::clone() {
|
||||
OrderingPtr exp(new Ordering(*this));
|
||||
Expression::deepCopy(exp);
|
||||
exp->m_key = Clone(m_key);
|
||||
exp->m_direction = m_direction;
|
||||
return exp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// parser functions
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static analysis functions
|
||||
|
||||
void Ordering::analyzeProgram(AnalysisResultPtr ar) {
|
||||
m_key->analyzeProgram(ar);
|
||||
}
|
||||
|
||||
ConstructPtr Ordering::getNthKid(int n) const {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return m_key;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return ConstructPtr();
|
||||
}
|
||||
|
||||
int Ordering::getKidCount() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Ordering::setNthKid(int n, ConstructPtr cp) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
m_key = dynamic_pointer_cast<Expression>(cp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr Ordering::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
bool coerce) {
|
||||
m_key->inferAndCheck(ar, Type::Some, false);
|
||||
return Type::Object;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Ordering::outputCodeModel(CodeGenerator &cg) {
|
||||
int direction;
|
||||
switch (m_direction) {
|
||||
case T_ASCENDING:
|
||||
direction = 1;
|
||||
break;
|
||||
case T_DESCENDING:
|
||||
direction = 2;
|
||||
break;
|
||||
default:
|
||||
direction = 3;
|
||||
break;
|
||||
}
|
||||
auto propCount = direction > 0 ? 3 : 2;
|
||||
cg.printObjectHeader("Ordering", propCount);
|
||||
cg.printPropertyHeader("key");
|
||||
m_key->outputCodeModel(cg);
|
||||
if (propCount == 3) {
|
||||
cg.printPropertyHeader("direction");
|
||||
cg.printValue(direction);
|
||||
}
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
void Ordering::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
m_key->outputPHP(cg, ar);
|
||||
switch (m_direction) {
|
||||
case T_ASCENDING:
|
||||
cg_printf(" ascending");
|
||||
break;
|
||||
case T_DESCENDING:
|
||||
cg_printf(" decending");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_ORDERING_H_
|
||||
#define incl_HPHP_ORDERING_H_
|
||||
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/parser/scanner.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_BOOST_TYPES(Ordering);
|
||||
|
||||
class Ordering : public Expression {
|
||||
|
||||
public:
|
||||
Ordering(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr key, TokenID direction);
|
||||
|
||||
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
|
||||
|
||||
ExpressionPtr getKey() const { return m_key; }
|
||||
TokenID getDirection() { return m_direction; }
|
||||
private:
|
||||
ExpressionPtr m_key;
|
||||
TokenID m_direction;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
#endif // incl_HPHP_ORDERING_H_
|
||||
@@ -300,45 +300,6 @@ void ParameterExpression::compatibleDefault() {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ParameterExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
auto propCount = 2;
|
||||
if (m_attributeList) propCount++;
|
||||
if (m_modifier != 0) propCount++;
|
||||
if (m_ref) propCount++;
|
||||
if (m_defaultValue != nullptr) propCount++;
|
||||
cg.printObjectHeader("ParameterDeclaration", propCount);
|
||||
if (m_attributeList) {
|
||||
cg.printPropertyHeader("isPassedByReference");
|
||||
cg.printExpressionVector(m_attributeList);
|
||||
}
|
||||
if (m_modifier != 0) {
|
||||
cg.printPropertyHeader("modifiers");
|
||||
printf("V:9:\"HH\\Vector\":1:{");
|
||||
switch (m_modifier) {
|
||||
case T_PUBLIC: cg.printValue("public"); break;
|
||||
case T_PROTECTED: cg.printValue("protected"); break;
|
||||
case T_PRIVATE: cg.printValue("private"); break;
|
||||
default: assert(false);
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
if (m_ref) {
|
||||
cg.printPropertyHeader("isPassedByReference");
|
||||
cg.printValue(true);
|
||||
}
|
||||
cg.printPropertyHeader("name");
|
||||
cg.printValue(m_name);
|
||||
if (m_defaultValue) {
|
||||
cg.printPropertyHeader("expression");
|
||||
m_defaultValue->outputCodeModel(cg);
|
||||
}
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/expression/constant_expression.h"
|
||||
#include "hphp/compiler/json.h"
|
||||
#include "hphp/util/json.h"
|
||||
#include "hphp/parser/scanner.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
@@ -163,28 +163,6 @@ ExpressionPtr QOpExpression::unneededHelper() {
|
||||
return static_pointer_cast<Expression>(shared_from_this());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QOpExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
if (m_expYes == nullptr) {
|
||||
cg.printObjectHeader("ValueIfNullExpression", 3);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_condition->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("valueIfNull");
|
||||
} else {
|
||||
cg.printObjectHeader("ConditionalExpression", 4);
|
||||
cg.printPropertyHeader("condition");
|
||||
m_condition->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("valueIfTrue");
|
||||
m_expYes->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("valueIfFalse");
|
||||
}
|
||||
m_expNo->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/expression/query_expression.h"
|
||||
#include "hphp/compiler/expression/simple_query_clause.h"
|
||||
#include "hphp/compiler/analysis/capture_extractor.h"
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/runtime/base/complex-types.h"
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constructors/destructors
|
||||
|
||||
QueryOrderby::QueryOrderby(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_BASE_PARAMETER_VALUES) {
|
||||
m_expressions = nullptr;
|
||||
}
|
||||
|
||||
ExpressionPtr QueryOrderby::clone() {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QueryExpression::QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr head, ExpressionPtr body)
|
||||
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(QueryExpression)) {
|
||||
m_queryargs = ExpressionListPtr(
|
||||
new ExpressionList(getScope(), getLocation())
|
||||
);
|
||||
m_expressions = ExpressionListPtr(
|
||||
new ExpressionList(getScope(), getLocation())
|
||||
);
|
||||
m_expressions->addElement(head);
|
||||
|
||||
assert(body != nullptr && body->is(Expression::KindOfExpressionList));
|
||||
ExpressionListPtr el(static_pointer_cast<ExpressionList>(body));
|
||||
for (unsigned int i = 0; i < el->getCount(); i++) {
|
||||
if ((*el)[i]) m_expressions->addElement((*el)[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QueryExpression::QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionListPtr clauses)
|
||||
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(QueryExpression)) {
|
||||
m_queryargs = ExpressionListPtr(
|
||||
new ExpressionList(getScope(), getLocation())
|
||||
);
|
||||
m_expressions = clauses;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// parser functions
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static analysis functions
|
||||
|
||||
ExpressionListPtr QueryExpression::getQueryArguments() {
|
||||
if (m_queryargs->getCount() == 0) serializeQueryExpression();
|
||||
return m_queryargs;
|
||||
}
|
||||
|
||||
StringData* QueryExpression::getQueryString() {
|
||||
if (m_querystr == nullptr) serializeQueryExpression();
|
||||
return m_querystr;
|
||||
}
|
||||
|
||||
void QueryExpression::serializeQueryExpression() {
|
||||
CaptureExtractor ce;
|
||||
auto qe = ce.rewrite(static_pointer_cast<Expression>(shared_from_this()));
|
||||
m_queryargs->clearElements();
|
||||
for (auto e : ce.getCapturedExpressions()) {
|
||||
m_queryargs->addElement(e);
|
||||
}
|
||||
assert(m_queryargs->getCount() > 0); //syntax requires an initial from clause
|
||||
|
||||
std::ostringstream serialized;
|
||||
CodeGenerator cg(&serialized, CodeGenerator::Output::CodeModel);
|
||||
cg.setAstClassPrefix("Code"); //TODO: create option for this
|
||||
qe->outputCodeModel(cg);
|
||||
std::string s(serialized.str().c_str(), serialized.str().length());
|
||||
m_querystr = makeStaticString(s);
|
||||
}
|
||||
|
||||
void QueryOrderby::analyzeProgram(AnalysisResultPtr ar) {
|
||||
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
|
||||
(*m_expressions)[i]->analyzeProgram(ar);
|
||||
}
|
||||
}
|
||||
|
||||
ConstructPtr QueryOrderby::getNthKid(int n) const {
|
||||
if (n < (int)m_expressions->getCount()) {
|
||||
return (*m_expressions)[n];
|
||||
}
|
||||
return ConstructPtr();
|
||||
}
|
||||
|
||||
int QueryOrderby::getKidCount() const {
|
||||
return m_expressions->getCount();
|
||||
}
|
||||
|
||||
void QueryOrderby::setNthKid(int n, ConstructPtr cp) {
|
||||
int m = m_expressions->getCount();
|
||||
if (n >= m) {
|
||||
assert(false);
|
||||
} else {
|
||||
(*m_expressions)[n] = dynamic_pointer_cast<Expression>(cp);
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr QueryOrderby::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
bool coerce) {
|
||||
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
|
||||
if (ExpressionPtr e = (*m_expressions)[i]) {
|
||||
e->inferAndCheck(ar, Type::Some, false);
|
||||
}
|
||||
}
|
||||
return Type::Object;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QueryOrderby::outputCodeModel(CodeGenerator &cg) {
|
||||
if (this->getKindOf() == Expression::KindOfOrderbyClause) {
|
||||
cg.printObjectHeader("OrderbyClause", 2);
|
||||
} else {
|
||||
cg.printObjectHeader("QueryExpression", 2);
|
||||
}
|
||||
cg.printPropertyHeader("clauses");
|
||||
m_expressions->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
void QueryOrderby::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
if (this->getKindOf() == Expression::KindOfOrderbyClause) {
|
||||
cg_printf("orderby ");
|
||||
}
|
||||
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
|
||||
if (ExpressionPtr e = (*m_expressions)[i]) {
|
||||
e->outputPHP(cg, ar);
|
||||
if (i > 0) cg_printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_QUERY_EXPRESSION_H_
|
||||
#define incl_HPHP_QUERY_EXPRESSION_H_
|
||||
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/runtime/base/static-string-table.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_BOOST_TYPES(QueryOrderby);
|
||||
|
||||
class QueryOrderby : public Expression {
|
||||
public:
|
||||
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
|
||||
|
||||
protected:
|
||||
explicit QueryOrderby(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS);
|
||||
|
||||
ExpressionListPtr m_expressions;
|
||||
};
|
||||
|
||||
DECLARE_BOOST_TYPES(QueryExpression);
|
||||
|
||||
class QueryExpression : public QueryOrderby {
|
||||
public:
|
||||
QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr head, ExpressionPtr body);
|
||||
QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionListPtr clauses);
|
||||
|
||||
virtual ExpressionPtr clone() {
|
||||
QueryExpressionPtr exp(new QueryExpression(*this));
|
||||
Expression::deepCopy(exp);
|
||||
exp->m_expressions = Clone(m_expressions);
|
||||
exp->m_queryargs = Clone(m_queryargs);
|
||||
exp->m_querystr = m_querystr;
|
||||
return exp;
|
||||
}
|
||||
|
||||
ExpressionListPtr getClauses() const { return m_expressions; }
|
||||
ExpressionListPtr getQueryArguments();
|
||||
StringData* getQueryString();
|
||||
private:
|
||||
void serializeQueryExpression();
|
||||
|
||||
ExpressionListPtr m_queryargs;
|
||||
StringData* m_querystr;
|
||||
};
|
||||
|
||||
DECLARE_BOOST_TYPES(OrderbyClause);
|
||||
|
||||
class OrderbyClause : public QueryOrderby {
|
||||
public:
|
||||
OrderbyClause(EXPRESSION_CONSTRUCTOR_PARAMETERS, ExpressionPtr orderings)
|
||||
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(OrderbyClause)) {
|
||||
assert(orderings && orderings->is(Expression::KindOfExpressionList));
|
||||
m_expressions = static_pointer_cast<ExpressionList>(orderings);
|
||||
}
|
||||
|
||||
virtual ExpressionPtr clone() {
|
||||
OrderbyClausePtr exp(new OrderbyClause(*this));
|
||||
Expression::deepCopy(exp);
|
||||
exp->m_expressions = Clone(m_expressions);
|
||||
return exp;
|
||||
}
|
||||
|
||||
ExpressionListPtr getOrderings() const { return m_expressions; }
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
#endif // incl_HPHP_QUERY_EXPRESSION_H_
|
||||
@@ -384,48 +384,6 @@ std::string ScalarExpression::getIdentifier() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ScalarExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
switch (m_type) {
|
||||
case T_NS_C:
|
||||
case T_LINE:
|
||||
case T_TRAIT_C:
|
||||
case T_CLASS_C:
|
||||
case T_METHOD_C:
|
||||
case T_FUNC_C: {
|
||||
cg.printObjectHeader("SimpleVariableExpression", 2);
|
||||
std::string varName;
|
||||
switch (m_type) {
|
||||
case T_NS_C: varName = "__NAMESPACE__"; break;
|
||||
case T_LINE: varName = "__LINE__"; break;
|
||||
case T_TRAIT_C: varName = "__TRAIT__"; break;
|
||||
case T_CLASS_C: varName = "__CLASS__"; break;
|
||||
case T_METHOD_C: varName = "__METHOD__"; break;
|
||||
case T_FUNC_C: varName = "__FUNCTION__"; break;
|
||||
default: break;
|
||||
}
|
||||
cg.printPropertyHeader("variableName");
|
||||
cg.printValue(varName);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cg.printObjectHeader("ScalarExpression", 2);
|
||||
cg.printPropertyHeader("value");
|
||||
cg.printValue(m_originalValue);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ScalarExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
switch (m_type) {
|
||||
case T_CONSTANT_ENCAPSED_STRING:
|
||||
@@ -501,7 +459,7 @@ Variant ScalarExpression::getVariant() const {
|
||||
return String(m_value);
|
||||
case T_LNUMBER:
|
||||
case T_COMPILER_HALT_OFFSET:
|
||||
return getIntValue();
|
||||
return strtoll(m_value.c_str(), nullptr, 0);
|
||||
case T_LINE:
|
||||
return String(m_translated).toInt64();
|
||||
case T_TRAIT_C:
|
||||
@@ -540,7 +498,7 @@ bool ScalarExpression::getString(const std::string *&s) const {
|
||||
|
||||
bool ScalarExpression::getInt(int64_t &i) const {
|
||||
if (m_type == T_LNUMBER || m_type == T_COMPILER_HALT_OFFSET) {
|
||||
i = getIntValue();
|
||||
i = strtoll(m_value.c_str(), nullptr, 0);
|
||||
return true;
|
||||
} else if (m_type == T_LINE) {
|
||||
i = getLocation() ? getLocation()->line1 : 0;
|
||||
@@ -566,12 +524,3 @@ void ScalarExpression::setCompilerHaltOffset(int64_t ofs) {
|
||||
m_value = ss.str();
|
||||
m_originalValue = ss.str();
|
||||
}
|
||||
|
||||
int64_t ScalarExpression::getIntValue() const {
|
||||
// binary number syntax "0b" is not supported by strtoll
|
||||
if (m_value.compare(0, 2, "0b") == 0) {
|
||||
return strtoll(m_value.c_str() + 2, nullptr, 2);
|
||||
}
|
||||
|
||||
return strtoll(m_value.c_str(), nullptr, 0);
|
||||
}
|
||||
|
||||
@@ -87,8 +87,6 @@ private:
|
||||
std::string m_translated;
|
||||
bool m_quoted;
|
||||
std::string m_comment; // for inlined constant name
|
||||
|
||||
int64_t getIntValue() const;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -102,17 +102,12 @@ SimpleFunctionCall::SimpleFunctionCall
|
||||
const std::string &name, bool hadBackslash, ExpressionListPtr params,
|
||||
ExpressionPtr cls)
|
||||
: FunctionCall(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(SimpleFunctionCall),
|
||||
ExpressionPtr(), name, hadBackslash, params, cls)
|
||||
, m_type(FunType::Unknown)
|
||||
, m_dynamicConstant(false)
|
||||
, m_builtinFunction(false)
|
||||
, m_dynamicInvoke(false)
|
||||
, m_transformed(false)
|
||||
, m_changedToBytecode(false)
|
||||
, m_optimizable(false)
|
||||
, m_safe(0)
|
||||
, m_extra(nullptr)
|
||||
{
|
||||
ExpressionPtr(), name, hadBackslash, params, cls),
|
||||
m_type(FunType::Unknown), m_dynamicConstant(false),
|
||||
m_builtinFunction(false), m_fromCompiler(false),
|
||||
m_dynamicInvoke(false), m_transformed(false), m_no_volatile_check(false),
|
||||
m_safe(0), m_extra(nullptr) {
|
||||
|
||||
if (!m_class && m_className.empty()) {
|
||||
m_dynamicInvoke = Option::DynamicInvokeFunctions.find(m_name) !=
|
||||
Option::DynamicInvokeFunctions.end();
|
||||
@@ -443,7 +438,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
|
||||
}
|
||||
case FunType::FBCallUserFuncSafe:
|
||||
case FunType::FunctionExists:
|
||||
{
|
||||
if (!m_no_volatile_check) {
|
||||
FunctionScopePtr func = ar->findFunction(Util::toLower(symbol));
|
||||
if (func && func->isUserFunction()) {
|
||||
func->setVolatile();
|
||||
@@ -452,7 +447,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
|
||||
}
|
||||
case FunType::InterfaceExists:
|
||||
case FunType::ClassExists:
|
||||
{
|
||||
if (!m_no_volatile_check) {
|
||||
ClassScopePtr cls = ar->findClass(Util::toLower(symbol));
|
||||
if (cls && cls->isUserClass()) {
|
||||
cls->setVolatile();
|
||||
@@ -523,7 +518,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
|
||||
markRefParams(m_funcScope, m_name, canInvokeFewArgs());
|
||||
}
|
||||
} else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
|
||||
if (m_type == FunType::Unknown &&
|
||||
if (!m_fromCompiler && m_type == FunType::Unknown &&
|
||||
!m_class && !m_redeclared && !m_dynamicInvoke && !m_funcScope &&
|
||||
(m_className.empty() ||
|
||||
(m_classScope &&
|
||||
@@ -545,9 +540,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
if (m_classScope || !Unit::lookupFunc(String(m_name).get())) {
|
||||
Compiler::Error(Compiler::UnknownFunction, shared_from_this());
|
||||
}
|
||||
Compiler::Error(Compiler::UnknownFunction, shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,6 +570,7 @@ void SimpleFunctionCall::updateVtFlags() {
|
||||
m_name == "call_user_func_array" ||
|
||||
m_name == "forward_static_call" ||
|
||||
m_name == "forward_static_call_array" ||
|
||||
m_name == "hphp_create_continuation" ||
|
||||
m_name == "get_called_class") {
|
||||
f->setNextLSB(true);
|
||||
}
|
||||
@@ -610,6 +604,10 @@ bool SimpleFunctionCall::isCallToFunction(const char *name) const {
|
||||
!getClass() && getClassName().empty();
|
||||
}
|
||||
|
||||
bool SimpleFunctionCall::isCompilerCallToFunction(const char *name) const {
|
||||
return m_fromCompiler && isCallToFunction(name);
|
||||
}
|
||||
|
||||
bool SimpleFunctionCall::isSimpleDefine(StringData **outName,
|
||||
TypedValue *outValue) const {
|
||||
if (!isCallToFunction("define")) return false;
|
||||
@@ -959,7 +957,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (func->isUserFunction()) {
|
||||
if (!m_no_volatile_check && func->isUserFunction()) {
|
||||
func->setVolatile();
|
||||
}
|
||||
if (!func->isVolatile() && m_type == FunType::FunctionExists) {
|
||||
@@ -974,7 +972,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
|
||||
for (ClassScopePtrVec::const_iterator it = classes.begin();
|
||||
it != classes.end(); ++it) {
|
||||
ClassScopePtr cls = *it;
|
||||
if (cls->isUserClass()) {
|
||||
if (!m_no_volatile_check && cls->isUserClass()) {
|
||||
cls->setVolatile();
|
||||
}
|
||||
if (cls->isInterface()) {
|
||||
@@ -998,7 +996,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
|
||||
for (ClassScopePtrVec::const_iterator it = classes.begin();
|
||||
it != classes.end(); ++it) {
|
||||
ClassScopePtr cls = *it;
|
||||
if (cls->isUserClass()) {
|
||||
if (!m_no_volatile_check && cls->isUserClass()) {
|
||||
cls->setVolatile();
|
||||
}
|
||||
if (!cls->isInterface() && !cls->isTrait()) {
|
||||
@@ -1043,6 +1041,7 @@ ExpressionPtr SimpleFunctionCall::postOptimize(AnalysisResultConstPtr ar) {
|
||||
ExpressionPtr(), T_ARRAY, true));
|
||||
return replaceValue(rep);
|
||||
}
|
||||
m_params->resetOutputCount();
|
||||
}
|
||||
/*
|
||||
Dont do this for now. Need to take account of newly created
|
||||
@@ -1275,26 +1274,6 @@ TypePtr SimpleFunctionCall::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
|
||||
return rtype;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SimpleFunctionCall::outputCodeModel(CodeGenerator &cg) {
|
||||
if (m_class || !m_className.empty()) {
|
||||
cg.printObjectHeader("ClassMethodCallExpression", 4);
|
||||
cg.printPropertyHeader("className");
|
||||
StaticClassName::outputCodeModel(cg);
|
||||
cg.printPropertyHeader("methodName");
|
||||
} else {
|
||||
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
|
||||
cg.printPropertyHeader("functionName");
|
||||
}
|
||||
cg.printValue(m_origName);
|
||||
cg.printPropertyHeader("arguments");
|
||||
cg.printExpressionVector(m_params);
|
||||
cg.printPropertyHeader("sourceLocation");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -1634,3 +1613,4 @@ ExpressionPtr hphp_opt_is_callable(CodeGenerator *cg,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário