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 |
+9
-4
@@ -1,5 +1,10 @@
|
||||
*.[oad]
|
||||
*.hhbc
|
||||
/bin*-g
|
||||
/bin*-O
|
||||
/bin/*.so
|
||||
/bin/hphp_options
|
||||
/bin/systemlib.php
|
||||
.mkdir
|
||||
hphp.log
|
||||
|
||||
@@ -36,8 +41,6 @@ hphp.log
|
||||
/hphp/runtime/ext/*.ext_hhvm.h
|
||||
/hphp/runtime/ext/*/*.ext_hhvm.cpp
|
||||
/hphp/runtime/ext/*/*.ext_hhvm.h
|
||||
/hphp/runtime/ext/*/*/*.ext_hhvm.h
|
||||
/hphp/runtime/ext/*/*/*.ext_hhvm.cpp
|
||||
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.cpp
|
||||
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.h
|
||||
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.cpp
|
||||
@@ -52,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
|
||||
@@ -61,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
|
||||
@@ -23,5 +23,4 @@ env:
|
||||
script: hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
irc: "chat.freenode.net#hhvm"
|
||||
|
||||
@@ -1,31 +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)
|
||||
CHECK_CXX_SOURCE_COMPILES("#include <time.h>
|
||||
int main() {
|
||||
clock_gettime((clockid_t)0, NULL);
|
||||
return 0;
|
||||
}" 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()
|
||||
@@ -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,14 +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 ${GNUCC_48_OPT}")
|
||||
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)
|
||||
|
||||
+16
-18
@@ -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,10 +85,13 @@ 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)
|
||||
|
||||
# GD checks
|
||||
@@ -138,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)
|
||||
@@ -305,17 +302,19 @@ if (NOT RECENT_CCLIENT)
|
||||
message(FATAL_ERROR "Your version of c-client is too old, you need 2007")
|
||||
endif()
|
||||
|
||||
find_package(Libpam)
|
||||
if (PAM_INCLUDE_PATH)
|
||||
include_directories(${PAM_INCLUDE_PATH})
|
||||
else()
|
||||
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)
|
||||
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)
|
||||
add_definitions(-DSKIP_IMAP_SSL=1)
|
||||
endif()
|
||||
@@ -463,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)
|
||||
@@ -477,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()
|
||||
|
||||
|
||||
@@ -68,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)
|
||||
@@ -122,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()
|
||||
|
||||
+2
-21
@@ -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()
|
||||
@@ -120,10 +105,6 @@ if(APPLE)
|
||||
add_definitions(-DMACOSX_DEPLOYMENT_TARGET=10.6)
|
||||
endif()
|
||||
|
||||
if(ENABLE_FASTCGI)
|
||||
add_definitions(-DENABLE_FASTCGI=1)
|
||||
endif ()
|
||||
|
||||
# enable the OSS options if we have any
|
||||
add_definitions(-DHPHP_OSS=1)
|
||||
|
||||
|
||||
+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 precedessor 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.
|
||||
@@ -22,14 +22,10 @@ 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 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
|
||||
@@ -37,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 &
|
||||
|
||||
@@ -47,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
|
||||
|
||||
@@ -67,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
|
||||
|
||||
@@ -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
|
||||
+46
-11
@@ -16,14 +16,44 @@
|
||||
#
|
||||
|
||||
include(HPHPSetup)
|
||||
include(FollySetup)
|
||||
|
||||
# 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)
|
||||
@@ -32,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)
|
||||
@@ -44,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)
|
||||
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
Next release
|
||||
- support date.timezone in ini files
|
||||
- implement fileinfo
|
||||
- special comparisons for DateTime
|
||||
- <cool stuff goes here>
|
||||
|
||||
"Sausage" 14-Oct-2013
|
||||
- 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
|
||||
|
||||
@@ -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"
|
||||
@@ -2108,6 +2108,7 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
|
||||
}
|
||||
|
||||
cs->clearVisited();
|
||||
cs->clearChildOfYield();
|
||||
|
||||
StatementPtr s = dpc(Statement, cs);
|
||||
if (s) {
|
||||
@@ -2360,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:
|
||||
@@ -2395,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) {
|
||||
@@ -2530,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;
|
||||
@@ -2606,7 +2611,7 @@ private:
|
||||
|
||||
ExpressionListPtr el(
|
||||
new ExpressionList(
|
||||
CONSTRUCT_EXP(target),
|
||||
CONSTRUCT_PARAMS(target),
|
||||
ExpressionList::ListKindComma));
|
||||
if (target->isUnused()) {
|
||||
el->setUnused(true);
|
||||
@@ -2950,7 +2955,7 @@ private:
|
||||
slistPtr->insertElement(
|
||||
ExpStatementPtr(
|
||||
new ExpStatement(
|
||||
CONSTRUCT_STMT(slistPtr), assertion)),
|
||||
CONSTRUCT_PARAMS(slistPtr), assertion)),
|
||||
idx);
|
||||
}
|
||||
break;
|
||||
@@ -3031,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);
|
||||
|
||||
@@ -967,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() {}
|
||||
|
||||
@@ -993,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);
|
||||
@@ -1183,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)
|
||||
|
||||
@@ -1228,7 +1225,7 @@ template <typename When>
|
||||
void
|
||||
AnalysisResult::preWaitCallback(bool first,
|
||||
const BlockScopeRawPtrQueue &scopes,
|
||||
void *context) {
|
||||
void *opaque) {
|
||||
// default is no-op
|
||||
}
|
||||
|
||||
@@ -1237,7 +1234,7 @@ bool
|
||||
AnalysisResult::postWaitCallback(bool first,
|
||||
bool again,
|
||||
const BlockScopeRawPtrQueue &scopes,
|
||||
void *context) {
|
||||
void *opaque) {
|
||||
// default is no-op
|
||||
return again;
|
||||
}
|
||||
@@ -1302,7 +1299,7 @@ struct BIPairCmp {
|
||||
template <typename When>
|
||||
void
|
||||
AnalysisResult::processScopesParallel(const char *id,
|
||||
void *context /* = NULL */) {
|
||||
void *opaque /* = NULL */) {
|
||||
BlockScopeRawPtrQueue scopes;
|
||||
getScopesSet(scopes);
|
||||
|
||||
@@ -1339,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
|
||||
{
|
||||
@@ -1393,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();
|
||||
@@ -1565,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: " <<
|
||||
@@ -1672,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());
|
||||
}
|
||||
@@ -1686,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;
|
||||
@@ -1714,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);
|
||||
|
||||
+407
-1617
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -28,9 +28,6 @@
|
||||
#include "hphp/runtime/vm/unit.h"
|
||||
#include "hphp/util/hash.h"
|
||||
|
||||
#include <deque>
|
||||
#include <utility>
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
DECLARE_BOOST_TYPES(ClosureExpression);
|
||||
@@ -98,7 +95,6 @@ public:
|
||||
IterKind kind;
|
||||
Id id;
|
||||
};
|
||||
|
||||
#define O(name, imm, pop, push, flags) \
|
||||
void name(imm);
|
||||
#define NA
|
||||
@@ -123,7 +119,6 @@ public:
|
||||
#define AA ArrayData*
|
||||
#define BA Label&
|
||||
#define OA unsigned char
|
||||
#define VSA std::vector<std::string>&
|
||||
OPCODES
|
||||
#undef O
|
||||
#undef NA
|
||||
@@ -144,7 +139,6 @@ public:
|
||||
#undef AA
|
||||
#undef BA
|
||||
#undef OA
|
||||
#undef VSA
|
||||
private:
|
||||
ConstructPtr m_node;
|
||||
UnitEmitter& m_ue;
|
||||
@@ -322,246 +316,13 @@ 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;
|
||||
};
|
||||
|
||||
|
||||
class FinallyRouter;
|
||||
|
||||
DECLARE_BOOST_TYPES(FinallyRouterEntry);
|
||||
/*
|
||||
* FinallyRouterEntry 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 actions that can be taken inside a block.
|
||||
*/
|
||||
class FinallyRouterEntry {
|
||||
public:
|
||||
enum EntryKind {
|
||||
// Top-level (global) context.
|
||||
GlobalEntry,
|
||||
// Function body / method body entry.
|
||||
FuncBodyEntry,
|
||||
// Entry for finally fault funclets emitted after the body of
|
||||
// a function
|
||||
FuncFaultEntry,
|
||||
// Try block entry (begins with try ends after catches).
|
||||
TryFinallyEntry,
|
||||
// Finally block entry (begins after catches ends after finally)
|
||||
FinallyEntry,
|
||||
// Loop OR a break statement.
|
||||
LoopEntry,
|
||||
};
|
||||
|
||||
typedef Emitter::IterPair IterPair;
|
||||
typedef std::vector<IterPair> IterVec;
|
||||
|
||||
DECLARE_BOOST_TYPES(Action);
|
||||
/*
|
||||
* 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 Action {
|
||||
static const int k_unsetState;
|
||||
|
||||
explicit Action(FinallyRouter* router);
|
||||
~Action();
|
||||
|
||||
// Manage state ID reuse.
|
||||
bool isAllocated();
|
||||
void allocate();
|
||||
void release();
|
||||
|
||||
FinallyRouter* m_router;
|
||||
// The target to jump to once all the necessary finally blocks
|
||||
// are run.
|
||||
Label m_label;
|
||||
// The state ID that identifies this action inside finally switch
|
||||
// statements. This is the id assigned to the "state" unnamed
|
||||
// local variable.
|
||||
int m_state;
|
||||
};
|
||||
|
||||
FinallyRouterEntry(FinallyRouter* router,
|
||||
EntryKind kind,
|
||||
FinallyRouterEntryPtr parent);
|
||||
~FinallyRouterEntry();
|
||||
|
||||
// Helpers used for freeing iterators when appropriate actions
|
||||
// require that.
|
||||
void emitIterBreak(Emitter& e,
|
||||
IterVec& iters,
|
||||
Label& target);
|
||||
void emitIterFree(Emitter& e, IterVec& iters);
|
||||
void emitIterFree(Emitter& e);
|
||||
|
||||
// Emission of code snippets commencing actions. Method
|
||||
// emitXYZ(e, ...) should be used instead of e.XYZ(...) in
|
||||
// EmitterVisitor.
|
||||
void emitReturn(Emitter& e, char sym);
|
||||
void emitReturnImpl(Emitter& e,
|
||||
char sym,
|
||||
IterVec& iters);
|
||||
void emitGoto(Emitter& e, StringData* name);
|
||||
void emitGotoImpl(Emitter& e,
|
||||
StringData* name,
|
||||
IterVec& iters);
|
||||
void emitBreak(Emitter& e, int depth);
|
||||
void emitBreakImpl(Emitter& e,
|
||||
int depth,
|
||||
IterVec& iters);
|
||||
void emitContinue(Emitter& e, int depth);
|
||||
void emitContinueImpl(Emitter& e,
|
||||
int depth,
|
||||
IterVec& iters);
|
||||
|
||||
// Emit the switch statement in the finally epilogue. Optimizes
|
||||
// cases where there is either just a fall-through case, or where
|
||||
// there is a single case other than fall-through.
|
||||
void emitFinallySwitch(Emitter& e);
|
||||
|
||||
// Helper for emitting beginning of single case from the finally
|
||||
// epilogue.
|
||||
void emitCase(Emitter& e, std::vector<Label*>& cases, ActionPtr action);
|
||||
void emitReturnCase(Emitter& e, std::vector<Label*>& cases, char sym);
|
||||
void emitReturnCaseImpl(Emitter& e, char sym, IterVec& iters);
|
||||
void emitBreakCase(Emitter& e, std::vector<Label*>& cases, int depth);
|
||||
void emitBreakCaseImpl(Emitter& e, int depth, IterVec& iters);
|
||||
void emitContinueCase(Emitter& e, std::vector<Label*>& cases, int depth);
|
||||
void emitContinueCaseImpl(Emitter& e, int depth, IterVec& iters);
|
||||
|
||||
// Helper for establishing the maximal depth of break / continue
|
||||
// actions that are allocated.
|
||||
int getBreakContinueDepth();
|
||||
|
||||
// Returns the maximal break / continue depth admissable (aka the
|
||||
// number of nested loops).
|
||||
int getMaxBreakContinueDepth();
|
||||
|
||||
// Methods used for emitting different cases for the finally
|
||||
// epilogue switch.
|
||||
void emitGotoCase(Emitter& e, std::vector<Label*>& cases, StringData* name);
|
||||
void emitGotoCaseImpl(Emitter& e, StringData* name, IterVec& iters);
|
||||
void emitReturnCases(Emitter& e, std::vector<Label*>& cases);
|
||||
void emitGotoCases(Emitter& e, std::vector<Label*>& cases);
|
||||
void emitBreakContinueCases(Emitter& e, std::vector<Label*>& cases);
|
||||
void emitAllCases(Emitter& e, std::vector<Label*>& cases);
|
||||
|
||||
// Methods used for collecting labels corresponding to the cases
|
||||
// from the finally epilogue. All the labels are accumulated
|
||||
// inside the cases array. The array is eventually passed to
|
||||
// e.Switch as the immediate argument.
|
||||
void collectReturnCases(std::vector<Label*>& cases);
|
||||
void collectGotoCases(std::vector<Label*>& cases);
|
||||
void collectBreakContinueCases(std::vector<Label*>& cases);
|
||||
void collectCase(std::vector<Label*>& cases,
|
||||
ActionPtr action);
|
||||
void collectAllCases(std::vector<Label*>& cases);
|
||||
|
||||
// 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();
|
||||
|
||||
// Methods used for allocating new finally-aware code-paths.
|
||||
// When alloc is set to false, the action is merely allocated in
|
||||
// memory and shared among different entries. When alloc is set to
|
||||
// true, the action is additionally assigned a state ID.
|
||||
ActionPtr registerReturn(StatementPtr s, char sym);
|
||||
ActionPtr registerGoto(StatementPtr s, StringData* name, bool alloc);
|
||||
ActionPtr registerBreak(StatementPtr s, int depth, bool alloc);
|
||||
ActionPtr registerContinue(StatementPtr s, int depth, bool alloc);
|
||||
// Used to indicate that a particular label is present inside
|
||||
// an entry. Labels don't have corresponding actions, however
|
||||
// they need to be tracked in order to handle gotos appropriately.
|
||||
void registerLabel(StatementPtr s, StringData* name);
|
||||
// Yield / await is not supported inside a finally block for now.
|
||||
// This method throws a parse time fatal whenever appropriate.
|
||||
void registerYieldAwait(ExpressionPtr e);
|
||||
|
||||
FinallyRouter* m_router;
|
||||
EntryKind m_kind;
|
||||
// Only used for loop / break kind of entries.
|
||||
Id m_iterId;
|
||||
bool m_iterRef;
|
||||
// Because of a bug in code emission, functions sometimes have
|
||||
// inconsistent return flavours. Therefore instead of a single
|
||||
// return action, there need to be one return action per flavor
|
||||
// used. Once the bug is removed, this code can be simplified.
|
||||
std::map<char, ActionPtr> m_returnActions;
|
||||
// A map of goto actions. Each goto action is identified by the
|
||||
// name of the destination label.
|
||||
std::map<StringData*, ActionPtr, string_data_lt> m_gotoActions;
|
||||
// A map 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;
|
||||
// Continue actions identified by their depth.
|
||||
std::map<int, ActionPtr> m_continueActions;
|
||||
// Break actions identified by their depth.
|
||||
std::map<int, ActionPtr> m_breakActions;
|
||||
// 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 cases that need to be included in the switch statement. Only
|
||||
// used when kind is set to try statement.
|
||||
// These are the actions that are invoked inside the protected region
|
||||
// protected by the try represented by this entry.
|
||||
std::set<ActionPtr> m_finallyCases;
|
||||
// The parent entry.
|
||||
FinallyRouterEntryPtr m_parent;
|
||||
};
|
||||
|
||||
class FinallyRouter {
|
||||
public:
|
||||
typedef FinallyRouterEntry::EntryKind EntryKind;
|
||||
|
||||
FinallyRouter();
|
||||
~FinallyRouter();
|
||||
|
||||
// The top entry on the unified stack.
|
||||
FinallyRouterEntryPtr top();
|
||||
// Create an entry corresponding to the passed in statement s.
|
||||
// If the statement is insignificant (e.g. is an if statement),
|
||||
// nullptr is returned.
|
||||
FinallyRouterEntryPtr createForStatement(StatementPtr s);
|
||||
// Create a global (top-level) entry.
|
||||
FinallyRouterEntryPtr createGlobal(StatementPtr s);
|
||||
// Create an entry for a functiob body.
|
||||
FinallyRouterEntryPtr createFuncBody(StatementPtr s);
|
||||
// Create an entry for a fault funclet inside a function body
|
||||
FinallyRouterEntryPtr createFuncFault(StatementPtr s);
|
||||
// Helper function for creating entries.
|
||||
FinallyRouterEntryPtr create(StatementPtr s, EntryKind 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 enter(FinallyRouterEntryPtr);
|
||||
void leave(FinallyRouterEntryPtr);
|
||||
|
||||
// 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.
|
||||
int allocateState();
|
||||
void releaseState(int state);
|
||||
|
||||
// The stack of all the entered entries.
|
||||
std::vector<FinallyRouterEntryPtr> m_entries;
|
||||
// The state IDs currently allocated. See FIXME above.
|
||||
std::set<int> m_states;
|
||||
Label* m_entry;
|
||||
};
|
||||
|
||||
class EmitterVisitor {
|
||||
friend class UnsetUnnamedLocalThunklet;
|
||||
friend class FuncFinisher;
|
||||
public:
|
||||
explicit EmitterVisitor(UnitEmitter& ue);
|
||||
~EmitterVisitor();
|
||||
@@ -571,7 +332,6 @@ 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;
|
||||
@@ -589,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);
|
||||
@@ -610,15 +370,6 @@ public:
|
||||
|| isJumpTarget(m_ue.bcPos())
|
||||
|| (instrFlags(getPrevOpcode()) & TF) == 0);
|
||||
}
|
||||
FinallyRouter& getFinallyRouter() { return m_finallyRouter; }
|
||||
Id getStateLocal() {
|
||||
DCHECK(m_stateLocal >= 0);
|
||||
return m_stateLocal;
|
||||
}
|
||||
Id getRetLocal() {
|
||||
DCHECK(m_retLocal >= 0);
|
||||
return m_retLocal;
|
||||
}
|
||||
|
||||
class IncludeTimeFatalException : public Exception {
|
||||
public:
|
||||
@@ -688,6 +439,31 @@ private:
|
||||
FuncEmitter* m_fe;
|
||||
};
|
||||
|
||||
class ControlTargets {
|
||||
public:
|
||||
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),
|
||||
@@ -706,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 {
|
||||
@@ -769,19 +541,16 @@ 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<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;
|
||||
FinallyRouter m_finallyRouter;
|
||||
Id m_stateLocal;
|
||||
Id m_retLocal;
|
||||
|
||||
MetaInfoBuilder m_metaInfo;
|
||||
public:
|
||||
bool checkIfStackEmpty(const char* forInstruction) const;
|
||||
@@ -800,11 +569,16 @@ 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);
|
||||
@@ -814,6 +588,7 @@ public:
|
||||
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);
|
||||
@@ -834,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);
|
||||
@@ -899,55 +675,31 @@ 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,
|
||||
FinallyRouterEntryPtr entry);
|
||||
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);
|
||||
|
||||
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 newFuncletAndRegion(Offset start,
|
||||
Offset end,
|
||||
Thunklet* t,
|
||||
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
|
||||
void newFuncletAndRegion(StatementPtr stmt,
|
||||
Offset start,
|
||||
Offset end,
|
||||
Thunklet* t,
|
||||
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
|
||||
|
||||
void newFPIRegion(Offset start, Offset end, Offset fpOff);
|
||||
void copyOverExnHandlers(FuncEmitter* fe);
|
||||
@@ -967,7 +719,6 @@ public:
|
||||
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,11 +13,8 @@
|
||||
| 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/analysis_result.h"
|
||||
#include "hphp/compiler/analysis/class_scope.h"
|
||||
@@ -26,6 +23,7 @@
|
||||
#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"
|
||||
@@ -100,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);
|
||||
@@ -111,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);
|
||||
@@ -324,73 +321,66 @@ 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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hoistOnly = true;
|
||||
}
|
||||
|
||||
m_includeState = 2;
|
||||
}
|
||||
|
||||
@@ -400,9 +390,11 @@ void FileScope::analyzeIncludes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileScope::visit(AnalysisResultPtr ar,
|
||||
void (*cb)(AnalysisResultPtr, StatementPtr, void*),
|
||||
void *data) {
|
||||
void *data)
|
||||
{
|
||||
if (m_pseudoMain) {
|
||||
cb(ar, m_pseudoMain->getStmt(), data);
|
||||
}
|
||||
@@ -417,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(),
|
||||
|
||||
@@ -62,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;
|
||||
|
||||
@@ -354,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());
|
||||
|
||||
@@ -226,8 +226,6 @@ public:
|
||||
bool allowOverride() const;
|
||||
void setAllowOverride();
|
||||
|
||||
bool needsFinallyLocals() const;
|
||||
|
||||
/**
|
||||
* Whether this function is a runtime helper function
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,148 +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::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:%ld;", 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:6:\"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", 4);
|
||||
printPropertyHeader("expression");
|
||||
expression->outputCodeModel(*this);
|
||||
printPropertyHeader("operation");
|
||||
printValue(PHP_REFERENCE_OP);
|
||||
printPropertyHeader("location");
|
||||
printLocation(expression->getLocation());
|
||||
printObjectFooter();
|
||||
} else {
|
||||
expression->outputCodeModel(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::printExpressionVector(ExpressionListPtr el) {
|
||||
printf("V:6:\"Vector\":%d:{", el->getCount());
|
||||
if (el->getCount() > 0) {
|
||||
el->outputCodeModel(*this);
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
|
||||
void CodeGenerator::printExpressionVector(ExpressionPtr e) {
|
||||
printf("V:6:\"Vector\":1:{");
|
||||
e->outputCodeModel(*this);
|
||||
printf("}");
|
||||
}
|
||||
|
||||
void CodeGenerator::printAsBlock(StatementPtr s) {
|
||||
if (s->is(Statement::KindOfBlockStatement)) {
|
||||
s->outputCodeModel(*this);
|
||||
} else {
|
||||
printObjectHeader("BlockStatement", 2);
|
||||
printPropertyHeader("statements");
|
||||
if (s->is(Statement::KindOfStatementList)) {
|
||||
auto sl = static_pointer_cast<StatementList>(s);
|
||||
printStatementVector(sl);
|
||||
} else {
|
||||
printf("V:6:\"Vector\":1:{");
|
||||
s->outputCodeModel(*this);
|
||||
printf("}");
|
||||
}
|
||||
printPropertyHeader("location");
|
||||
printLocation(s->getLocation());
|
||||
printObjectFooter();
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::printStatementVector(StatementListPtr sl) {
|
||||
printf("V:6:\"Vector\":%d:{", sl->getCount());
|
||||
if (sl->getCount() > 0) {
|
||||
sl->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_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,34 +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 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 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,103 +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_REFERENCE_OP = 21,
|
||||
PHP_REQUIRE_OP = 22,
|
||||
PHP_REQUIRE_ONCE_OP = 23,
|
||||
PHP_STRING_CAST_OP = 24,
|
||||
PHP_UNSET_CAST_OP = 25,
|
||||
};
|
||||
|
||||
/** Enumerates the kinds of type declaration statements. */
|
||||
enum CodeModelTypeKind {
|
||||
PHP_CLASS = 1,
|
||||
PHP_INTERFACE = 2,
|
||||
PHP_TRAIT = 3,
|
||||
};
|
||||
|
||||
}
|
||||
#endif // incl_HPHP_CODE_MODEL_ENUMS_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";
|
||||
@@ -596,7 +596,6 @@ int process(const CompilerOptions &po) {
|
||||
return 1;
|
||||
}
|
||||
if (Option::WholeProgram || po.target == "analyze") {
|
||||
Timer timer(Timer::WallTime, "analyzeProgram");
|
||||
ar->analyzeProgram();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -195,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);
|
||||
@@ -244,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.
|
||||
*/
|
||||
@@ -301,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("location");
|
||||
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("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
} else {
|
||||
cg.printObjectHeader("UnaryOpExpression", 4);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_variable->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_ARRAY_APPEND_POINT_OP);
|
||||
cg.printPropertyHeader("location");
|
||||
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("location");
|
||||
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("location");
|
||||
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", 2);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("operation");
|
||||
cg.printValue(PHP_AWAIT_OP);
|
||||
cg.printPropertyHeader("location");
|
||||
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;
|
||||
|
||||
@@ -913,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("location");
|
||||
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("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -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", 2);
|
||||
cg.printPropertyHeader("className");
|
||||
StaticClassName::outputCodeModel(cg);
|
||||
cg.printPropertyHeader("propertyName");
|
||||
cg.printValue(m_varName);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -279,19 +279,6 @@ bool ClosureExpression::hasStaticLocalsImpl(ConstructPtr root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ClosureExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ClosureExpression", 3);
|
||||
cg.printPropertyHeader("function");
|
||||
m_func->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("capturedVariables");
|
||||
cg.printExpressionVector(m_vars);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -273,17 +273,6 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return actualType;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ConstantExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("SimpleVariableExpression", 2);
|
||||
cg.printPropertyHeader("name");
|
||||
cg.printValue(getNonNSOriginalName());
|
||||
cg.printPropertyHeader("location");
|
||||
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("location");
|
||||
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("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -119,21 +119,6 @@ bool EncapsListExpression::canonCompare(ExpressionPtr e) const {
|
||||
return m_type == el->m_type;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EncapsListExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("EncapsListExpression", 2);
|
||||
cg.printPropertyHeader("delimiter");
|
||||
cg.printValue(m_type);
|
||||
if (m_exps) {
|
||||
cg.printPropertyHeader("expressions");
|
||||
cg.printExpressionVector(m_exps);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -36,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; \
|
||||
@@ -350,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) {
|
||||
}
|
||||
|
||||
@@ -248,6 +249,19 @@ void ExpressionList::stripConcat() {
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
@@ -464,15 +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];
|
||||
cg.printExpression(exp, exp?exp->hasContext(RefParameter):false);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -75,6 +75,14 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -273,19 +273,6 @@ TypePtr ListAssignment::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return m_array->inferAndCheck(ar, Type::Variant, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ListAssignment::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ListAssignmentExpression", 3);
|
||||
cg.printPropertyHeader("variables");
|
||||
cg.printExpressionVector(m_variables);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_array->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -131,29 +131,6 @@ TypePtr ModifierExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return TypePtr();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ModifierExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printf("V:6:\"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
|
||||
|
||||
|
||||
@@ -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("location");
|
||||
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("location");
|
||||
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("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -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:6:\"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("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -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("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -384,45 +384,6 @@ std::string ScalarExpression::getIdentifier() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ScalarExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ScalarExpression", 2);
|
||||
cg.printPropertyHeader("value");
|
||||
switch (m_type) {
|
||||
case T_CONSTANT_ENCAPSED_STRING:
|
||||
case T_ENCAPSED_AND_WHITESPACE:
|
||||
case T_STRING:
|
||||
case T_NUM_STRING:
|
||||
cg.printValue(m_value);
|
||||
break;
|
||||
case T_LNUMBER:
|
||||
case T_COMPILER_HALT_OFFSET:
|
||||
cg.printValue((int64_t)strtoll(m_value.c_str(), nullptr, 0));
|
||||
break;
|
||||
case T_LINE:
|
||||
cg.printValue(String(m_translated).toInt64());
|
||||
break;
|
||||
case T_TRAIT_C:
|
||||
case T_CLASS_C:
|
||||
case T_NS_C:
|
||||
case T_METHOD_C:
|
||||
case T_FUNC_C:
|
||||
cg.printValue(m_translated);
|
||||
break;
|
||||
case T_DNUMBER:
|
||||
cg.printValue(String(m_value).toDouble());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ScalarExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
switch (m_type) {
|
||||
case T_CONSTANT_ENCAPSED_STRING:
|
||||
|
||||
@@ -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 &&
|
||||
@@ -575,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);
|
||||
}
|
||||
@@ -608,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;
|
||||
@@ -957,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) {
|
||||
@@ -972,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()) {
|
||||
@@ -996,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()) {
|
||||
@@ -1041,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
|
||||
@@ -1273,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");
|
||||
}
|
||||
m_nameExp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("arguments");
|
||||
cg.printExpressionVector(m_params);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(m_nameExp->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
|
||||
bool isDefineWithoutImpl(AnalysisResultConstPtr ar);
|
||||
void setValid() { m_valid = true; }
|
||||
void setFromCompiler() { m_fromCompiler = true; }
|
||||
void setThrowFatal() { m_type = FunType::ThrowFatal; }
|
||||
void setThrowParseFatal() { m_type = FunType::ThrowParseFatal; }
|
||||
bool isParseFatalFunction() const {
|
||||
@@ -77,21 +78,8 @@ public:
|
||||
void updateVtFlags();
|
||||
void setLocalThis(const std::string &name) { m_localThis = name; }
|
||||
bool isCallToFunction(const char *name) const;
|
||||
bool isCompilerCallToFunction(const char *name) const;
|
||||
void resolveNSFallbackFunc(AnalysisResultConstPtr ar, FileScopePtr fs);
|
||||
|
||||
void setOptimizable() {
|
||||
m_optimizable = true;
|
||||
}
|
||||
bool isOptimizable() const {
|
||||
return m_optimizable;
|
||||
}
|
||||
void changeToBytecode() {
|
||||
m_changedToBytecode = true;
|
||||
}
|
||||
virtual bool allowCellByRef() const override {
|
||||
return m_changedToBytecode;
|
||||
}
|
||||
|
||||
protected:
|
||||
enum class FunType {
|
||||
Unknown,
|
||||
@@ -119,11 +107,11 @@ protected:
|
||||
FunType m_type;
|
||||
unsigned m_dynamicConstant : 1;
|
||||
unsigned m_builtinFunction : 1;
|
||||
unsigned m_fromCompiler : 1;
|
||||
unsigned m_invokeFewArgsDecision : 1;
|
||||
unsigned m_dynamicInvoke : 1;
|
||||
unsigned m_transformed : 1;
|
||||
unsigned m_changedToBytecode : 1; // true if it morphed into a bytecode
|
||||
unsigned m_optimizable : 1; // true if it can be morphed into a bytecode
|
||||
unsigned m_no_volatile_check : 1;
|
||||
|
||||
int m_safe;
|
||||
ExpressionPtr m_safeDef;
|
||||
|
||||
@@ -307,17 +307,6 @@ TypePtr SimpleVariable::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
|
||||
return actual;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SimpleVariable::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("SimpleVariableExpression", 2);
|
||||
cg.printPropertyHeader("variableName");
|
||||
cg.printValue(m_name);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -167,20 +167,6 @@ bool StaticClassName::checkPresent() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void StaticClassName::outputCodeModel(CodeGenerator &cg) {
|
||||
if (isSelf()) {
|
||||
cg.printf("self");
|
||||
} else if (isParent()) {
|
||||
cg.printf("parent");
|
||||
} else if (isStatic()) {
|
||||
cg.printf("static");
|
||||
} else {
|
||||
cg.printf("%s", m_origClassName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void StaticClassName::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
if (m_class) {
|
||||
m_class->outputPHP(cg, ar);
|
||||
|
||||
@@ -56,7 +56,6 @@ protected:
|
||||
std::string m_className;
|
||||
|
||||
void updateClassName();
|
||||
void outputCodeModel(CodeGenerator &cg);
|
||||
void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
|
||||
private:
|
||||
unsigned m_self : 1;
|
||||
|
||||
@@ -337,22 +337,6 @@ bool StaticMemberExpression::canonCompare(ExpressionPtr e) const {
|
||||
return m_className == s->m_className;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void StaticMemberExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ClassPropertyExpression", 2);
|
||||
cg.printPropertyHeader("className");
|
||||
StaticClassName::outputCodeModel(cg);
|
||||
if (m_exp->is(Expression::KindOfScalarExpression)) {
|
||||
cg.printPropertyHeader("propertyName");
|
||||
} else {
|
||||
cg.printPropertyHeader("propertyExpression");
|
||||
}
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "hphp/compiler/analysis/code_error.h"
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
#include "hphp/compiler/statement/statement_list.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/compiler/analysis/function_scope.h"
|
||||
@@ -568,80 +567,6 @@ ExpressionPtr UnaryOpExpression::unneededHelper() {
|
||||
return static_pointer_cast<Expression>(shared_from_this());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
switch (m_op) {
|
||||
case T_UNSET:
|
||||
case T_EXIT:
|
||||
case T_ARRAY:
|
||||
case T_ISSET:
|
||||
case T_EMPTY:
|
||||
case T_EVAL: {
|
||||
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
|
||||
std::string funcName;
|
||||
switch (m_op) {
|
||||
case T_UNSET: funcName = "unset"; break;
|
||||
case T_EXIT: funcName = "exit"; break;
|
||||
case T_ARRAY: funcName = "array"; break;
|
||||
case T_ISSET: funcName = "isset"; break;
|
||||
case T_EMPTY: funcName = "empty"; break;
|
||||
case T_EVAL: funcName = "eval"; break;
|
||||
default: break;
|
||||
}
|
||||
cg.printPropertyHeader("functionName");
|
||||
cg.printValue(funcName);
|
||||
cg.printPropertyHeader("arguments");
|
||||
printf("V:6:\"Vector\":1:{");
|
||||
m_exp->outputCodeModel(cg);
|
||||
printf("}");
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cg.printObjectHeader("UnaryOpExpression", 3);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("operation");
|
||||
int op = 0;
|
||||
switch (m_op) {
|
||||
case T_CLONE: op = PHP_CLONE_OP; break;
|
||||
case T_INC:
|
||||
op = m_front ? PHP_PRE_INCREMENT_OP : PHP_POST_INCREMENT_OP;
|
||||
break;
|
||||
case T_DEC:
|
||||
op = m_front ? PHP_PRE_DECREMENT_OP : PHP_POST_DECREMENT_OP;
|
||||
break;
|
||||
case '+': op = PHP_PLUS_OP; break;
|
||||
case '-': op = PHP_MINUS_OP; break;
|
||||
case '!': op = PHP_NOT_OP; break;
|
||||
case '~': op = PHP_BITWISE_NOT_OP; break;
|
||||
case T_INT_CAST: op = PHP_INT_CAST_OP; break;
|
||||
case T_DOUBLE_CAST: op = PHP_FLOAT_CAST_OP; break;
|
||||
case T_STRING_CAST: op = PHP_STRING_CAST_OP; break;
|
||||
case T_ARRAY_CAST: op = PHP_ARRAY_CAST_OP; break;
|
||||
case T_OBJECT_CAST: op = PHP_OBJECT_CAST_OP; break;
|
||||
case T_BOOL_CAST: op = PHP_BOOL_CAST_OP; break;
|
||||
case T_UNSET_CAST: op = PHP_UNSET_CAST_OP; break;
|
||||
case '@': op = PHP_ERROR_CONTROL_OP; break;
|
||||
case T_INCLUDE: op = PHP_INCLUDE_OP; break;
|
||||
case T_INCLUDE_ONCE: op = PHP_INCLUDE_ONCE_OP; break;
|
||||
case T_REQUIRE: op = PHP_REQUIRE_OP; break;
|
||||
case T_REQUIRE_ONCE: op = PHP_REQUIRE_ONCE_OP; break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
cg.printValue(op);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -15,17 +15,10 @@
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/expression/user_attribute.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/compiler/expression/unary_op_expression.h"
|
||||
#include "hphp/parser/scanner.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DECLARE_BOOST_TYPES(Expression);
|
||||
DECLARE_BOOST_TYPES(ExpressionList);
|
||||
DECLARE_BOOST_TYPES(UnaryOpExpression);
|
||||
|
||||
// constructors/destructors
|
||||
|
||||
UserAttribute::UserAttribute
|
||||
@@ -58,32 +51,6 @@ TypePtr UserAttribute::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return TypePtr();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UserAttribute::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("CodeAttribute", m_exp != nullptr ? 3 : 2);
|
||||
cg.printPropertyHeader("attributeName");
|
||||
cg.printValue(m_name);
|
||||
if (m_exp != nullptr && m_exp->is(Expression::KindOfUnaryOpExpression)) {
|
||||
UnaryOpExpressionPtr u(static_pointer_cast<UnaryOpExpression>(m_exp));
|
||||
if (u->getOp() == T_ARRAY) {
|
||||
ExpressionPtr ex = u->getExpression();
|
||||
if (ex->is(Expression::KindOfExpressionList)) {
|
||||
ExpressionListPtr el(static_pointer_cast<ExpressionList>(ex));
|
||||
cg.printPropertyHeader("expressions");
|
||||
cg.printExpressionVector(el);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ void YieldExpression::analyzeProgram(AnalysisResultPtr ar) {
|
||||
if (m_keyExp) {
|
||||
m_keyExp->analyzeProgram(ar);
|
||||
}
|
||||
m_valExp->setChildOfYield();
|
||||
m_valExp->analyzeProgram(ar);
|
||||
|
||||
m_label.setNew();
|
||||
@@ -95,21 +96,6 @@ TypePtr YieldExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
return Type::Variant;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void YieldExpression::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("YieldExpression", m_keyExp != nullptr ? 3 : 2);
|
||||
cg.printPropertyHeader("expression");
|
||||
if (m_keyExp != nullptr) {
|
||||
cg.printPropertyHeader("key");
|
||||
m_keyExp->outputCodeModel(cg);
|
||||
}
|
||||
cg.printPropertyHeader("value");
|
||||
m_valExp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
@@ -118,6 +118,7 @@ bool Option::EnableHipHopExperimentalSyntax = false;
|
||||
bool Option::EnableShortTags = true;
|
||||
bool Option::EnableAspTags = false;
|
||||
bool Option::EnableXHP = false;
|
||||
bool Option::EnableFinallyStatement = false;
|
||||
int Option::ParserThreadCount = 0;
|
||||
|
||||
int Option::GetScannerType() {
|
||||
@@ -130,7 +131,10 @@ int Option::GetScannerType() {
|
||||
}
|
||||
|
||||
int Option::InvokeFewArgsCount = 6;
|
||||
bool Option::InvokeWithSpecificArgs = true;
|
||||
bool Option::FlattenInvoke = true;
|
||||
int Option::InlineFunctionThreshold = -1;
|
||||
bool Option::UseVirtualDispatch = false;
|
||||
bool Option::EliminateDeadCode = true;
|
||||
bool Option::CopyProp = false;
|
||||
bool Option::LocalCopyProp = true;
|
||||
@@ -141,7 +145,6 @@ bool Option::VariableCoalescing = false;
|
||||
bool Option::ArrayAccessIdempotent = false;
|
||||
bool Option::DumpAst = false;
|
||||
bool Option::WholeProgram = true;
|
||||
bool Option::UseHHBBC = getenv("HHVM_HHBBC");
|
||||
bool Option::RecordErrors = true;
|
||||
std::string Option::DocJson;
|
||||
|
||||
@@ -150,6 +153,8 @@ bool Option::AllVolatile = false;
|
||||
|
||||
StringBag Option::OptionStrings;
|
||||
|
||||
bool Option::GenerateCppLibCode = false;
|
||||
bool Option::GenerateSourceInfo = false;
|
||||
bool Option::GenerateDocComments = true;
|
||||
|
||||
void (*Option::m_hookHandler)(Hdf &config);
|
||||
@@ -278,11 +283,16 @@ void Option::Load(Hdf &config) {
|
||||
ParserThreadCount = Process::GetCPUCount();
|
||||
}
|
||||
|
||||
EnableFinallyStatement = config["EnableFinallyStatement"].getBool();
|
||||
|
||||
EnableEval = (EvalLevel)config["EnableEval"].getByte(0);
|
||||
AllDynamic = config["AllDynamic"].getBool(true);
|
||||
AllVolatile = config["AllVolatile"].getBool();
|
||||
|
||||
GenerateCppLibCode = config["GenerateCppLibCode"].getBool(false);
|
||||
GenerateSourceInfo = config["GenerateSourceInfo"].getBool(false);
|
||||
GenerateDocComments = config["GenerateDocComments"].getBool(true);
|
||||
UseVirtualDispatch = config["UseVirtualDispatch"].getBool(false);
|
||||
EliminateDeadCode = config["EliminateDeadCode"].getBool(true);
|
||||
CopyProp = config["CopyProp"].getBool(false);
|
||||
LocalCopyProp = config["LocalCopyProp"].getBool(true);
|
||||
@@ -293,7 +303,6 @@ void Option::Load(Hdf &config) {
|
||||
ArrayAccessIdempotent = config["ArrayAccessIdempotent"].getBool(false);
|
||||
DumpAst = config["DumpAst"].getBool(false);
|
||||
WholeProgram = config["WholeProgram"].getBool(true);
|
||||
UseHHBBC = config["UseHHBBC"].getBool(UseHHBBC);
|
||||
|
||||
// Temporary, during file-cache migration.
|
||||
FileCache::UseNewCache = config["UseNewCache"].getBool(false);
|
||||
|
||||
@@ -222,6 +222,7 @@ public:
|
||||
static bool EnableShortTags;
|
||||
static bool EnableAspTags;
|
||||
static bool EnableXHP;
|
||||
static bool EnableFinallyStatement;
|
||||
static int ParserThreadCount;
|
||||
|
||||
static int GetScannerType();
|
||||
@@ -237,7 +238,10 @@ public:
|
||||
* Optimizations
|
||||
*/
|
||||
static int InvokeFewArgsCount;
|
||||
static bool InvokeWithSpecificArgs;
|
||||
static bool FlattenInvoke;
|
||||
static int InlineFunctionThreshold;
|
||||
static bool UseVirtualDispatch;
|
||||
static bool EliminateDeadCode;
|
||||
static bool CopyProp;
|
||||
static bool LocalCopyProp;
|
||||
@@ -248,12 +252,13 @@ public:
|
||||
/**
|
||||
* Output options
|
||||
*/
|
||||
static bool GenerateCppLibCode;
|
||||
static bool GenerateSourceInfo;
|
||||
static bool GenerateDocComments;
|
||||
static bool ControlFlow;
|
||||
static bool VariableCoalescing;
|
||||
static bool DumpAst;
|
||||
static bool WholeProgram;
|
||||
static bool UseHHBBC; // see hhbbc/README
|
||||
static bool RecordErrors;
|
||||
static std::string DocJson; // filename to dump doc JSON to
|
||||
|
||||
|
||||
@@ -193,14 +193,14 @@ FileCachePtr Package::getFileCache() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ParserWorker :
|
||||
public JobQueueWorker<std::pair<const char *,bool>, Package*, true, true> {
|
||||
public JobQueueWorker<std::pair<const char *,bool>, true, true> {
|
||||
public:
|
||||
bool m_ret;
|
||||
ParserWorker() : m_ret(true) {}
|
||||
virtual void doJob(JobType job) {
|
||||
bool ret;
|
||||
try {
|
||||
Package *package = m_context;
|
||||
Package *package = (Package*)m_opaque;
|
||||
ret = package->parseImpl(job.first);
|
||||
} catch (Exception &e) {
|
||||
Logger::Error("%s", e.getMessage().c_str());
|
||||
@@ -222,7 +222,8 @@ void Package::addSourceFile(const char *fileName, bool check /* = false */) {
|
||||
Lock lock(m_mutex);
|
||||
bool inserted = m_filesToParse.insert(Util::canonicalize(fileName)).second;
|
||||
if (inserted && m_dispatcher) {
|
||||
((JobQueueDispatcher<ParserWorker>*)m_dispatcher)->enqueue(
|
||||
((JobQueueDispatcher<ParserWorker::JobType,
|
||||
ParserWorker>*)m_dispatcher)->enqueue(
|
||||
std::make_pair(m_files.add(fileName), check));
|
||||
}
|
||||
}
|
||||
@@ -239,7 +240,7 @@ bool Package::parse(bool check) {
|
||||
}
|
||||
if (threadCount <= 0) threadCount = 1;
|
||||
|
||||
JobQueueDispatcher<ParserWorker>
|
||||
JobQueueDispatcher<ParserWorker::JobType, ParserWorker>
|
||||
dispatcher(threadCount, true, 0, false, this);
|
||||
|
||||
m_dispatcher = &dispatcher;
|
||||
|
||||
+4046
-4137
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -100,17 +100,13 @@
|
||||
#endif
|
||||
|
||||
#define NEW_EXP0(cls) \
|
||||
cls##Ptr(new cls(BlockScopePtr(), \
|
||||
getLocation()))
|
||||
cls##Ptr(new cls(BlockScopePtr(), getLocation()))
|
||||
#define NEW_EXP(cls, e...) \
|
||||
cls##Ptr(new cls(BlockScopePtr(), \
|
||||
getLocation(), ##e))
|
||||
cls##Ptr(new cls(BlockScopePtr(), getLocation(), ##e))
|
||||
#define NEW_STMT0(cls) \
|
||||
cls##Ptr(new cls(BlockScopePtr(), getLabelScope(), \
|
||||
getLocation()))
|
||||
cls##Ptr(new cls(BlockScopePtr(), getLocation()))
|
||||
#define NEW_STMT(cls, e...) \
|
||||
cls##Ptr(new cls(BlockScopePtr(), getLabelScope(), \
|
||||
getLocation(), ##e))
|
||||
cls##Ptr(new cls(BlockScopePtr(), getLocation(), ##e))
|
||||
|
||||
#define PARSE_ERROR(fmt, args...) HPHP_PARSER_ERROR(fmt, this, ##args)
|
||||
|
||||
@@ -155,8 +151,7 @@ StatementListPtr Parser::ParseString(const String& input, AnalysisResultPtr ar,
|
||||
Parser::Parser(Scanner &scanner, const char *fileName,
|
||||
AnalysisResultPtr ar, int fileSize /* = 0 */)
|
||||
: ParserBase(scanner, fileName), m_ar(ar), m_lambdaMode(false),
|
||||
m_closureGenerator(false), m_nsState(SeenNothing),
|
||||
m_aliasTable(getAutoAliasedClasses(), [&] { return isAutoAliasOn(); }) {
|
||||
m_closureGenerator(false), m_nsState(SeenNothing) {
|
||||
string md5str = Eval::FileRepository::unitMd5(scanner.getMd5());
|
||||
MD5 md5 = MD5(md5str.c_str());
|
||||
|
||||
@@ -217,6 +212,10 @@ string Parser::errString() {
|
||||
return m_error.empty() ? getMessage() : m_error;
|
||||
}
|
||||
|
||||
bool Parser::enableFinallyStatement() {
|
||||
return Option::EnableFinallyStatement;
|
||||
}
|
||||
|
||||
void Parser::pushComment() {
|
||||
m_comments.push_back(m_scanner.detachDocComment());
|
||||
}
|
||||
@@ -249,39 +248,6 @@ void Parser::completeScope(BlockScopePtr inner) {
|
||||
}
|
||||
}
|
||||
|
||||
LabelScopePtr Parser::getLabelScope() const {
|
||||
DCHECK(!m_labelScopes.empty());
|
||||
DCHECK(!m_labelScopes.back().empty());
|
||||
DCHECK(m_labelScopes.back().back() != nullptr);
|
||||
return m_labelScopes.back().back();
|
||||
}
|
||||
|
||||
void Parser::onNewLabelScope(bool fresh) {
|
||||
if (fresh) {
|
||||
m_labelScopes.push_back(LabelScopePtrVec());
|
||||
}
|
||||
DCHECK(!m_labelScopes.empty());
|
||||
LabelScopePtr labelScope(new LabelScope());
|
||||
m_labelScopes.back().push_back(labelScope);
|
||||
}
|
||||
|
||||
void Parser::onScopeLabel(const Token& stmt, const Token& label) {
|
||||
DCHECK(!m_labelScopes.empty());
|
||||
DCHECK(!m_labelScopes.back().empty());
|
||||
for (auto& scope : m_labelScopes.back()) {
|
||||
scope->addLabel(stmt.stmt, label.text());
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::onCompleteLabelScope(bool fresh) {
|
||||
assert(!m_labelScopes.empty());
|
||||
assert(!m_labelScopes.back().empty());
|
||||
m_labelScopes.back().pop_back();
|
||||
if (fresh) {
|
||||
m_labelScopes.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// variables
|
||||
|
||||
@@ -420,7 +386,7 @@ void Parser::onCallParam(Token &out, Token *params, Token &expr, bool ref) {
|
||||
}
|
||||
|
||||
void Parser::onCall(Token &out, bool dynamic, Token &name, Token ¶ms,
|
||||
Token *cls) {
|
||||
Token *cls, bool fromCompiler) {
|
||||
ExpressionPtr clsExp;
|
||||
if (cls) {
|
||||
clsExp = cls->exp;
|
||||
@@ -429,6 +395,7 @@ void Parser::onCall(Token &out, bool dynamic, Token &name, Token ¶ms,
|
||||
out->exp = NEW_EXP(DynamicFunctionCall, name->exp,
|
||||
dynamic_pointer_cast<ExpressionList>(params->exp),
|
||||
clsExp);
|
||||
assert(!fromCompiler);
|
||||
} else {
|
||||
const string &s = name.text();
|
||||
// strip out namespaces for func_get_args and friends check
|
||||
@@ -448,13 +415,8 @@ void Parser::onCall(Token &out, bool dynamic, Token &name, Token ¶ms,
|
||||
(new RealSimpleFunctionCall
|
||||
(BlockScopePtr(), getLocation(), name->text(), name->num() & 2,
|
||||
dynamic_pointer_cast<ExpressionList>(params->exp), clsExp));
|
||||
if (m_scanner.isHHSyntaxEnabled() && !(name->num() & 2)) {
|
||||
// If the function name is without any backslashes or
|
||||
// namespace qualification then we treat this as a candidate
|
||||
// for optimization via bytecode promotion.
|
||||
// "idx" is the only function in that class for now but it's
|
||||
// cheaper to set the bit that to check for the function name
|
||||
call->setOptimizable();
|
||||
if (fromCompiler) {
|
||||
call->setFromCompiler();
|
||||
}
|
||||
out->exp = call;
|
||||
|
||||
@@ -944,7 +906,7 @@ StatementPtr Parser::onFunctionHelper(FunctionType type,
|
||||
|
||||
StatementListPtr stmts = stmt->stmt || stmt->num() != 1 ?
|
||||
dynamic_pointer_cast<StatementList>(stmt->stmt)
|
||||
: NEW_STMT0(StatementList);
|
||||
: NEW_EXP0(StatementList);
|
||||
|
||||
ExpressionListPtr old_params =
|
||||
dynamic_pointer_cast<ExpressionList>(params->exp);
|
||||
@@ -1048,8 +1010,7 @@ void Parser::onParam(Token &out, Token *params, Token &type, Token &var,
|
||||
void Parser::onClassStart(int type, Token &name) {
|
||||
const Type::TypePtrMap& typeHintTypes =
|
||||
Type::GetTypeHintTypes(m_scanner.isHHSyntaxEnabled());
|
||||
if (0 == strcasecmp("self", name.text().c_str()) ||
|
||||
0 == strcasecmp("parent", name.text().c_str()) ||
|
||||
if (name.text() == "self" || name.text() == "parent" ||
|
||||
typeHintTypes.find(name.text()) != typeHintTypes.end()) {
|
||||
PARSE_ERROR("Cannot use '%s' as class name as it is reserved",
|
||||
name.text().c_str());
|
||||
@@ -1670,18 +1631,12 @@ void Parser::onTry(Token &out, Token &tryStmt, Token &className, Token &var,
|
||||
out->stmt = NEW_STMT(TryStatement, tryStmt->stmt,
|
||||
dynamic_pointer_cast<StatementList>(stmtList),
|
||||
finallyStmt->stmt);
|
||||
if (tryStmt->stmt) {
|
||||
out->stmt->setLabelScope(stmtList->getLabelScope());
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::onTry(Token &out, Token &tryStmt, Token &finallyStmt) {
|
||||
out->stmt = NEW_STMT(TryStatement, tryStmt->stmt,
|
||||
dynamic_pointer_cast<StatementList>(NEW_STMT0(StatementList)),
|
||||
finallyStmt->stmt);
|
||||
if (tryStmt->stmt) {
|
||||
out->stmt->setLabelScope(tryStmt->stmt->getLabelScope());
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::onCatch(Token &out, Token &catches, Token &className, Token &var,
|
||||
@@ -1699,11 +1654,6 @@ void Parser::onCatch(Token &out, Token &catches, Token &className, Token &var,
|
||||
|
||||
void Parser::onFinally(Token &out, Token &stmt) {
|
||||
out->stmt = NEW_STMT(FinallyStatement, stmt->stmt);
|
||||
// TODO (#3271396) This can be greatly improved. In particular
|
||||
// even when a finally block exists inside a function it is often
|
||||
// the case that the unnamed locals state & ret are not needed.
|
||||
// See task description for further details.
|
||||
m_file->setAttribute(FileScope::NeedsFinallyLocals);
|
||||
}
|
||||
|
||||
void Parser::onThrow(Token &out, Token &expr) {
|
||||
@@ -1825,86 +1775,6 @@ void Parser::onTypeSpecialization(Token& type, char specialization) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// namespace support
|
||||
|
||||
//////////////////// AliasTable /////////////////////
|
||||
|
||||
Parser::AliasTable::AliasTable(const std::vector<AliasEntry>& autoAliases,
|
||||
std::function<bool ()> autoOracle) :
|
||||
m_autoAliases(autoAliases), m_autoOracle(autoOracle),
|
||||
m_alreadyImported(false) {
|
||||
|
||||
if (!m_autoOracle) {
|
||||
setFalseOracle();
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::AliasTable::setFalseOracle() {
|
||||
m_autoOracle = [] () { return false; };
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the auto-imports to the map.
|
||||
* This is called by all the other operations, so the auto-import occurs
|
||||
* on-demand.
|
||||
*/
|
||||
void Parser::AliasTable::addAutoImports() {
|
||||
if (!m_alreadyImported && m_autoOracle()) {
|
||||
m_alreadyImported = true;
|
||||
|
||||
for (auto entry : m_autoAliases) {
|
||||
m_aliases[entry.alias] = (NameEntry){entry.name, true};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Parser::AliasTable::getName(std::string alias) {
|
||||
addAutoImports();
|
||||
auto it = m_aliases.find(alias);
|
||||
return (m_aliases.end() == it) ? "" : it->second.name;
|
||||
}
|
||||
|
||||
bool Parser::AliasTable::isAliased(std::string alias) {
|
||||
addAutoImports();
|
||||
return m_aliases.find(alias) != m_aliases.end();
|
||||
}
|
||||
|
||||
bool Parser::AliasTable::isAutoImported(std::string alias) {
|
||||
addAutoImports();
|
||||
auto it = m_aliases.find(alias);
|
||||
return it != m_aliases.end() && it->second.isAuto;
|
||||
}
|
||||
|
||||
void Parser::AliasTable::map(std::string alias, std::string name) {
|
||||
addAutoImports();
|
||||
m_aliases[alias] = (NameEntry){name, false};
|
||||
}
|
||||
|
||||
/*
|
||||
* To be called when we enter a fresh namespace.
|
||||
*/
|
||||
void Parser::AliasTable::clear() {
|
||||
m_aliases.clear();
|
||||
m_alreadyImported = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
* We auto-alias classes on HH mode and only if we're in the global namespace.
|
||||
*/
|
||||
bool Parser::isAutoAliasOn() {
|
||||
return m_scanner.isHHSyntaxEnabled() && ("" == m_namespace);
|
||||
}
|
||||
|
||||
std::vector<Parser::AliasTable::AliasEntry> Parser::getAutoAliasedClasses() {
|
||||
std::vector<AliasTable::AliasEntry> aliases;
|
||||
aliases.push_back(
|
||||
(AliasTable::AliasEntry){"Traversable", "HH\\Traversable"});
|
||||
aliases.push_back(
|
||||
(AliasTable::AliasEntry){"Iterator", "HH\\Iterator"});
|
||||
return aliases;
|
||||
}
|
||||
|
||||
void Parser::nns(int token) {
|
||||
if (m_nsState == SeenNamespaceStatement && token != ';') {
|
||||
error("No code may exist outside of namespace {}: %s",
|
||||
@@ -1930,9 +1800,10 @@ void Parser::onNamespaceStart(const std::string &ns,
|
||||
|
||||
m_nsState = InsideNamespace;
|
||||
m_nsFileScope = file_scope;
|
||||
m_aliases.clear();
|
||||
pushComment();
|
||||
|
||||
m_namespace = ns;
|
||||
m_aliasTable.clear();
|
||||
}
|
||||
|
||||
void Parser::onNamespaceEnd() {
|
||||
@@ -1949,17 +1820,12 @@ void Parser::onUse(const std::string &ns, const std::string &as) {
|
||||
key = ns.substr(pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// It's not an error if the alias already exists but is auto-imported.
|
||||
// In that case, it gets replaced.
|
||||
if (m_aliasTable.isAliased(key) && !m_aliasTable.isAutoImported(key) &&
|
||||
m_aliasTable.getName(key) != ns) {
|
||||
if (m_aliases.find(key) != m_aliases.end() && m_aliases[key] != ns) {
|
||||
error("Cannot use %s as %s because the name is already in use: %s",
|
||||
ns.c_str(), key.c_str(), getMessage().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
m_aliasTable.map(key, ns);
|
||||
m_aliases[key] = ns;
|
||||
}
|
||||
|
||||
std::string Parser::nsDecl(const std::string &name) {
|
||||
@@ -1976,16 +1842,15 @@ std::string Parser::resolve(const std::string &ns, bool cls) {
|
||||
alias = ns.substr(0, pos);
|
||||
}
|
||||
|
||||
if (m_aliasTable.isAliased(alias)) {
|
||||
auto name = m_aliasTable.getName(alias);
|
||||
|
||||
hphp_string_imap<std::string>::const_iterator iter = m_aliases.find(alias);
|
||||
if (iter != m_aliases.end()) {
|
||||
// Was it a namespace alias?
|
||||
if (pos != string::npos) {
|
||||
return name + ns.substr(pos);
|
||||
return iter->second + ns.substr(pos);
|
||||
}
|
||||
// Only classes can appear directly in "use" statements
|
||||
if (cls) {
|
||||
return name;
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2050,7 +1915,7 @@ void Parser::registerAlias(std::string name) {
|
||||
size_t pos = name.rfind(NAMESPACE_SEP);
|
||||
if (pos != string::npos) {
|
||||
string key = name.substr(pos + 1);
|
||||
m_aliasTable.map(key, name);
|
||||
m_aliases[key] = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#ifndef incl_HPHP_COMPILER_PARSER_H_
|
||||
#define incl_HPHP_COMPILER_PARSER_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "hphp/runtime/base/exceptions.h"
|
||||
#include "hphp/parser/parser.h"
|
||||
#include "hphp/compiler/construct.h"
|
||||
@@ -55,7 +53,6 @@ namespace HPHP {
|
||||
DECLARE_BOOST_TYPES(Expression);
|
||||
DECLARE_BOOST_TYPES(Statement);
|
||||
DECLARE_BOOST_TYPES(StatementList);
|
||||
DECLARE_BOOST_TYPES(LabelScope);
|
||||
DECLARE_BOOST_TYPES(Location);
|
||||
DECLARE_BOOST_TYPES(AnalysisResult);
|
||||
DECLARE_BOOST_TYPES(BlockScope);
|
||||
@@ -127,6 +124,7 @@ public:
|
||||
virtual bool parseImpl();
|
||||
bool parse();
|
||||
virtual void error(const char* fmt, ...) ATTRIBUTE_PRINTF(2,3);
|
||||
virtual bool enableFinallyStatement();
|
||||
IMPLEMENT_XHP_ATTRIBUTES;
|
||||
|
||||
virtual void fatal(const Location* loc, const char* msg);
|
||||
@@ -159,7 +157,8 @@ public:
|
||||
void onStaticMember(Token &out, Token &cls, Token &name);
|
||||
void onRefDim(Token &out, Token &var, Token &offset);
|
||||
void onCallParam(Token &out, Token *params, Token &expr, bool ref);
|
||||
void onCall(Token &out, bool dynamic, Token &name, Token ¶ms, Token *cls);
|
||||
void onCall(Token &out, bool dynamic, Token &name, Token ¶ms,
|
||||
Token *cls, bool fromCompiler = false);
|
||||
void onEncapsList(Token &out, int type, Token &list);
|
||||
void addEncap(Token &out, Token *list, Token &expr, int type);
|
||||
void encapRefDim(Token &out, Token &var, Token &offset);
|
||||
@@ -275,36 +274,6 @@ public:
|
||||
std::string nsDecl(const std::string &name);
|
||||
std::string resolve(const std::string &ns, bool cls);
|
||||
|
||||
/*
|
||||
* Get the current label scope. A new label scope is demarcated by
|
||||
* one of the following: a loop, a switch statement, a finally block,
|
||||
* a try block or one of the constructs demarcating variables scopes
|
||||
* (i.e. functions, closures, etc.)
|
||||
* For every label scope, we keep track of the labels
|
||||
* that are available inside it. This is required for supporting
|
||||
* features such as try ... finally.
|
||||
*/
|
||||
LabelScopePtr getLabelScope() const;
|
||||
|
||||
/*
|
||||
* Called whenever a new label scope is entered. The fresh parameter
|
||||
* indicates whether the scope is also a variable scope (i.e. a
|
||||
* function, a closure, ...) or just a label scope (i.e. a loop body,
|
||||
* a switch statement, a finally block, ...).
|
||||
*/
|
||||
void onNewLabelScope(bool fresh);
|
||||
|
||||
/*
|
||||
* Called whenever a new label is encountered.
|
||||
*/
|
||||
void onScopeLabel(const Token& stmt, const Token& label);
|
||||
|
||||
/*
|
||||
* Called whenever a label scope ends. The fresh parameter has the
|
||||
* same meaning as for onNewLabelScope.
|
||||
*/
|
||||
void onCompleteLabelScope(bool fresh);
|
||||
|
||||
virtual void invalidateGoto(TStatementPtr stmt, GotoError error);
|
||||
virtual void invalidateLabel(TStatementPtr stmt);
|
||||
|
||||
@@ -339,7 +308,6 @@ private:
|
||||
FileScopePtr m_file;
|
||||
std::vector<std::string> m_comments; // for docComment stack
|
||||
std::vector<BlockScopePtrVec> m_scopes;
|
||||
std::vector<LabelScopePtrVec> m_labelScopes;
|
||||
std::vector<FunctionContext> m_funcContexts;
|
||||
std::vector<std::vector<StatementPtr> > m_prependingStatements;
|
||||
std::vector<ScalarExpressionPtr> m_compilerHaltOffsetVec;
|
||||
@@ -401,57 +369,11 @@ private:
|
||||
SeenNamespaceStatement,
|
||||
InsideNamespace,
|
||||
};
|
||||
|
||||
/*
|
||||
* An AliasTable maps aliases to names.
|
||||
* We use it instead a regular map because it lazily imports a bunch of
|
||||
* names into the current namespace when appropriate.
|
||||
*/
|
||||
class AliasTable {
|
||||
public:
|
||||
|
||||
struct AliasEntry {
|
||||
std::string alias;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
AliasTable(const std::vector<AliasEntry>& autoAliases,
|
||||
std::function<bool ()> autoOracle);
|
||||
|
||||
std::string getName(std::string alias);
|
||||
bool isAliased(std::string alias);
|
||||
bool isAutoImported(std::string alias);
|
||||
void map(std::string alias, std::string name);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
||||
struct NameEntry {
|
||||
std::string name;
|
||||
bool isAuto; // Is the name automatically-imported?
|
||||
};
|
||||
|
||||
hphp_string_imap<NameEntry> m_aliases;
|
||||
// These get imported every time we enter a new namespace.
|
||||
std::vector<AliasEntry> m_autoAliases;
|
||||
// Returns true if stuff should be auto-imported.
|
||||
std::function<bool ()> m_autoOracle;
|
||||
// Have we already auto-imported names for the current namespace?
|
||||
// This is useful because auto-imports are done lazily.
|
||||
bool m_alreadyImported;
|
||||
|
||||
void setFalseOracle();
|
||||
void addAutoImports();
|
||||
};
|
||||
|
||||
NamespaceState m_nsState;
|
||||
bool m_nsFileScope;
|
||||
std::string m_namespace; // current namespace
|
||||
AliasTable m_aliasTable;
|
||||
|
||||
hphp_string_imap<std::string> m_aliases;
|
||||
void registerAlias(std::string name);
|
||||
bool isAutoAliasOn();
|
||||
std::vector<AliasTable::AliasEntry> getAutoAliasedClasses();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -93,19 +93,6 @@ void BlockStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
if (m_stmts) m_stmts->inferTypes(ar);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BlockStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("BlockStatement", m_stmts != nullptr ? 2 : 1);
|
||||
if (m_stmts != nullptr) {
|
||||
cg.printPropertyHeader("statements");
|
||||
m_stmts->outputCodeModel(cg);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -75,21 +75,6 @@ StatementPtr BreakStatement::preOptimize(AnalysisResultConstPtr ar) {
|
||||
void BreakStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BreakStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
if (strncmp(m_name, "break", 5)) {
|
||||
cg.printObjectHeader("BreakStatement", 2);
|
||||
} else {
|
||||
cg.printObjectHeader("ContinueStatement", 2);
|
||||
}
|
||||
cg.printPropertyHeader("depth");
|
||||
cg.printValue((int)m_depth);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -118,26 +118,6 @@ void CaseStatement::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
|
||||
if (m_stmt) m_stmt->inferTypes(ar);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CaseStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 1;
|
||||
if (m_condition != nullptr) numProps++;
|
||||
if (m_stmt != nullptr) numProps++;
|
||||
cg.printObjectHeader("CaseStatement", numProps);
|
||||
if (m_condition != nullptr) {
|
||||
cg.printPropertyHeader("condition");
|
||||
m_condition->outputCodeModel(cg);
|
||||
}
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -134,25 +134,6 @@ void CatchStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
if (m_stmt) m_stmt->inferTypes(ar);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CatchStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 3;
|
||||
if (m_stmt != nullptr) numProps++;
|
||||
cg.printObjectHeader("CatchStatement", numProps);
|
||||
cg.printPropertyHeader("className");
|
||||
cg.printValue(m_origClassName);
|
||||
cg.printPropertyHeader("variableName");
|
||||
cg.printValue(m_variable->getName());
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -130,17 +130,6 @@ void ClassConstant::inferTypes(AnalysisResultPtr ar) {
|
||||
m_exp->inferAndCheck(ar, Type::Some, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ClassConstant::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ConstantStatement", 2);
|
||||
cg.printPropertyHeader("expressions");
|
||||
cg.printExpressionVector(m_exp);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "hphp/util/util.h"
|
||||
#include "hphp/compiler/statement/interface_statement.h"
|
||||
#include "hphp/compiler/statement/use_trait_statement.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
@@ -212,59 +211,6 @@ void ClassStatement::analyzeProgram(AnalysisResultPtr ar) {
|
||||
void ClassStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ClassStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 4;
|
||||
if (m_attrList != nullptr) numProps++;
|
||||
if (m_type == T_ABSTRACT || m_type == T_FINAL) numProps++;
|
||||
if (!m_parent.empty()) numProps++;
|
||||
if (m_base != nullptr) numProps++;
|
||||
if (m_stmt != nullptr) numProps++;
|
||||
if (!m_docComment.empty()) numProps++;
|
||||
|
||||
cg.printObjectHeader("TypeStatement", numProps);
|
||||
if (m_attrList != nullptr) {
|
||||
cg.printPropertyHeader("attributes");
|
||||
cg.printExpressionVector(m_attrList);
|
||||
}
|
||||
if (m_type == T_ABSTRACT) {
|
||||
cg.printPropertyHeader("modifiers");
|
||||
cg.printModifierVector("abstract");
|
||||
} else if (m_type == T_FINAL) {
|
||||
cg.printPropertyHeader("modifiers");
|
||||
cg.printModifierVector("final");
|
||||
}
|
||||
cg.printPropertyHeader("kind");
|
||||
if (m_type == T_TRAIT) {
|
||||
cg.printValue(PHP_TRAIT);
|
||||
} else {
|
||||
cg.printValue(PHP_CLASS);
|
||||
}
|
||||
cg.printPropertyHeader("name");
|
||||
cg.printValue(m_originalName);
|
||||
//TODO: type parameters (task 3262469)
|
||||
if (!m_parent.empty()) {
|
||||
cg.printPropertyHeader("baseClass");
|
||||
cg.printTypeExpression(m_originalParent);
|
||||
}
|
||||
if (m_base != nullptr) {
|
||||
cg.printPropertyHeader("interfaces");
|
||||
cg.printExpressionVector(m_base);
|
||||
}
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
if (!m_docComment.empty()) {
|
||||
cg.printPropertyHeader("comments");
|
||||
cg.printValue(m_docComment);
|
||||
}
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -279,19 +279,6 @@ void ClassVariable::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ClassVariable::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ClassVariableStatement", 3);
|
||||
cg.printPropertyHeader("modifiers");
|
||||
m_modifiers->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("expressions");
|
||||
cg.printExpressionVector(m_declaration);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -90,21 +90,6 @@ void DoStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DoStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("DoStatement", m_stmt != nullptr ? 3 : 2);
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("condition");
|
||||
m_condition->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -81,17 +81,6 @@ void EchoStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
m_exp->inferAndCheck(ar, Type::String, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EchoStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("EchoStatement", 2);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -96,17 +96,6 @@ void ExpStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
m_exp->inferAndCheck(ar, Type::Any, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ExpStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ExpressionStatement", 2);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -92,19 +92,6 @@ void FinallyStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
if (m_stmt) m_stmt->inferTypes(ar);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FinallyStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("FinallyStatement", m_stmt == nullptr ? 1 : 2);
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -120,36 +120,6 @@ void ForStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ForStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 1;
|
||||
if (m_exp1 != nullptr) numProps++;
|
||||
if (m_exp2 != nullptr) numProps++;
|
||||
if (m_exp3 != nullptr) numProps++;
|
||||
if (m_stmt != nullptr) numProps++;
|
||||
cg.printObjectHeader("ForStatement", numProps);
|
||||
if (m_exp1 != nullptr) {
|
||||
cg.printPropertyHeader("expression1");
|
||||
m_exp1->outputCodeModel(cg);
|
||||
}
|
||||
if (m_exp2 != nullptr) {
|
||||
cg.printPropertyHeader("expression2");
|
||||
m_exp2->outputCodeModel(cg);
|
||||
}
|
||||
if (m_exp3 != nullptr) {
|
||||
cg.printPropertyHeader("expression3");
|
||||
m_exp3->outputCodeModel(cg);
|
||||
}
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -151,30 +151,6 @@ void ForEachStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ForEachStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 3;
|
||||
if (m_name != nullptr) numProps++;
|
||||
if (m_stmt != nullptr) numProps++;
|
||||
cg.printObjectHeader("ForeachStatement", numProps);
|
||||
cg.printPropertyHeader("collection");
|
||||
m_array->outputCodeModel(cg);
|
||||
if (m_name != nullptr) {
|
||||
cg.printPropertyHeader("key");
|
||||
m_name->outputCodeModel(cg);
|
||||
}
|
||||
cg.printPropertyHeader("value");
|
||||
cg.printExpression(m_value, m_ref);
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -132,12 +132,6 @@ void FunctionStatement::analyzeProgram(AnalysisResultPtr ar) {
|
||||
void FunctionStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FunctionStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
MethodStatement::outputCodeModel(cg);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -135,17 +135,6 @@ void GlobalStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GlobalStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("GlobalStatement", 2);
|
||||
cg.printPropertyHeader("expressions");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -86,17 +86,6 @@ void GotoStatement::setNthKid(int n, ConstructPtr cp) {
|
||||
void GotoStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GotoStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("GotoStatement", 2);
|
||||
cg.printPropertyHeader("label");
|
||||
cg.printValue(m_label);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -83,25 +83,6 @@ void IfBranchStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
if (m_stmt) m_stmt->inferTypes(ar);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IfBranchStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
if (m_condition == nullptr) {
|
||||
if (m_stmt != nullptr) m_stmt->outputCodeModel(cg);
|
||||
return;
|
||||
}
|
||||
cg.printObjectHeader("ConditionalStatement", 3);
|
||||
cg.printPropertyHeader("condition");
|
||||
m_condition->outputCodeModel(cg);
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("trueBlock");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -216,41 +216,6 @@ void IfStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
if (m_stmts) m_stmts->inferTypes(ar);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IfStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
for (int i = 0; i < m_stmts->getCount(); i++) {
|
||||
IfBranchStatementPtr branch =
|
||||
dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
|
||||
assert(branch != nullptr); // this cast always succeeds, by construction.
|
||||
auto condition = branch->getCondition();
|
||||
auto statements = branch->getStmt();
|
||||
auto numProps = 1;
|
||||
if (condition != nullptr) numProps++;
|
||||
if (statements != nullptr) numProps++;
|
||||
if (i < m_stmts->getCount() - 1) numProps++;
|
||||
if (i > 0) {
|
||||
cg.printPropertyHeader("falseBlock");
|
||||
if (i < m_stmts->getCount() - 1) {
|
||||
printf("V:6:\"Vector\":1:{");
|
||||
}
|
||||
}
|
||||
if (condition != nullptr) {
|
||||
cg.printObjectHeader("ConditionalStatement", 3);
|
||||
cg.printPropertyHeader("condition");
|
||||
condition->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("trueBlock");
|
||||
}
|
||||
if (statements != nullptr) {
|
||||
cg.printAsBlock(statements);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < m_stmts->getCount() - 1; i++) {
|
||||
cg.printf("}");
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "hphp/compiler/analysis/variable_table.h"
|
||||
#include "hphp/util/util.h"
|
||||
#include "hphp/compiler/option.h"
|
||||
#include "hphp/compiler/code_model_enums.h"
|
||||
#include "hphp/compiler/parser/parser.h"
|
||||
|
||||
using namespace HPHP;
|
||||
@@ -253,42 +252,6 @@ StatementPtr InterfaceStatement::preOptimize(AnalysisResultConstPtr ar) {
|
||||
void InterfaceStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InterfaceStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 3;
|
||||
if (m_attrList != nullptr) numProps++;
|
||||
if (m_base != nullptr) numProps++;
|
||||
if (m_stmt != nullptr) numProps++;
|
||||
if (!m_docComment.empty()) numProps++;
|
||||
|
||||
cg.printObjectHeader("TypeStatement", numProps);
|
||||
if (m_attrList != nullptr) {
|
||||
cg.printPropertyHeader("attributes");
|
||||
cg.printExpressionVector(m_attrList);
|
||||
}
|
||||
cg.printPropertyHeader("kind");
|
||||
cg.printValue(PHP_INTERFACE);
|
||||
cg.printPropertyHeader("name");
|
||||
cg.printValue(m_originalName);
|
||||
//TODO: type parameters (task 3262469)
|
||||
if (m_base != nullptr) {
|
||||
cg.printPropertyHeader("interfaces");
|
||||
cg.printExpressionVector(m_base);
|
||||
}
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
if (!m_docComment.empty()) {
|
||||
cg.printPropertyHeader("comments");
|
||||
cg.printValue(m_docComment);
|
||||
}
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -67,17 +67,6 @@ void LabelStatement::setNthKid(int n, ConstructPtr cp) {
|
||||
void LabelStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LabelStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("LabelStatement", 2);
|
||||
cg.printPropertyHeader("label");
|
||||
cg.printValue(m_label);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -547,8 +547,7 @@ void MethodStatement::inferFunctionTypes(AnalysisResultPtr ar) {
|
||||
Variant(Variant::NullInit()));
|
||||
ReturnStatementPtr returnStmt =
|
||||
ReturnStatementPtr(
|
||||
new ReturnStatement(getScope(), getLabelScope(),
|
||||
getLocation(), constant));
|
||||
new ReturnStatement(getScope(), getLocation(), constant));
|
||||
m_stmt->addElement(returnStmt);
|
||||
}
|
||||
}
|
||||
@@ -563,51 +562,6 @@ void MethodStatement::inferFunctionTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MethodStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 3;
|
||||
if (m_attrList != nullptr) numProps++;
|
||||
if (m_ref) numProps++;
|
||||
if (m_params != nullptr) numProps++;
|
||||
if (m_retTypeAnnotation != nullptr) numProps++;
|
||||
if (m_stmt != nullptr) numProps++;
|
||||
if (!m_docComment.empty()) numProps++;
|
||||
cg.printObjectHeader("FunctionStatement", numProps);
|
||||
if (m_attrList != nullptr) {
|
||||
cg.printPropertyHeader("attributes");
|
||||
cg.printExpressionVector(m_attrList);
|
||||
}
|
||||
cg.printPropertyHeader("modifiers");
|
||||
m_modifiers->outputCodeModel(cg);
|
||||
if (m_ref) {
|
||||
cg.printPropertyHeader("returnsReference");
|
||||
cg.printValue(m_ref);
|
||||
}
|
||||
cg.printPropertyHeader("name");
|
||||
cg.printValue(m_originalName);
|
||||
//TODO: type parameters (task 3262469)
|
||||
if (m_params != nullptr) {
|
||||
cg.printPropertyHeader("parameters");
|
||||
cg.printExpressionVector(m_params);
|
||||
}
|
||||
if (m_retTypeAnnotation != nullptr) {
|
||||
cg.printPropertyHeader("returnType");
|
||||
m_retTypeAnnotation->outputCodeModel(cg);
|
||||
}
|
||||
if (m_stmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_stmt);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
if (!m_docComment.empty()) {
|
||||
cg.printPropertyHeader("comments");
|
||||
cg.printValue(m_docComment);
|
||||
}
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -115,20 +115,6 @@ void ReturnStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ReturnStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto nump = m_exp ? 2 : 1;
|
||||
cg.printObjectHeader("ReturnStatement", nump);
|
||||
if (m_exp) {
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -28,10 +28,7 @@ const char *Statement::Names[] = {
|
||||
};
|
||||
|
||||
Statement::Statement(STATEMENT_CONSTRUCTOR_BASE_PARAMETERS)
|
||||
: Construct(scope, loc),
|
||||
m_kindOf(kindOf),
|
||||
m_labelScope(labelScope) {
|
||||
DCHECK(m_labelScope != nullptr);
|
||||
: Construct(scope, loc), m_kindOf(kindOf) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -18,23 +18,19 @@
|
||||
#define incl_HPHP_STATEMENT_H_
|
||||
|
||||
#include "hphp/compiler/expression/expression.h"
|
||||
#include "hphp/compiler/analysis/label_scope.h"
|
||||
#include <string>
|
||||
|
||||
#define STATEMENT_CONSTRUCTOR_BASE_PARAMETERS \
|
||||
BlockScopePtr scope, LabelScopePtr labelScope, LocationPtr loc, \
|
||||
Statement::KindOf kindOf
|
||||
BlockScopePtr scope, LocationPtr loc, Statement::KindOf kindOf
|
||||
#define STATEMENT_CONSTRUCTOR_BASE_PARAMETER_VALUES \
|
||||
scope, labelScope, loc, kindOf
|
||||
scope, loc, kindOf
|
||||
#define STATEMENT_CONSTRUCTOR_PARAMETERS \
|
||||
BlockScopePtr scope, LabelScopePtr labelScope, LocationPtr loc
|
||||
BlockScopePtr scope, LocationPtr loc
|
||||
#define STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(kindOf) \
|
||||
scope, labelScope, loc, Statement::KindOf##kindOf
|
||||
scope, loc, Statement::KindOf##kindOf
|
||||
#define DECLARE_BASE_STATEMENT_VIRTUAL_FUNCTIONS \
|
||||
virtual void analyzeProgram(AnalysisResultPtr ar); \
|
||||
virtual StatementPtr clone(); \
|
||||
virtual void inferTypes(AnalysisResultPtr ar); \
|
||||
virtual void outputCodeModel(CodeGenerator &cg); \
|
||||
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
|
||||
#define DECLARE_STATEMENT_VIRTUAL_FUNCTIONS \
|
||||
DECLARE_BASE_STATEMENT_VIRTUAL_FUNCTIONS; \
|
||||
@@ -42,15 +38,12 @@
|
||||
virtual int getKidCount() const; \
|
||||
virtual void setNthKid(int n, ConstructPtr cp)
|
||||
#define NULL_STATEMENT() \
|
||||
BlockStatementPtr(new BlockStatement(getScope(), \
|
||||
getLabelScope(), \
|
||||
getLocation(), \
|
||||
BlockStatementPtr(new BlockStatement(getScope(), getLocation(), \
|
||||
StatementListPtr()))
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DECLARE_BOOST_TYPES(Statement);
|
||||
DECLARE_BOOST_TYPES(LabelScope);
|
||||
|
||||
#define DECLARE_STATEMENT_TYPES(x) \
|
||||
x(FunctionStatement), \
|
||||
@@ -156,14 +149,10 @@ public:
|
||||
|
||||
virtual int getRecursiveCount() const { return 1; }
|
||||
|
||||
LabelScopePtr getLabelScope() { return m_labelScope; }
|
||||
void setLabelScope(LabelScopePtr labelScope) { m_labelScope = labelScope; }
|
||||
|
||||
protected:
|
||||
KindOf m_kindOf;
|
||||
int m_silencerCountMax;
|
||||
int m_silencerCountCurrent;
|
||||
LabelScopePtr m_labelScope;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -262,8 +262,7 @@ bool StatementList::mergeConcatAssign() {
|
||||
var, exp1, T_CONCAT_EQUAL));
|
||||
}
|
||||
expStmt = ExpStatementPtr
|
||||
(new ExpStatement(getScope(), getLabelScope(),
|
||||
getLocation(), exp));
|
||||
(new ExpStatement(getScope(), getLocation(), exp));
|
||||
|
||||
m_stmts[i - length] = expStmt;
|
||||
for (j = i - (length - 1); i > j; i--) removeElement(j);
|
||||
@@ -414,14 +413,6 @@ void StatementList::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void StatementList::outputCodeModel(CodeGenerator &cg) {
|
||||
for (unsigned int i = 0; i < m_stmts.size(); i++) {
|
||||
m_stmts[i]->outputCodeModel(cg);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -188,17 +188,6 @@ void StaticStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
scope->getVariables()->clearAttribute(VariableTable::InsideStaticStatement);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void StaticStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("StaticStatement", 2);
|
||||
cg.printPropertyHeader("expressions");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -185,24 +185,6 @@ void SwitchStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SwitchStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 2;
|
||||
if (m_cases != nullptr) numProps++;
|
||||
|
||||
cg.printObjectHeader("SwitchStatement", numProps);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
if (m_cases != nullptr) {
|
||||
cg.printPropertyHeader("caseStatements");
|
||||
cg.printStatementVector(m_cases);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -73,17 +73,6 @@ void ThrowStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
m_exp->inferAndCheck(ar, Type::Object, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ThrowStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("ThrowStatement", 2);
|
||||
cg.printPropertyHeader("expression");
|
||||
m_exp->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -103,28 +103,6 @@ void TraitAliasStatement::setNthKid(int n, ConstructPtr cp) {
|
||||
void TraitAliasStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TraitAliasStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto propCount = 3;
|
||||
auto traitName = m_traitName->getString();
|
||||
if (!traitName.empty()) propCount++;
|
||||
cg.printObjectHeader("TraitAliasStatement", propCount);
|
||||
if (!traitName.empty()) {
|
||||
cg.printPropertyHeader("traitName");
|
||||
cg.printValue(traitName);
|
||||
}
|
||||
cg.printPropertyHeader("methodName1");
|
||||
m_methodName->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("modifiers");
|
||||
m_modifiers->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("methodName2");
|
||||
m_newMethodName->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -107,21 +107,6 @@ void TraitPrecStatement::setNthKid(int n, ConstructPtr cp) {
|
||||
void TraitPrecStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TraitPrecStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
cg.printObjectHeader("TraitInsteadStatement", 3);
|
||||
cg.printPropertyHeader("traitName");
|
||||
m_traitName->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("methodName");
|
||||
m_methodName->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("otherTraitNames");
|
||||
cg.printExpressionVector(m_otherTraitNames);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -126,31 +126,6 @@ void TryStatement::inferTypes(AnalysisResultPtr ar) {
|
||||
if (m_finallyStmt) m_finallyStmt->inferTypes(ar);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TryStatement::outputCodeModel(CodeGenerator &cg) {
|
||||
auto numProps = 1;
|
||||
if (m_tryStmt != nullptr) numProps++;
|
||||
if (m_catches->getCount() > 0) numProps++;
|
||||
if (m_finallyStmt != nullptr) numProps++;
|
||||
cg.printObjectHeader("TryStatement", numProps);
|
||||
if (m_tryStmt != nullptr) {
|
||||
cg.printPropertyHeader("block");
|
||||
cg.printAsBlock(m_tryStmt);
|
||||
}
|
||||
if (m_catches->getCount() > 0) {
|
||||
cg.printPropertyHeader("catchStatements");
|
||||
cg.printStatementVector(m_catches);
|
||||
}
|
||||
if (m_finallyStmt != nullptr) {
|
||||
cg.printPropertyHeader("finallyStatement");
|
||||
m_finallyStmt->outputCodeModel(cg);
|
||||
}
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
|
||||
@@ -56,17 +56,6 @@ void TypedefStatement::analyzeProgram(AnalysisResultPtr) {}
|
||||
|
||||
void TypedefStatement::inferTypes(AnalysisResultPtr) {}
|
||||
|
||||
void TypedefStatement::outputCodeModel(CodeGenerator& cg) {
|
||||
cg.printObjectHeader("TypedefStatement", 3);
|
||||
cg.printPropertyHeader("name");
|
||||
cg.printValue(name);
|
||||
cg.printPropertyHeader("typeAnnotation");
|
||||
annot->outputCodeModel(cg);
|
||||
cg.printPropertyHeader("location");
|
||||
cg.printLocation(this->getLocation());
|
||||
cg.printObjectFooter();
|
||||
}
|
||||
|
||||
void TypedefStatement::outputPHP(CodeGenerator& cg, AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
|
||||
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