Comparar commits
120 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| b74a0da062 | |||
| e663cfb0fd | |||
| b3b41e08bb | |||
| 3e24e506f4 | |||
| ef1d4c9c1e | |||
| cee31f4412 | |||
| 65d2487ab7 | |||
| 67013476b5 | |||
| 2b3ae234fb | |||
| 6fed85fbb4 | |||
| bd2e014e8f | |||
| c8cc07a61c | |||
| 26c4d57cfa | |||
| f58323820c | |||
| 2f9f1a705b | |||
| 387a3555e2 | |||
| 8a119496e1 | |||
| 5662a67f12 | |||
| ac63ae02c6 | |||
| f3a6aaee37 | |||
| bbdf9729fb | |||
| 09e01875a0 | |||
| 26a6669575 | |||
| 162b46fb99 | |||
| f5188b8fe9 | |||
| 0f9c93f9f9 | |||
| 5ed74f1e03 | |||
| d9943ae3c5 | |||
| f109b02c7d | |||
| ac0ec5696a | |||
| 64b6d99ef2 | |||
| e300bc8cce | |||
| bc6703d03f | |||
| aee58ac19e | |||
| c375ba70b0 | |||
| 1643cb1d17 | |||
| 51f0a5bd3b | |||
| 8572bdeb7f | |||
| cf7133b406 | |||
| a44b190095 | |||
| e69e05711a | |||
| 3cf77e2df9 | |||
| 7fd841e6c1 | |||
| f3ddbe63f1 | |||
| 1e4b0ed05b | |||
| 2406e11d44 | |||
| 1e54607680 | |||
| 28116234fb | |||
| 337f15cc8d | |||
| a18dd73d06 | |||
| 067e38c23d | |||
| 2db86bd721 | |||
| 527a155239 | |||
| 1bc06a26cf | |||
| 76681bfc14 | |||
| 740868989c | |||
| 26c2654528 | |||
| bab632f35a | |||
| 51ffd22f03 | |||
| 03c8d47acb | |||
| a4903eb14e | |||
| 9efb3c8e25 | |||
| c21f2c3966 | |||
| 3a5087077f | |||
| dc8cc4656b | |||
| 00b2101db0 | |||
| 3248a83461 | |||
| 14c9e841c8 | |||
| 839bb3103e | |||
| dec99505a6 | |||
| f3cf268bb1 | |||
| 5455370de0 | |||
| 116bb2c662 | |||
| cc5cc6d5cb | |||
| cc863bf301 | |||
| e09dbb6f89 | |||
| 5acac417e2 | |||
| b17ec4702a | |||
| f6efec4d7c | |||
| 75948e48f7 | |||
| 3286e1d7c0 | |||
| d6be84e026 | |||
| 0763e566f4 | |||
| 8c57d016d5 | |||
| 44dc3b58f4 | |||
| b24236e602 | |||
| dbab820ff4 | |||
| 441fb578ec | |||
| 755d38157f | |||
| 4196354f4f | |||
| f7dd399bd6 | |||
| 0b586489c9 | |||
| 31222e2c84 | |||
| d87811fd9b | |||
| 6492f650f5 | |||
| d09fd3e421 | |||
| 5baef2646d | |||
| 22541f491c | |||
| a4b2eea173 | |||
| e3d0c97679 | |||
| 795400d899 | |||
| 5483751a25 | |||
| 4797536f9d | |||
| c67d35c50a | |||
| 453c9938c9 | |||
| 3e19c90b93 | |||
| bed8c0e6fe | |||
| 1b83a11ee8 | |||
| 94081c2cbc | |||
| c7959bbe6a | |||
| 94aed72d26 | |||
| 6ac06a50eb | |||
| 5e7c9d3457 | |||
| 1eeb100510 | |||
| 6a4ec5ae0e | |||
| 52697c84a0 | |||
| c4956fac10 | |||
| ddd8720bf4 | |||
| 84d9aa7236 | |||
| 363d1bb20f |
+38
-78
@@ -8,102 +8,62 @@
|
||||
.mkdir
|
||||
hphp.log
|
||||
|
||||
/src/test/test
|
||||
/src/test/test_fast.inc
|
||||
/src/test/test_mysql_info.inc
|
||||
/src/test/test_suite.inc
|
||||
/src/test/real_mysql_info.inc
|
||||
/src/test/*.tmp
|
||||
/src/test/vm/*.out
|
||||
/src/test/vm/*.diff
|
||||
/src/test/vm/*.log
|
||||
/src/test/vm/*.reduce_out
|
||||
/src/test/vm/*.reduce_diff
|
||||
/src/test/vm/*.reduce_exp
|
||||
/src/test/vm/*.perf
|
||||
/src/test/vm/perf/*.out
|
||||
/src/test/vm/perf/*.diff
|
||||
/src/test/vm/perf/*.perf
|
||||
/src/runtime/ext_hhvm/xconstants.php
|
||||
/src/runtime/ext_hhvm/ext_hhvm_infotabs.cpp
|
||||
/src/runtime/ext_hhvm/ext_noinline.cpp
|
||||
/src/compiler/analysis/code_error.inc
|
||||
/hphp/test/test
|
||||
/hphp/test/test_fast.inc
|
||||
/hphp/test/test_mysql_info.inc
|
||||
/hphp/test/test_suite.inc
|
||||
/hphp/test/real_mysql_info.inc
|
||||
/hphp/test/*.tmp
|
||||
/hphp/test/vm/*.out
|
||||
/hphp/test/vm/*.diff
|
||||
/hphp/test/vm/*.log
|
||||
/hphp/test/vm/*.reduce_out
|
||||
/hphp/test/vm/*.reduce_diff
|
||||
/hphp/test/vm/*.reduce_exp
|
||||
/hphp/test/vm/*.perf
|
||||
/hphp/test/vm/perf/*.out
|
||||
/hphp/test/vm/perf/*.diff
|
||||
/hphp/test/vm/perf/*.perf
|
||||
/hphp/runtime/ext_hhvm/ext_noinline.cpp
|
||||
/hphp/compiler/analysis/code_error.inc
|
||||
|
||||
/src/runtime/tmp/Test*
|
||||
/src/runtime/tmp/run
|
||||
/src/runtime/tmp/run.sh
|
||||
/src/runtime/tmp/libtest.so
|
||||
/src/runtime/vm/repo_schema.h
|
||||
/src/runtime/base/compiler_id.h
|
||||
/hphp/runtime/tmp/Test*
|
||||
/hphp/runtime/tmp/run
|
||||
/hphp/runtime/tmp/run.sh
|
||||
/hphp/runtime/tmp/libtest.so
|
||||
/hphp/runtime/vm/repo_schema.h
|
||||
/hphp/runtime/base/compiler_id.h
|
||||
|
||||
/src/hphpi/gen
|
||||
/src/hphpi/hphpi
|
||||
/hphp/hphpi/gen
|
||||
/hphp/hphpi/hphpi
|
||||
|
||||
/src/hhvm/gen
|
||||
/src/hhvm/hhvm
|
||||
/src/hhvm/hphp
|
||||
/hphp/hhvm/gen
|
||||
/hphp/hhvm/hhvm
|
||||
|
||||
/src/tools/shmw/shmw
|
||||
/hphp/tools/shmw/shmw
|
||||
|
||||
/src/ffi/java/classes
|
||||
/src/ffi/java/hphp_ffi_java.h
|
||||
/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
|
||||
|
||||
/facebook/arcanist/.phutil_module_cache
|
||||
|
||||
/facebook/autoload_files
|
||||
/facebook/hotcold.hdf
|
||||
/facebook/benchmark/shootout/output_bench
|
||||
/facebook/benchmark/shootout/output_bintree_new
|
||||
/facebook/libcore_files
|
||||
/facebook/output_*
|
||||
/facebook/push/install
|
||||
/facebook/stub_funcs.hdf
|
||||
/facebook/volatile.hdf
|
||||
/facebook/www.pid
|
||||
|
||||
/facebook/push/apc
|
||||
/facebook/push/apclog
|
||||
/facebook/push/autoload_files
|
||||
/facebook/push/hotcold.hdf
|
||||
/facebook/push/output_www
|
||||
/facebook/push/system.tgz
|
||||
/facebook/push/volatile.hdf
|
||||
/facebook/push/stub_funcs.hdf
|
||||
/facebook/push/output
|
||||
/facebook/push/shared
|
||||
|
||||
/facebook/extensions/gen
|
||||
/facebook/extensions/hphpi
|
||||
/local/*.mk
|
||||
|
||||
CMakeFiles
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
|
||||
/output_gd/
|
||||
|
||||
/src/TAGS
|
||||
|
||||
# arcanist working-copy settings
|
||||
.arc/
|
||||
|
||||
# fbcode output directory
|
||||
/bin/_fbcode_bin/
|
||||
/hphp/TAGS
|
||||
|
||||
# Generated makefiles
|
||||
/src/third_party/lz4/Makefile
|
||||
/src/third_party/double-conversion/Makefile
|
||||
/src/third_party/folly/Makefile
|
||||
/src/runtime/ext_hhvm/Makefile
|
||||
/src/test/Makefile
|
||||
/src/hphp/Makefile
|
||||
/src/hhvm/Makefile
|
||||
/src/compiler/Makefile
|
||||
/src/Makefile
|
||||
/hphp/runtime/ext_hhvm/Makefile
|
||||
/hphp/test/Makefile
|
||||
/hphp/hphp/Makefile
|
||||
/hphp/hhvm/Makefile
|
||||
/hphp/compiler/Makefile
|
||||
/hphp/Makefile
|
||||
/Makefile
|
||||
|
||||
# eclipse files
|
||||
|
||||
+12
-12
@@ -134,15 +134,15 @@ find_package(EXPAT REQUIRED)
|
||||
include_directories(${EXPAT_INCLUDE_DIRS})
|
||||
|
||||
# SQLite3 + timelib are bundled in HPHP sources
|
||||
include_directories("${HPHP_HOME}/src/third_party/libsqlite3")
|
||||
include_directories("${HPHP_HOME}/src/third_party/timelib")
|
||||
include_directories("${HPHP_HOME}/src/third_party/libafdt/src")
|
||||
include_directories("${HPHP_HOME}/src/third_party/libmbfl")
|
||||
include_directories("${HPHP_HOME}/src/third_party/libmbfl/mbfl")
|
||||
include_directories("${HPHP_HOME}/src/third_party/libmbfl/filter")
|
||||
include_directories("${HPHP_HOME}/src/third_party/lz4")
|
||||
include_directories("${HPHP_HOME}/src/third_party/double-conversion/src")
|
||||
include_directories("${HPHP_HOME}/src/third_party/folly")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/libsqlite3")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/timelib")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/libafdt/src")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/libmbfl")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/libmbfl/mbfl")
|
||||
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")
|
||||
|
||||
FIND_LIBRARY(XHP_LIB xhp)
|
||||
FIND_PATH(XHP_INCLUDE_DIR xhp_preprocess.hpp)
|
||||
@@ -151,7 +151,7 @@ if (XHP_LIB AND XHP_INCLUDE_DIR)
|
||||
include_directories(${XHP_INCLUDE_DIR})
|
||||
set(SKIP_BUNDLED_XHP ON)
|
||||
else()
|
||||
include_directories("${HPHP_HOME}/src/third_party/xhp/xhp")
|
||||
include_directories("${HPHP_HOME}/hphp/third_party/xhp/xhp")
|
||||
endif()
|
||||
|
||||
# ICU
|
||||
@@ -351,8 +351,8 @@ endif()
|
||||
# message(FATAL_ERROR "Flex is too old, found ${FLEX_VERSION} and we need 2.5.33")
|
||||
#endif()
|
||||
|
||||
include_directories(${HPHP_HOME}/src)
|
||||
include_directories(${HPHP_HOME}/src/system/gen)
|
||||
include_directories(${HPHP_HOME}/hphp)
|
||||
include_directories(${HPHP_HOME}/hphp/system/gen)
|
||||
|
||||
macro(hphp_link target)
|
||||
if (GOOGLE_HEAP_PROFILER_ENABLED OR GOOGLE_CPU_PROFILER_ENABLED)
|
||||
|
||||
@@ -112,10 +112,10 @@ 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-60 -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(CMAKE_C_FLAGS "-w")
|
||||
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-60 -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")
|
||||
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")
|
||||
endif()
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||
@@ -126,6 +126,6 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET (CMAKE_CXX_FLAGS_RELEASE "-O3")
|
||||
ENDIF()
|
||||
|
||||
include_directories(${HPHP_HOME}/src)
|
||||
include_directories(${HPHP_HOME}/src/lib/system/gen)
|
||||
include_directories(${HPHP_HOME}/hphp)
|
||||
include_directories(${HPHP_HOME}/hphp/lib/system/gen)
|
||||
include_directories(${HPHP_HOME})
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/CMake/HPHPFunctions.cmake")
|
||||
include(CheckFunctionExists)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/hphp)
|
||||
|
||||
IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
message(FATAL_ERROR "32-bit support is currently unsupported, check back with a later version of HipHop")
|
||||
|
||||
+3
-5
@@ -179,16 +179,14 @@ class Exception {
|
||||
// Remove top stack frames up to and including Exception::__init__,
|
||||
// set the 'file' and 'line' properties appropriately
|
||||
while (!empty($this->trace)) {
|
||||
$top = $this->trace[0];
|
||||
$top = array_shift($this->trace);
|
||||
if (isset($top['class']) && isset($top['function']) &&
|
||||
strcasecmp($top['class'], 'exception') === 0 &&
|
||||
strcasecmp($top['function'], '__init__') === 0) {
|
||||
$frame = array_shift($this->trace);
|
||||
if (isset($frame['file'])) $this->file = $frame['file'];
|
||||
if (isset($frame['line'])) $this->line = $frame['line'];
|
||||
if (isset($top['file'])) $this->file = $top['file'];
|
||||
if (isset($top['line'])) $this->line = $top['line'];
|
||||
return;
|
||||
}
|
||||
array_shift($this->trace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#
|
||||
# +----------------------------------------------------------------------+
|
||||
# | HipHop for PHP |
|
||||
# +----------------------------------------------------------------------+
|
||||
# | Copyright (c) 2010 Facebook, Inc. (http://www.facebook.com) |
|
||||
# | Copyright (c) 1997-2010 The PHP Group |
|
||||
# +----------------------------------------------------------------------+
|
||||
# | This source file is subject to version 3.01 of the PHP license, |
|
||||
# | that is bundled with this package in the file LICENSE, and is |
|
||||
# | available through the world-wide-web at the following url: |
|
||||
# | http://www.php.net/license/3_01.txt |
|
||||
# | If you did not receive a copy of the PHP license and are unable to |
|
||||
# | obtain it through the world-wide-web, please send a note to |
|
||||
# | license@php.net so we can mail you a copy immediately. |
|
||||
# +----------------------------------------------------------------------+
|
||||
#
|
||||
|
||||
include(HPHPSetup)
|
||||
|
||||
if ("$ENV{USE_HHVM}" STREQUAL "1")
|
||||
# HHVM Build
|
||||
SET(USE_HHVM TRUE)
|
||||
SET(ENV{HHVM} 1)
|
||||
ADD_DEFINITIONS("-DHHVM -DHHVM_BINARY=1 -DHHVM_PATH=\\\"${HPHP_HOME}/hphp/hhvm/hhvm\\\"")
|
||||
|
||||
if ("$ENV{USE_HPHPC}" STREQUAL "1")
|
||||
message(FATAL_ERROR "Both USE_HHVM and USE_HPHPC are set, you may only select one")
|
||||
endif()
|
||||
else()
|
||||
# HPHPc Build
|
||||
SET(USE_HHVM FALSE)
|
||||
ADD_DEFINITIONS("-DHHVM_PATH=\"\"")
|
||||
|
||||
if (NOT "$ENV{USE_HPHPC}" STREQUAL "1")
|
||||
message(FATAL_ERROR "You must select which version of HipHop to build by setting either USE_HHVM=1 or USE_HPHPC=1 in your environment")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/eval runtime/ext runtime/vm system/gen system/lib util)
|
||||
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})
|
||||
|
||||
endforeach(dir ${RECURSIVE_SOURCE_SUBDIRS})
|
||||
|
||||
# Disable hardware counters off of Linux
|
||||
if(NOT LINUX)
|
||||
add_definitions(-DNO_HARDWARE_COUNTERS)
|
||||
list(REMOVE_ITEM CXX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/runtime/base/hardware_counter.cpp)
|
||||
endif()
|
||||
|
||||
# remove ext_hhvm, util/tests, and runtime/vm/translator/test
|
||||
foreach (file ${CXX_SOURCES})
|
||||
if (${file} MATCHES "ext_hhvm")
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif()
|
||||
if (${file} MATCHES "util/test")
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif()
|
||||
if (${file} MATCHES "runtime/vm/translator/test")
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif()
|
||||
if (${file} MATCHES "runtime/vm/translator/hopt/test")
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif()
|
||||
endforeach(file ${CXX_SOURCES})
|
||||
|
||||
# remove ext/sep for hhvm
|
||||
if (USE_HHVM)
|
||||
foreach (file ${CXX_SOURCES})
|
||||
if (${file} MATCHES "ext/sep")
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif()
|
||||
endforeach(file ${CXX_SOURCES})
|
||||
endif(USE_HHVM)
|
||||
|
||||
|
||||
if (EXISTS "${hphp_SOURCE_DIR}/HPHP_EXCLUDE_FILES.txt")
|
||||
FILE(READ ${hphp_SOURCE_DIR}/HPHP_EXCLUDE_FILES.txt HPHP_EXCLUDE_FILES)
|
||||
STRING(REGEX REPLACE "[\n\r]" ";" HPHP_EXCLUDE_FILES "${HPHP_EXCLUDE_FILES}")
|
||||
else ()
|
||||
SET(HPHP_EXCLUDE_FILES)
|
||||
endif ()
|
||||
|
||||
foreach (t ${HPHP_EXCLUDE_FILES})
|
||||
string(SUBSTRING ${t} 0 1 T_FIRST_CHAR)
|
||||
if (${T_FIRST_CHAR} STREQUAL "D")
|
||||
|
||||
string(REGEX REPLACE "^[D]" "" SKIP_DIR "${t}")
|
||||
file(TO_CMAKE_PATH "${hphp_SOURCE_DIR}/${SKIP_DIR}" SKIP_DIR)
|
||||
string(LENGTH "${SKIP_DIR}" SKIP_DIR_LENGTH)
|
||||
|
||||
message(STATUS "Let's remove ${SKIP_DIR}")
|
||||
|
||||
foreach (file ${CXX_SOURCES})
|
||||
string(LENGTH "${file}" FILE_LENGTH)
|
||||
if (${FILE_LENGTH} GREATER ${SKIP_DIR_LENGTH})
|
||||
string(SUBSTRING ${file} 0 ${SKIP_DIR_LENGTH} FILE_PATH)
|
||||
if (${FILE_PATH} STREQUAL ${SKIP_DIR})
|
||||
list(REMOVE_ITEM CXX_SOURCES ${file})
|
||||
endif ()
|
||||
endif ()
|
||||
endforeach(file ${CXX_SOURCES})
|
||||
|
||||
elseif (${T_FIRST_CHAR} STREQUAL "#")
|
||||
|
||||
# doing nothing since this is a comment
|
||||
|
||||
else ()
|
||||
list(FIND CXX_SOURCES "${hphp_SOURCE_DIR}/${t}" FOUND_T)
|
||||
if (FOUND_T GREATER -1)
|
||||
LIST(REMOVE_AT CXX_SOURCES ${FOUND_T})
|
||||
endif()
|
||||
endif ()
|
||||
endforeach(t ${HPHP_EXCLUDE_FILES})
|
||||
|
||||
#FLEX_TARGET(HphpScanner ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/hphp.x ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/lex.eval_.cpp COMPILE_FLAGS " -w -i -Peval_")
|
||||
#BISON_TARGET(HphpParser ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/hphp.y ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/hphp.tab.cpp COMPILE_FLAGS " -v -d -p eval_")
|
||||
#ADD_FLEX_BISON_DEPENDENCY(HphpScanner HphpParser)
|
||||
|
||||
# required to remove warning when a file is there twice
|
||||
#list(REMOVE_ITEM CXX_SOURCES ${FLEX_HphpScanner_OUTPUTS} ${BISON_HphpParser_OUTPUTS})
|
||||
#list(APPEND CXX_SOURCES ${FLEX_HphpScanner_OUTPUTS} ${BISON_HphpParser_OUTPUTS})
|
||||
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||
|
||||
#add_library(sqlite3 STATIC "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libsqlite3/sqlite3.c")
|
||||
|
||||
#auto_sources(TIMELIB_SOURCES "*.c" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/third_party/timelib")
|
||||
#add_library(timelib STATIC ${TIMELIB_SOURCES})
|
||||
|
||||
if (NOT SKIP_BUNDLED_XHP)
|
||||
add_subdirectory(third_party/xhp/xhp)
|
||||
endif()
|
||||
|
||||
add_subdirectory(third_party/libafdt)
|
||||
add_subdirectory(third_party/libmbfl)
|
||||
add_subdirectory(third_party/libsqlite3)
|
||||
add_subdirectory(third_party/timelib)
|
||||
add_subdirectory(third_party/lz4)
|
||||
add_subdirectory(third_party/double-conversion)
|
||||
add_subdirectory(third_party/folly)
|
||||
|
||||
foreach (CXX_FILE ${CXX_SOURCES})
|
||||
if(${CXX_FILE} MATCHES ".no.cpp$")
|
||||
SET_SOURCE_FILES_PROPERTIES(
|
||||
${CXX_FILE}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS -O0
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT runtime/base/compiler_id.h
|
||||
COMMAND hphp/tools/generate_compiler_id.sh
|
||||
DEPENDS ${CXX_SOURCES} ${C_SOURCES}
|
||||
WORKING_DIRECTORY ${HPHP_HOME}
|
||||
COMMENT "Generating Compiler ID"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT runtime/vm/repo_schema.h
|
||||
COMMAND hphp/tools/generate_repo_schema.sh
|
||||
DEPENDS ${CXX_SOURCES} ${C_SOURCES}
|
||||
WORKING_DIRECTORY ${HPHP_HOME}
|
||||
COMMENT "Generating Repo Schema ID"
|
||||
VERBATIM)
|
||||
|
||||
ADD_LIBRARY(hphp_runtime_static STATIC runtime/vm/repo_schema.h runtime/base/compiler_id.h ${CXX_SOURCES} ${C_SOURCES})
|
||||
#ADD_LIBRARY(hphp_runtime SHARED ${C_SOURCES} ${CXX_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 PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
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_subdirectory(compiler)
|
||||
|
||||
if (USE_HHVM)
|
||||
add_subdirectory(runtime/ext_hhvm)
|
||||
endif()
|
||||
|
||||
add_subdirectory(hhvm)
|
||||
|
||||
if (NOT "$ENV{HPHP_NOTEST}" STREQUAL "1")
|
||||
add_subdirectory(test)
|
||||
endif ()
|
||||
+10
-10
@@ -1438,7 +1438,7 @@ ExpressionPtr AliasManager::canonicalizeNode(
|
||||
Expression::UnsetContext)) {
|
||||
ExpressionPtr rep;
|
||||
int interf =
|
||||
findInterf(e, true, rep, NULL, doArrayCSE);
|
||||
findInterf(e, true, rep, nullptr, doArrayCSE);
|
||||
add(m_accessList, e);
|
||||
if (interf == SameAccess) {
|
||||
if (e->getKindOf() == rep->getKindOf()) {
|
||||
@@ -1498,7 +1498,7 @@ ExpressionPtr AliasManager::canonicalizeNode(
|
||||
Expression::UnsetContext))) {
|
||||
ExpressionPtr rep;
|
||||
int interf =
|
||||
findInterf(e, true, rep, NULL, doArrayCSE);
|
||||
findInterf(e, true, rep, nullptr, doArrayCSE);
|
||||
if (!m_inPseudoMain && interf == DisjointAccess && !m_cleared &&
|
||||
e->is(Expression::KindOfSimpleVariable) &&
|
||||
!e->isThis()) {
|
||||
@@ -3669,7 +3669,7 @@ void AliasManager::doFinal(MethodStatementPtr m) {
|
||||
}
|
||||
|
||||
void AliasManager::performReferencedAndNeededAnalysis(MethodStatementPtr m) {
|
||||
always_assert(m_graph != NULL);
|
||||
always_assert(m_graph != nullptr);
|
||||
|
||||
// bail out for pseudomain context
|
||||
if (m->getScope()->inPseudoMain()) return;
|
||||
@@ -3696,7 +3696,7 @@ void AliasManager::performReferencedAndNeededAnalysis(MethodStatementPtr m) {
|
||||
}
|
||||
|
||||
int AliasManager::copyProp(MethodStatementPtr m) {
|
||||
if (m_graph == NULL) createCFG(m);
|
||||
if (m_graph == nullptr) createCFG(m);
|
||||
|
||||
performReferencedAndNeededAnalysis(m);
|
||||
|
||||
@@ -3719,13 +3719,13 @@ int AliasManager::copyProp(MethodStatementPtr m) {
|
||||
}
|
||||
|
||||
void AliasManager::deleteCFG() {
|
||||
assert(m_graph != NULL);
|
||||
assert(m_graph != nullptr);
|
||||
delete m_graph;
|
||||
m_graph = NULL;
|
||||
m_graph = nullptr;
|
||||
}
|
||||
|
||||
void AliasManager::createCFG(MethodStatementPtr m) {
|
||||
assert(m_graph == NULL);
|
||||
assert(m_graph == nullptr);
|
||||
m_graph = ControlFlowGraph::buildControlFlow(m);
|
||||
}
|
||||
|
||||
@@ -3735,7 +3735,7 @@ void AliasManager::insertTypeAssertions(AnalysisResultConstPtr ar,
|
||||
i.walk(m->getStmts());
|
||||
|
||||
if (Option::ControlFlow && Option::DumpAst) {
|
||||
if (m_graph != NULL) deleteCFG();
|
||||
if (m_graph != nullptr) deleteCFG();
|
||||
createCFG(m);
|
||||
printf("-------- BEGIN INSERTED -----------\n");
|
||||
m_graph->dump(m_arp);
|
||||
@@ -3750,7 +3750,7 @@ void AliasManager::removeTypeAssertions(AnalysisResultConstPtr ar,
|
||||
r.walk(m->getStmts());
|
||||
|
||||
if (Option::ControlFlow && Option::DumpAst) {
|
||||
if (m_graph != NULL) deleteCFG();
|
||||
if (m_graph != nullptr) deleteCFG();
|
||||
createCFG(m);
|
||||
printf("-------- BEGIN REMOVED -----------\n");
|
||||
m_graph->dump(m_arp);
|
||||
@@ -3778,7 +3778,7 @@ int AliasManager::optimize(AnalysisResultConstPtr ar, MethodStatementPtr m) {
|
||||
if (copyProp(m)) return 1;
|
||||
}
|
||||
|
||||
if (m_graph != NULL) deleteCFG();
|
||||
if (m_graph != nullptr) deleteCFG();
|
||||
|
||||
m_hasChainRoot = false;
|
||||
|
||||
+20
-20
@@ -74,7 +74,7 @@ IMPLEMENT_THREAD_LOCAL(BlockScopeRawPtrFlagsHashMap,
|
||||
AnalysisResult::AnalysisResult()
|
||||
: BlockScope("Root", "", StatementPtr(), BlockScope::ProgramScope),
|
||||
m_arrayLitstrKeyMaxSize(0), m_arrayIntegerKeyMaxSize(0),
|
||||
m_package(NULL), m_parseOnDemand(false), m_phase(ParseAllFiles),
|
||||
m_package(nullptr), m_parseOnDemand(false), m_phase(ParseAllFiles),
|
||||
m_scalarArraysCounter(0), m_paramRTTICounter(0),
|
||||
m_scalarArraySortedAvgLen(0), m_scalarArraySortedIndex(0),
|
||||
m_scalarArraySortedSumLen(0), m_scalarArrayCompressedTextSize(0),
|
||||
@@ -1611,7 +1611,7 @@ public:
|
||||
template<>
|
||||
void AnalysisResult::preWaitCallback<Post>(
|
||||
bool first, const BlockScopeRawPtrQueue &scopes, void *opaque) {
|
||||
assert(!Option::ControlFlow || opaque != NULL);
|
||||
assert(!Option::ControlFlow || opaque != nullptr);
|
||||
if (first && Option::ControlFlow) {
|
||||
JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *dispatcher
|
||||
= (JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *) opaque;
|
||||
@@ -1814,14 +1814,14 @@ void AnalysisResult::outputCPPNamedScalarVarIntegers(const std::string &file) {
|
||||
const vector<string> &strings = it->second;
|
||||
for (unsigned int i = 0; i < strings.size(); i++) {
|
||||
int64 val;
|
||||
sscanf(strings[i].c_str(), "%llx", &val);
|
||||
sscanf(strings[i].c_str(), "%" PRIx64, &val);
|
||||
Variant v(val);
|
||||
int64 *startp = (int64 *)&v;
|
||||
int64 *endp = (startp + multiple);
|
||||
for (int64 *p = startp; p < endp; p++) {
|
||||
cg_printf("0x%016llxLL, ", *p);
|
||||
cg_printf("0x%016" PRIx64 "L, ", *p);
|
||||
}
|
||||
cg_printf("// %lld\n", val);
|
||||
cg_printf("// %" PRId64 "\n", val);
|
||||
}
|
||||
}
|
||||
cg_indentEnd("};\n");
|
||||
@@ -1844,7 +1844,7 @@ void AnalysisResult::outputCPPNamedScalarVarIntegers(const std::string &file) {
|
||||
|
||||
void AnalysisResult::outputCPPFiniteDouble(CodeGenerator &cg, double dval) {
|
||||
assert(finite(dval));
|
||||
char *buf = NULL;
|
||||
char *buf = nullptr;
|
||||
if (dval == 0.0) dval = 0.0; // so to avoid "-0" output
|
||||
// 17 to ensure lossless conversion
|
||||
vspprintf(&buf, 0, "%.*G", 17, dval);
|
||||
@@ -1882,12 +1882,12 @@ void AnalysisResult::outputCPPNamedScalarVarDoubles(const std::string &file) {
|
||||
const vector<string> &strings = it->second;
|
||||
for (unsigned int i = 0; i < strings.size(); i++) {
|
||||
double val;
|
||||
sscanf(strings[i].c_str(), "%llx", (int64*)(&val));
|
||||
sscanf(strings[i].c_str(), "%" PRIx64, (int64*)(&val));
|
||||
Variant v(val);
|
||||
int64 *startp = (int64 *)&v;
|
||||
int64 *endp = (startp + multiple);
|
||||
for (int64 *p = startp; p < endp; p++) {
|
||||
cg_printf("0x%016llxLL, ", *p);
|
||||
cg_printf("0x%016" PRIx64 "L, ", *p);
|
||||
}
|
||||
cg_printf("// ");
|
||||
outputCPPFiniteDouble(cg, val);
|
||||
@@ -2511,7 +2511,7 @@ void AnalysisResult::outputAllCPP(CodeGenerator::Output output,
|
||||
{
|
||||
vector<OutputJob*> jobs;
|
||||
JobQueueDispatcher<OutputJob*, OutputWorker>
|
||||
dispatcher(threadCount, true, 0, false, NULL);
|
||||
dispatcher(threadCount, true, 0, false, nullptr);
|
||||
|
||||
string root = getOutputPath() + "/";
|
||||
for (StringToFileScopePtrVecMap::const_iterator iter = clusters.begin();
|
||||
@@ -2544,7 +2544,7 @@ void AnalysisResult::outputAllCPP(CodeGenerator::Output output,
|
||||
{
|
||||
vector<OutputJob*> jobs;
|
||||
JobQueueDispatcher<OutputJob*, OutputWorker>
|
||||
dispatcher(threadCount, true, 0, false, NULL);
|
||||
dispatcher(threadCount, true, 0, false, nullptr);
|
||||
|
||||
if (clusterCount > 0) {
|
||||
OutputJob *job = new RepartitionJob(ar, filenames, additionalCPPs);
|
||||
@@ -2809,7 +2809,7 @@ void AnalysisResult::outputCPPNameMaps() {
|
||||
char **params = (char **)calloc(m_paramRTTICounter, sizeof(char*));
|
||||
for (map<string, int>::const_iterator
|
||||
iter = m_paramRTTIs.begin(); iter != m_paramRTTIs.end(); ++iter) {
|
||||
assert(params[iter->second] == NULL);
|
||||
assert(params[iter->second] == nullptr);
|
||||
params[iter->second] = (char *)iter->first.c_str();
|
||||
}
|
||||
for (int i = 0; i < m_paramRTTICounter; i++) {
|
||||
@@ -2828,7 +2828,7 @@ void AnalysisResult::outputCPPNameMaps() {
|
||||
void AnalysisResult::outputRTTIMetaData(const char *filename) {
|
||||
assert(filename && *filename);
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (f == NULL) {
|
||||
if (f == nullptr) {
|
||||
throw Exception("Unable to open %s: %s", filename,
|
||||
Util::safe_strerror(errno).c_str());
|
||||
}
|
||||
@@ -2886,10 +2886,10 @@ void AnalysisResult::outputCPPUtilImpl(CodeGenerator::Output output) {
|
||||
for (set<int64>::const_iterator it = m_allIntegers.begin();
|
||||
it != m_allIntegers.end(); it++) {
|
||||
if (!String::HasConverted(*(it))) {
|
||||
if (*(it) == LONG_MIN) {
|
||||
cg_printf("(int64)0x%llxLL,\n", (uint64)LONG_MIN);
|
||||
if (*(it) == std::numeric_limits<int64_t>::min()) {
|
||||
cg_printf("(int64)0x8000000000000000LL,\n");
|
||||
} else {
|
||||
cg_printf("%lldLL,\n", *(it));
|
||||
cg_printf("%" PRId64 "L,\n", *(it));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4587,7 +4587,7 @@ void AnalysisResult::preGenerateCPP(CodeGenerator::Output output,
|
||||
AnalysisResultPtr ar = shared_from_this();
|
||||
vector<PreGenerateCPPJob*> jobs;
|
||||
JobQueueDispatcher<OutputJob*, OutputWorker>
|
||||
dispatcher(threadCount, true, 0, false, NULL);
|
||||
dispatcher(threadCount, true, 0, false, nullptr);
|
||||
|
||||
m_pregenerating = true;
|
||||
BOOST_FOREACH(FileScopePtr fs, files) {
|
||||
@@ -5065,7 +5065,7 @@ void AnalysisResult::outputStringProxyData(CodeGenerator &cg,
|
||||
cg_printf("%s,\n", lStrings[i].c_str());
|
||||
}
|
||||
for (uint i = 0; i < bStrings.size(); i++) {
|
||||
cg_printf("%s, (const char *)%lldLL,\n",
|
||||
cg_printf("%s, (const char *)%" PRId64 "L,\n",
|
||||
bStrings[i].first.c_str(), (int64)bStrings[i].second);
|
||||
}
|
||||
cg_indentEnd("};\n");
|
||||
@@ -5306,7 +5306,7 @@ void AnalysisResult::outputCPPSepExtensionMake() {
|
||||
for (unsigned int i = 0; i < Option::SepExtensions.size(); i++) {
|
||||
Option::SepExtensionOptions &options = Option::SepExtensions[i];
|
||||
if (options.include_path.empty()) {
|
||||
f << "\t-I $(PROJECT_ROOT)/src/runtime/ext/sep/" << options.name;
|
||||
f << "\t-I $(PROJECT_ROOT)/hphp/runtime/ext/sep/" << options.name;
|
||||
} else {
|
||||
f << "\t-I " << options.include_path;
|
||||
}
|
||||
@@ -5318,14 +5318,14 @@ void AnalysisResult::outputCPPSepExtensionMake() {
|
||||
Option::SepExtensionOptions &options = Option::SepExtensions[i];
|
||||
if (options.shared) {
|
||||
if (options.lib_path.empty()) {
|
||||
f << "\t-L $(PROJECT_ROOT)/src/runtime/ext/sep/" << options.name;
|
||||
f << "\t-L $(PROJECT_ROOT)/hphp/runtime/ext/sep/" << options.name;
|
||||
} else {
|
||||
f << "\t-L " << options.lib_path;
|
||||
}
|
||||
f << " -l" << options.name << " \\\n";
|
||||
} else {
|
||||
if (options.lib_path.empty()) {
|
||||
f << "\t$(PROJECT_ROOT)/src/runtime/ext/sep/" << options.name;
|
||||
f << "\t$(PROJECT_ROOT)/hphp/runtime/ext/sep/" << options.name;
|
||||
} else {
|
||||
f << "\t" << options.lib_path;
|
||||
}
|
||||
+1
-1
@@ -635,7 +635,7 @@ public:
|
||||
|
||||
private:
|
||||
template <typename Visitor>
|
||||
void processScopesParallel(const char *id, void *opaque = NULL);
|
||||
void processScopesParallel(const char *id, void *opaque = nullptr);
|
||||
|
||||
template <typename Visitor>
|
||||
void preWaitCallback(bool first,
|
||||
@@ -116,13 +116,13 @@ public:
|
||||
static bool SkipRecurse(ConstructRawPtr cp);
|
||||
|
||||
static bool SkipRecurse(StatementPtr s) {
|
||||
return SkipRecurse(s ? s.get() : NULL);
|
||||
return SkipRecurse(s ? s.get() : nullptr);
|
||||
}
|
||||
static bool SkipRecurse(StatementConstPtr s) {
|
||||
return SkipRecurse(s ? s.get() : NULL);
|
||||
return SkipRecurse(s ? s.get() : nullptr);
|
||||
}
|
||||
static bool SkipRecurse(StatementRawPtr s) {
|
||||
return SkipRecurse(s ? s.get() : NULL);
|
||||
return SkipRecurse(s ? s.get() : nullptr);
|
||||
}
|
||||
|
||||
static bool SkipRecurse(const Statement *stmt);
|
||||
@@ -1247,7 +1247,7 @@ TypePtr ClassScope::checkConst(BlockScopeRawPtr context,
|
||||
ConstructPtr construct,
|
||||
const std::vector<std::string> &bases,
|
||||
BlockScope *&defScope) {
|
||||
defScope = NULL;
|
||||
defScope = nullptr;
|
||||
return getConstants()->check(context, name, type, coerce,
|
||||
ar, construct, m_bases, defScope);
|
||||
}
|
||||
@@ -2216,7 +2216,7 @@ void ClassScope::outputCPPGetClassPropTableImpl(
|
||||
Option::ConstantPrefix,
|
||||
CodeGenerator::FormatLabel(name).c_str());
|
||||
}
|
||||
cg_printf("0x%x1LL", name_ix);
|
||||
cg_printf("int64_t(0x%xd)", name_ix);
|
||||
} else if (flags & ConstRedeclared) {
|
||||
cg_printf("offsetof(%s,%s%s)+0x%x00000003",
|
||||
system ? "SystemGlobals" : "GlobalVariables",
|
||||
@@ -2232,7 +2232,7 @@ void ClassScope::outputCPPGetClassPropTableImpl(
|
||||
CodeGenerator::FormatLabel(name).c_str(),
|
||||
cls_ix);
|
||||
} else {
|
||||
cg_printf("0x%x%07x%dLL", name_ix, cls_ix,
|
||||
cg_printf("0x%x%07x%dL", name_ix, cls_ix,
|
||||
flags & ConstDerivesFromRedeclared ? 4 : 5);
|
||||
}
|
||||
*p = ++index;
|
||||
@@ -3219,9 +3219,9 @@ void ClassScope::outputCPPMethodInvokeTableSupport(CodeGenerator &cg,
|
||||
assert(iterFuncs != funcScopes.end());
|
||||
FunctionScopePtr func = iterFuncs->second;
|
||||
|
||||
const char *extra = NULL;
|
||||
const char *extra = nullptr;
|
||||
string prefix;
|
||||
const char *instance = NULL;
|
||||
const char *instance = nullptr;
|
||||
if (func->isStatic()) {
|
||||
prefix += Option::ClassPrefix;
|
||||
prefix += id;
|
||||
@@ -3459,7 +3459,7 @@ void ClassScope::outputMethodWrappers(CodeGenerator &cg,
|
||||
FunctionScopePtr func = m_functionsVec[i];
|
||||
if (func->isPublic() && !func->isConstructor(self) &&
|
||||
!func->isMagic() && !func->isAbstract()) {
|
||||
func->outputMethodWrapper(cg, ar, NULL);
|
||||
func->outputMethodWrapper(cg, ar, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,7 @@ void ClearErrors() {
|
||||
}
|
||||
|
||||
void Error(ErrorType error, ConstructPtr construct) {
|
||||
if (hhvm) return;
|
||||
if (!Option::RecordErrors) return;
|
||||
ErrorInfoPtr errorInfo(new ErrorInfo());
|
||||
errorInfo->m_error = error;
|
||||
errorInfo->m_construct1 = construct;
|
||||
@@ -187,7 +187,7 @@ void Error(ErrorType error, ConstructPtr construct) {
|
||||
}
|
||||
|
||||
void Error(ErrorType error, ConstructPtr construct1, ConstructPtr construct2) {
|
||||
if (hhvm) return;
|
||||
if (!Option::RecordErrors) return;
|
||||
ErrorInfoPtr errorInfo(new ErrorInfo());
|
||||
errorInfo->m_error = error;
|
||||
errorInfo->m_construct1 = construct1;
|
||||
@@ -197,7 +197,7 @@ void Error(ErrorType error, ConstructPtr construct1, ConstructPtr construct2) {
|
||||
}
|
||||
|
||||
void Error(ErrorType error, ConstructPtr construct, const std::string &data) {
|
||||
if (hhvm) return;
|
||||
if (!Option::RecordErrors) return;
|
||||
ErrorInfoPtr errorInfo(new ErrorInfo());
|
||||
errorInfo->m_error = error;
|
||||
errorInfo->m_construct1 = construct;
|
||||
+1
-1
@@ -165,7 +165,7 @@ TypePtr ConstantTable::check(BlockScopeRawPtr context,
|
||||
assert(!m_blockScope.is(BlockScope::FunctionScope));
|
||||
bool isClassScope = m_blockScope.is(BlockScope::ClassScope);
|
||||
TypePtr actualType;
|
||||
defScope = NULL;
|
||||
defScope = nullptr;
|
||||
if (name == "true" || name == "false") {
|
||||
actualType = Type::Boolean;
|
||||
} else {
|
||||
@@ -128,7 +128,7 @@ private:
|
||||
|
||||
ControlFlowInfo *get(ConstructRawPtr cp) {
|
||||
ConstructCFIMap::iterator it = m_ccfiMap.find(cp);
|
||||
return it == m_ccfiMap.end() ? NULL : &it->second;
|
||||
return it == m_ccfiMap.end() ? nullptr : &it->second;
|
||||
}
|
||||
|
||||
ControlFlowInfo &cfi(ConstructRawPtr cp) {
|
||||
@@ -735,7 +735,7 @@ const StringData* SymbolicStack::getName(int index) const {
|
||||
if (m_symStack[index].metaType == META_LITSTR) {
|
||||
return m_symStack[index].metaData.name;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const StringData* SymbolicStack::getClsName(int index) const {
|
||||
@@ -1353,7 +1353,7 @@ void EmitterVisitor::prepareEvalStack() {
|
||||
if (m_evalStackIsUnknown) {
|
||||
if (!m_evalStack.empty()) {
|
||||
InvariantViolation("Emitter expected to have an empty evaluation "
|
||||
"stack because the eval stack was unknown, but"
|
||||
"stack because the eval stack was unknown, but "
|
||||
"it was non-empty.");
|
||||
return;
|
||||
}
|
||||
@@ -1400,19 +1400,24 @@ bool EmitterVisitor::isJumpTarget(Offset target) {
|
||||
}
|
||||
|
||||
#define CONTROL_BODY(brk, cnt, brkH, cntH) \
|
||||
ControlTargetPusher _cop(this, -1, brk, cnt, brkH, cntH)
|
||||
#define FOREACH_BODY(itId, brk, cnt, brkH, cntH) \
|
||||
ControlTargetPusher _cop(this, itId, brk, cnt, brkH, cntH)
|
||||
ControlTargetPusher _cop(this, -1, false, brk, cnt, brkH, cntH)
|
||||
#define FOREACH_BODY(itId, itRef, brk, cnt, brkH, cntH) \
|
||||
ControlTargetPusher _cop(this, itId, itRef, brk, cnt, brkH, cntH)
|
||||
|
||||
class IterFreeThunklet : public Thunklet {
|
||||
public:
|
||||
IterFreeThunklet(Id iterId) : m_id(iterId) {}
|
||||
IterFreeThunklet(Id iterId, bool itRef) : m_id(iterId), m_itRef(itRef) {}
|
||||
virtual void emit(Emitter& e) {
|
||||
e.IterFree(m_id);
|
||||
if (m_itRef) {
|
||||
e.MIterFree(m_id);
|
||||
} else {
|
||||
e.IterFree(m_id);
|
||||
}
|
||||
e.Unwind();
|
||||
}
|
||||
private:
|
||||
Id m_id;
|
||||
bool m_itRef;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1595,7 +1600,7 @@ void EmitterVisitor::visit(FileScopePtr file) {
|
||||
StringData::GetStaticString(meth->getOriginalName());
|
||||
m_methLabels[methName] = new Label();
|
||||
// Emit afterwards
|
||||
postponeMeth(meth, NULL, true);
|
||||
postponeMeth(meth, nullptr, true);
|
||||
}
|
||||
}
|
||||
{
|
||||
@@ -1788,7 +1793,7 @@ static StringData* getClassName(ExpressionPtr e) {
|
||||
if (cls && !cls->isTrait()) {
|
||||
return StringData::GetStaticString(cls->getOriginalName());
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static DataType getPredictedDataType(ExpressionPtr expr) {
|
||||
@@ -1890,7 +1895,7 @@ bool isTupleInit(ExpressionPtr init_expr, int* cap) {
|
||||
ExpressionPtr ex = (*el)[i];
|
||||
if (ex->getKindOf() != Expression::KindOfArrayPairExpression) return false;
|
||||
ArrayPairExpressionPtr ap = static_pointer_cast<ArrayPairExpression>(ex);
|
||||
if (ap->getName() != NULL || ap->isRef()) return false;
|
||||
if (ap->getName() != nullptr || ap->isRef()) return false;
|
||||
}
|
||||
*cap = n;
|
||||
return true;
|
||||
@@ -1960,7 +1965,11 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
}
|
||||
if (bs->is(Statement::KindOfBreakStatement)) {
|
||||
if (m_contTargets.front().m_itId != -1) {
|
||||
e.IterFree(m_contTargets.front().m_itId);
|
||||
if (m_contTargets.front().m_itRef) {
|
||||
e.MIterFree(m_contTargets.front().m_itId);
|
||||
} else {
|
||||
e.IterFree(m_contTargets.front().m_itId);
|
||||
}
|
||||
}
|
||||
e.Jmp(m_contTargets.front().m_brkTarg);
|
||||
} else {
|
||||
@@ -2514,7 +2523,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
postponeMeth(m, NULL, true);
|
||||
postponeMeth(m, nullptr, true);
|
||||
} else {
|
||||
FuncEmitter* fe = m_ue.newFuncEmitter(nName, false);
|
||||
e.DefFunc(fe->id());
|
||||
@@ -2834,7 +2843,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
if (op == T_COLLECTION) {
|
||||
ScalarExpressionPtr cls =
|
||||
static_pointer_cast<ScalarExpression>(b->getExp1());
|
||||
const std::string* clsName = NULL;
|
||||
const std::string* clsName = nullptr;
|
||||
cls->getString(clsName);
|
||||
int cType = 0;
|
||||
if (!strcasecmp(clsName->c_str(), "vector")) {
|
||||
@@ -2987,7 +2996,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
ExpressionListPtr args(el->getExpressions());
|
||||
int n = args ? args->getCount() : 0;
|
||||
int i = 0;
|
||||
FPIRegionRecorder* fpi = NULL;
|
||||
FPIRegionRecorder* fpi = nullptr;
|
||||
if (el->getType() == '`') {
|
||||
const static StringData* s_shell_exec =
|
||||
StringData::GetStaticString("shell_exec");
|
||||
@@ -3398,20 +3407,29 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
ExpressionListPtr params(om->getParams());
|
||||
int numParams = params ? params->getCount() : 0;
|
||||
|
||||
Offset fpiStart;
|
||||
if (!om->getName().empty()) {
|
||||
// $obj->name(...)
|
||||
// ^^^^
|
||||
// Use getOriginalName, which hasn't been case-normalized, since
|
||||
// __call() is case-preserving.
|
||||
StringData* nameLiteral =
|
||||
StringData::GetStaticString(om->getOriginalName());
|
||||
fpiStart = m_ue.bcPos();
|
||||
e.FPushObjMethodD(numParams, nameLiteral);
|
||||
} else {
|
||||
Offset fpiStart = 0;
|
||||
ExpressionPtr methName = om->getNameExp();
|
||||
bool useDirectForm = false;
|
||||
if (methName->is(Expression::KindOfScalarExpression)) {
|
||||
ScalarExpressionPtr sval(
|
||||
static_pointer_cast<ScalarExpression>(methName));
|
||||
const std::string& methStr = sval->getOriginalLiteralString();
|
||||
if (!methStr.empty()) {
|
||||
// $obj->name(...)
|
||||
// ^^^^
|
||||
// Use getOriginalLiteralString(), which hasn't been
|
||||
// case-normalized, since __call() needs to preserve
|
||||
// the case.
|
||||
StringData* nameLiteral = StringData::GetStaticString(methStr);
|
||||
fpiStart = m_ue.bcPos();
|
||||
e.FPushObjMethodD(numParams, nameLiteral);
|
||||
useDirectForm = true;
|
||||
}
|
||||
}
|
||||
if (!useDirectForm) {
|
||||
// $obj->{...}(...)
|
||||
// ^^^^^
|
||||
visit(om->getNameExp());
|
||||
visit(methName);
|
||||
emitConvertToCell(e);
|
||||
fpiStart = m_ue.bcPos();
|
||||
e.FPushObjMethod(numParams);
|
||||
@@ -3419,7 +3437,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
if (clsName) {
|
||||
Id id = m_ue.mergeLitstr(clsName);
|
||||
m_metaInfo.add(fpiStart, Unit::MetaInfo::Class, false,
|
||||
om->getName().empty() ? 1 : 0, id);
|
||||
useDirectForm ? 0 : 1, id);
|
||||
}
|
||||
{
|
||||
FPIRegionRecorder fpi(this, m_ue, m_evalStack, fpiStart);
|
||||
@@ -3625,7 +3643,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
TypedValue tvVal;
|
||||
initScalar(tvVal, val);
|
||||
|
||||
if (key != NULL) {
|
||||
if (key != nullptr) {
|
||||
// Key.
|
||||
assert(key->isScalar());
|
||||
TypedValue tvKey;
|
||||
@@ -3768,7 +3786,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
PreClassEmitter* pce = m_ue.newPreClassEmitter(
|
||||
className, PreClass::AlwaysHoistable);
|
||||
pce->init(sLoc->line0, sLoc->line1, m_ue.bcPos(),
|
||||
AttrUnique | AttrPersistent, parentName, NULL);
|
||||
AttrUnique | AttrPersistent, parentName, nullptr);
|
||||
|
||||
// We're still at the closure definition site. Emit code to instantiate
|
||||
// the new anonymous class, with the use variables as arguments.
|
||||
@@ -3789,7 +3807,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
TypedValue uninit;
|
||||
tvWriteUninit(&uninit);
|
||||
for (int i = 0; i < useCount; ++i) {
|
||||
pce->addProperty(useVars[i].first, AttrPrivate, NULL, &uninit);
|
||||
pce->addProperty(useVars[i].first, AttrPrivate, nullptr, &uninit);
|
||||
}
|
||||
|
||||
// The constructor. This is entirely generated; all it does is stash its
|
||||
@@ -4135,13 +4153,7 @@ void EmitterVisitor::emitVGet(Emitter& e) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace PassByRefKind {
|
||||
static const ssize_t AllowCell = 0;
|
||||
static const ssize_t WarnOnCell = 1;
|
||||
static const ssize_t ErrorOnCell = 2;
|
||||
}
|
||||
|
||||
static ssize_t getPassByRefKind(ExpressionPtr exp) {
|
||||
EmitterVisitor::PassByRefKind EmitterVisitor::getPassByRefKind(ExpressionPtr exp) {
|
||||
// The PassByRefKind of a list assignment expression is determined
|
||||
// by the PassByRefKind of the RHS. This loop will repeatedly recurse
|
||||
// on the RHS until it encounters an expression other than a list
|
||||
@@ -4265,21 +4277,25 @@ void EmitterVisitor::emitFuncCallArg(Emitter& e,
|
||||
}
|
||||
return;
|
||||
}
|
||||
emitFPass(e, paramId, getPassByRefKind(exp));
|
||||
}
|
||||
|
||||
void EmitterVisitor::emitFPass(Emitter& e, int paramId, PassByRefKind passByRefKind) {
|
||||
if (checkIfStackEmpty("FPass*")) return;
|
||||
LocationGuard locGuard(e, m_tempLoc);
|
||||
m_tempLoc.reset();
|
||||
|
||||
emitClsIfSPropBase(e);
|
||||
int iLast = m_evalStack.size()-1;
|
||||
int i = scanStackForLocation(iLast);
|
||||
int sz = iLast - i;
|
||||
assert(sz >= 0);
|
||||
char sym = m_evalStack.get(i);
|
||||
// This ensures that the FPass instruction will be associated with
|
||||
// exp's source location.
|
||||
LocationGuard locGuard(e, m_tempLoc);
|
||||
m_tempLoc.reset();
|
||||
if (sz == 0 || (sz == 1 && StackSym::GetMarker(sym) == StackSym::S)) {
|
||||
switch (sym) {
|
||||
case StackSym::L: e.FPassL(paramId, m_evalStack.getLoc(i)); break;
|
||||
case StackSym::C:
|
||||
switch (getPassByRefKind(exp)) {
|
||||
switch (passByRefKind) {
|
||||
case PassByRefKind::AllowCell: e.FPassC(paramId); break;
|
||||
case PassByRefKind::WarnOnCell: e.FPassCW(paramId); break;
|
||||
case PassByRefKind::ErrorOnCell: e.FPassCE(paramId); break;
|
||||
@@ -4575,7 +4591,13 @@ void EmitterVisitor::emitConvertToCell(Emitter& e) {
|
||||
|
||||
void EmitterVisitor::emitFreePendingIters(Emitter& e) {
|
||||
for (unsigned i = 0; i < m_pendingIters.size(); ++i) {
|
||||
e.IterFree(m_pendingIters[i]);
|
||||
auto pendingIter = m_pendingIters[i];
|
||||
if (pendingIter.second == KindOfMIter) {
|
||||
e.MIterFree(pendingIter.first);
|
||||
} else {
|
||||
assert(pendingIter.second == KindOfIter);
|
||||
e.IterFree(pendingIter.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4739,7 +4761,7 @@ void EmitterVisitor::emitClsIfSPropBase(Emitter& e) {
|
||||
}
|
||||
|
||||
Label* EmitterVisitor::getContinuationGotoLabel(StatementPtr s) {
|
||||
Label* label = NULL;
|
||||
Label* label = nullptr;
|
||||
StatementListPtr stmts(static_pointer_cast<StatementList>(s));
|
||||
for (int i = 0; i < stmts->getCount(); i++) {
|
||||
StatementPtr s((*stmts)[i]);
|
||||
@@ -4749,7 +4771,7 @@ Label* EmitterVisitor::getContinuationGotoLabel(StatementPtr s) {
|
||||
visit(f);
|
||||
} else if (s->is(Statement::KindOfGotoStatement)) {
|
||||
GotoStatementPtr g(static_pointer_cast<GotoStatement>(s));
|
||||
always_assert(label == NULL);
|
||||
always_assert(label == nullptr);
|
||||
label = &m_gotoLabels[StringData::GetStaticString(g->label())];
|
||||
} else {
|
||||
not_implemented();
|
||||
@@ -5292,7 +5314,7 @@ void EmitterVisitor::emitPostponedMeths() {
|
||||
e.VerifyParamType(i);
|
||||
}
|
||||
if (fe->isClosureBody()) {
|
||||
assert(p.m_closureUseVars != NULL);
|
||||
assert(p.m_closureUseVars != nullptr);
|
||||
// Emit code to unpack the instance variables (which store the
|
||||
// use-variables) into locals. Some of the use-variables may have the
|
||||
// same name, in which case the last one wins.
|
||||
@@ -5583,7 +5605,7 @@ void EmitterVisitor::emitPostponedClosureCtors() {
|
||||
ClosureUseVarVec& useVars = ctor.m_useVars;
|
||||
FuncEmitter* fe = ctor.m_fe;
|
||||
const Location* sLoc = ctor.m_expr->getLocation().get();
|
||||
fe->init(sLoc->line0, sLoc->line1, m_ue.bcPos(), AttrPublic, false, NULL);
|
||||
fe->init(sLoc->line0, sLoc->line1, m_ue.bcPos(), AttrPublic, false, nullptr);
|
||||
|
||||
unsigned n = useVars.size();
|
||||
Emitter e(ctor.m_expr, m_ue, *this);
|
||||
@@ -5837,7 +5859,7 @@ void EmitterVisitor::emitFuncCall(Emitter& e, FunctionCallPtr node) {
|
||||
ExpressionListPtr params(node->getParams());
|
||||
int numParams = params ? params->getCount() : 0;
|
||||
bool isBuiltinCall = false;
|
||||
StringData* nLiteral = NULL;
|
||||
StringData* nLiteral = nullptr;
|
||||
Offset fpiStart;
|
||||
if (node->getClass() || !node->getClassName().empty()) {
|
||||
bool isSelfOrParent = node->isSelf() || node->isParent();
|
||||
@@ -5884,7 +5906,7 @@ void EmitterVisitor::emitFuncCall(Emitter& e, FunctionCallPtr node) {
|
||||
e.FPushFuncD(numParams, nLiteral);
|
||||
} else {
|
||||
// Special handling for func_get_args and friends inside a generator.
|
||||
const StringData* specialMethodName = NULL;
|
||||
const StringData* specialMethodName = nullptr;
|
||||
static const StringData* contName =
|
||||
StringData::GetStaticString(CONTINUATION_OBJECT_NAME);
|
||||
Id contId = m_curFunc->lookupVarId(contName);
|
||||
@@ -5902,7 +5924,7 @@ void EmitterVisitor::emitFuncCall(Emitter& e, FunctionCallPtr node) {
|
||||
specialMethodName = s_get_arg;
|
||||
}
|
||||
|
||||
if (specialMethodName != NULL) {
|
||||
if (specialMethodName != nullptr) {
|
||||
emitVirtualLocal(contId);
|
||||
emitCGet(e);
|
||||
fpiStart = m_ue.bcPos();
|
||||
@@ -6082,9 +6104,9 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
pce->addUserAttribute(uaName, tv);
|
||||
}
|
||||
|
||||
NonScalarVec* nonScalarPinitVec = NULL;
|
||||
NonScalarVec* nonScalarSinitVec = NULL;
|
||||
NonScalarVec* nonScalarConstVec = NULL;
|
||||
NonScalarVec* nonScalarPinitVec = nullptr;
|
||||
NonScalarVec* nonScalarSinitVec = nullptr;
|
||||
NonScalarVec* nonScalarConstVec = nullptr;
|
||||
if (StatementListPtr stmts = is->getStmts()) {
|
||||
int i, n = stmts->getCount();
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -6128,12 +6150,12 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
} else {
|
||||
tvWriteUninit(&tvVal);
|
||||
if (!(attrs & AttrStatic)) {
|
||||
if (nonScalarPinitVec == NULL) {
|
||||
if (nonScalarPinitVec == nullptr) {
|
||||
nonScalarPinitVec = new NonScalarVec();
|
||||
}
|
||||
nonScalarPinitVec->push_back(NonScalarPair(propName, vNode));
|
||||
} else {
|
||||
if (nonScalarSinitVec == NULL) {
|
||||
if (nonScalarSinitVec == nullptr) {
|
||||
nonScalarSinitVec = new NonScalarVec();
|
||||
}
|
||||
nonScalarSinitVec->push_back(NonScalarPair(propName, vNode));
|
||||
@@ -6166,7 +6188,7 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
initScalar(tvVal, vNode);
|
||||
} else {
|
||||
tvWriteUninit(&tvVal);
|
||||
if (nonScalarConstVec == NULL) {
|
||||
if (nonScalarConstVec == nullptr) {
|
||||
nonScalarConstVec = new NonScalarVec();
|
||||
}
|
||||
nonScalarConstVec->push_back(NonScalarPair(constName, vNode));
|
||||
@@ -6198,7 +6220,7 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
postponeCtor(is, fe);
|
||||
}
|
||||
|
||||
if (nonScalarPinitVec != NULL) {
|
||||
if (nonScalarPinitVec != nullptr) {
|
||||
// Non-scalar property initializers require 86pinit() for run-time
|
||||
// initialization support.
|
||||
static const StringData* methName = StringData::GetStaticString("86pinit");
|
||||
@@ -6207,7 +6229,7 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
postponePinit(is, fe, nonScalarPinitVec);
|
||||
}
|
||||
|
||||
if (nonScalarSinitVec != NULL) {
|
||||
if (nonScalarSinitVec != nullptr) {
|
||||
// Non-scalar property initializers require 86sinit() for run-time
|
||||
// initialization support.
|
||||
static const StringData* methName = StringData::GetStaticString("86sinit");
|
||||
@@ -6216,7 +6238,7 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
postponeSinit(is, fe, nonScalarSinitVec);
|
||||
}
|
||||
|
||||
if (nonScalarConstVec != NULL) {
|
||||
if (nonScalarConstVec != nullptr) {
|
||||
// Non-scalar constant initializers require 86cinit() for run-time
|
||||
// initialization support.
|
||||
static const StringData* methName = StringData::GetStaticString("86cinit");
|
||||
@@ -6230,15 +6252,25 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
return hoistable;
|
||||
}
|
||||
|
||||
void EmitterVisitor::emitBreakHandler(Emitter& e, Label& brkTarg,
|
||||
Label& cntTarg, Label& brkHand, Label& cntHand, Id iter /* = -1 */) {
|
||||
|
||||
void
|
||||
EmitterVisitor::emitBreakHandler(Emitter& e,
|
||||
Label& brkTarg,
|
||||
Label& cntTarg,
|
||||
Label& brkHand,
|
||||
Label& cntHand,
|
||||
Id iter /* = -1 */,
|
||||
IterKind itKind /* = KindOfIter */) {
|
||||
// Handle dynamic break
|
||||
if (brkHand.isUsed()) {
|
||||
brkHand.set(e);
|
||||
// Whatever happens, we have left this loop
|
||||
if (iter != -1) {
|
||||
e.IterFree(iter);
|
||||
if (itKind == KindOfMIter) {
|
||||
e.MIterFree(iter);
|
||||
} else {
|
||||
assert(itKind == KindOfIter);
|
||||
e.IterFree(iter);
|
||||
}
|
||||
}
|
||||
e.Int(1);
|
||||
e.Sub();
|
||||
@@ -6266,7 +6298,12 @@ void EmitterVisitor::emitBreakHandler(Emitter& e, Label& brkTarg,
|
||||
e.Jmp(cntTarg);
|
||||
leaving.set(e);
|
||||
// Leaving this loop
|
||||
e.IterFree(iter);
|
||||
if (itKind == KindOfMIter) {
|
||||
e.MIterFree(iter);
|
||||
} else {
|
||||
assert(itKind == KindOfIter);
|
||||
e.IterFree(iter);
|
||||
}
|
||||
e.Jmp(topContHandler());
|
||||
} else {
|
||||
e.JmpZ(topContHandler());
|
||||
@@ -6279,11 +6316,11 @@ void EmitterVisitor::emitBreakHandler(Emitter& e, Label& brkTarg,
|
||||
class ForeachIterGuard {
|
||||
EmitterVisitor& m_ev;
|
||||
public:
|
||||
ForeachIterGuard(EmitterVisitor& ev, Id iterId) : m_ev(ev) {
|
||||
m_ev.pushIterId(iterId);
|
||||
ForeachIterGuard(EmitterVisitor& ev, Id iterId, bool itRef) : m_ev(ev) {
|
||||
m_ev.pushIterScope(iterId, itRef);
|
||||
}
|
||||
~ForeachIterGuard() {
|
||||
m_ev.popIterId();
|
||||
m_ev.popIterScope();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6306,7 +6343,7 @@ void EmitterVisitor::emitForeach(Emitter& e, ForEachStatementPtr fe) {
|
||||
Label start;
|
||||
Offset bIterStart;
|
||||
Id itId = m_curFunc->allocIterator();
|
||||
ForeachIterGuard fig(*this, itId);
|
||||
ForeachIterGuard fig(*this, itId, strong);
|
||||
bool simpleCase = (!key || key->is(Expression::KindOfSimpleVariable)) &&
|
||||
val->is(Expression::KindOfSimpleVariable);
|
||||
|
||||
@@ -6334,9 +6371,9 @@ void EmitterVisitor::emitForeach(Emitter& e, ForEachStatementPtr fe) {
|
||||
if (strong) {
|
||||
emitConvertToVar(e);
|
||||
if (key) {
|
||||
e.IterInitMK(itId, exit, valTempLocal, keyTempLocal);
|
||||
e.MIterInitK(itId, exit, valTempLocal, keyTempLocal);
|
||||
} else {
|
||||
e.IterInitM(itId, exit, valTempLocal);
|
||||
e.MIterInit(itId, exit, valTempLocal);
|
||||
}
|
||||
} else {
|
||||
emitConvertToCell(e);
|
||||
@@ -6366,9 +6403,9 @@ void EmitterVisitor::emitForeach(Emitter& e, ForEachStatementPtr fe) {
|
||||
|
||||
if (strong) {
|
||||
if (key) {
|
||||
e.IterInitMK(itId, exit, valTempLocal, keyTempLocal);
|
||||
e.MIterInitK(itId, exit, valTempLocal, keyTempLocal);
|
||||
} else {
|
||||
e.IterInitM(itId, exit, valTempLocal);
|
||||
e.MIterInit(itId, exit, valTempLocal);
|
||||
}
|
||||
} else {
|
||||
if (key) {
|
||||
@@ -6413,7 +6450,7 @@ void EmitterVisitor::emitForeach(Emitter& e, ForEachStatementPtr fe) {
|
||||
}
|
||||
|
||||
{
|
||||
FOREACH_BODY(itId, exit, next, brkHand, cntHand);
|
||||
FOREACH_BODY(itId, strong, exit, next, brkHand, cntHand);
|
||||
if (body) visit(body);
|
||||
}
|
||||
bool needBreakHandler = (brkHand.isUsed() || cntHand.isUsed());
|
||||
@@ -6432,9 +6469,9 @@ void EmitterVisitor::emitForeach(Emitter& e, ForEachStatementPtr fe) {
|
||||
m_evalStack.cleanTopMeta();
|
||||
if (strong) {
|
||||
if (key) {
|
||||
e.IterNextMK(itId, start, valTempLocal, keyTempLocal);
|
||||
e.MIterNextK(itId, start, valTempLocal, keyTempLocal);
|
||||
} else {
|
||||
e.IterNextM(itId, start, valTempLocal);
|
||||
e.MIterNext(itId, start, valTempLocal);
|
||||
}
|
||||
} else {
|
||||
if (key) {
|
||||
@@ -6443,10 +6480,12 @@ void EmitterVisitor::emitForeach(Emitter& e, ForEachStatementPtr fe) {
|
||||
e.IterNext(itId, start, valTempLocal);
|
||||
}
|
||||
}
|
||||
newFaultRegion(bIterStart, m_ue.bcPos(), new IterFreeThunklet(itId), itId);
|
||||
newFaultRegion(bIterStart, m_ue.bcPos(), new IterFreeThunklet(itId, strong),
|
||||
itId);
|
||||
if (needBreakHandler) {
|
||||
e.Jmp(exit);
|
||||
emitBreakHandler(e, exit, next, brkHand, cntHand, itId);
|
||||
IterKind itKind = strong ? KindOfMIter : KindOfIter;
|
||||
emitBreakHandler(e, exit, next, brkHand, cntHand, itId, itKind);
|
||||
}
|
||||
if (!simpleCase) {
|
||||
m_curFunc->freeUnnamedLocal(valTempLocal);
|
||||
@@ -6604,8 +6643,8 @@ void EmitterVisitor::finishFunc(Emitter& e, FuncEmitter* fe) {
|
||||
|
||||
StringData* EmitterVisitor::newClosureName() {
|
||||
std::ostringstream str;
|
||||
str << "closure$";
|
||||
if (m_curFunc->pce() != NULL) {
|
||||
str << "Closure" << '$';
|
||||
if (m_curFunc->pce() != nullptr) {
|
||||
str << m_curFunc->pce()->name()->data();
|
||||
}
|
||||
str << '$';
|
||||
@@ -6806,14 +6845,14 @@ static Unit* emitHHBCNativeFuncUnit(const HhbcExtFuncInfo* builtinFuncs,
|
||||
fe->finish(ue->bcPos(), false);
|
||||
ue->recordFunction(fe);
|
||||
|
||||
for (ssize_t i = 0LL; i < numBuiltinFuncs; ++i) {
|
||||
for (ssize_t i = 0; i < numBuiltinFuncs; ++i) {
|
||||
const HhbcExtFuncInfo* info = &builtinFuncs[i];
|
||||
StringData* name = StringData::GetStaticString(info->m_name);
|
||||
BuiltinFunction bif = (BuiltinFunction)info->m_builtinFunc;
|
||||
BuiltinFunction nif = (BuiltinFunction)info->m_nativeFunc;
|
||||
const ClassInfo::MethodInfo* mi = ClassInfo::FindFunction(name);
|
||||
assert(mi &&
|
||||
"MethodInfo not found; probably need to rebuild src/system");
|
||||
"MethodInfo not found; probably need to rebuild hphp/system");
|
||||
FuncEmitter* fe = ue->newFuncEmitter(name, /*top*/ true);
|
||||
Offset base = ue->bcPos();
|
||||
fe->setBuiltinFunc(mi, bif, nif, base);
|
||||
@@ -6929,7 +6968,7 @@ static Unit* emitHHBCNativeClassUnit(const HhbcExtClassInfo* builtinClasses,
|
||||
// Build up extClassHash, a hashtable that maps class names to structures
|
||||
// containing C++ function pointers for the class's methods and constructors
|
||||
assert(Class::s_extClassHash.size() == 0);
|
||||
for (long long i = 0LL; i < numBuiltinClasses; ++i) {
|
||||
for (long long i = 0; i < numBuiltinClasses; ++i) {
|
||||
const HhbcExtClassInfo* info = builtinClasses + i;
|
||||
StringData *s = StringData::GetStaticString(info->m_name);
|
||||
Class::s_extClassHash[s] = info;
|
||||
@@ -6978,13 +7017,13 @@ static Unit* emitHHBCNativeClassUnit(const HhbcExtClassInfo* builtinClasses,
|
||||
assert(pending.empty());
|
||||
}
|
||||
|
||||
for (unsigned int i = 0LL; i < classEntries.size(); ++i) {
|
||||
for (unsigned int i = 0; i < classEntries.size(); ++i) {
|
||||
Entry& e = classEntries[i];
|
||||
StringData* parentName =
|
||||
StringData::GetStaticString(e.ci->getParentClass().get());
|
||||
PreClassEmitter* pce = ue->newPreClassEmitter(e.name,
|
||||
PreClass::AlwaysHoistable);
|
||||
pce->init(0, 0, ue->bcPos(), AttrUnique | AttrPersistent, parentName, NULL);
|
||||
pce->init(0, 0, ue->bcPos(), AttrUnique | AttrPersistent, parentName, nullptr);
|
||||
pce->setBuiltinClassInfo(e.ci, e.info->m_InstanceCtor, e.info->m_sizeof);
|
||||
{
|
||||
ClassInfo::InterfaceVec intfVec = e.ci->getInterfacesVec();
|
||||
@@ -7013,7 +7052,7 @@ static Unit* emitHHBCNativeClassUnit(const HhbcExtClassInfo* builtinClasses,
|
||||
const ClassInfo::MethodInfo* mi =
|
||||
e.ci->getMethodInfo(std::string(methodInfo->m_name));
|
||||
Offset base = ue->bcPos();
|
||||
fe->setBuiltinFunc(mi, bcf, NULL, base);
|
||||
fe->setBuiltinFunc(mi, bcf, nullptr, base);
|
||||
ue->emitOp(OpNativeImpl);
|
||||
}
|
||||
Offset past = ue->bcPos();
|
||||
@@ -7062,7 +7101,7 @@ static UnitEmitter* emitHHBCVisitor(AnalysisResultPtr ar, FileScopeRawPtr fsp) {
|
||||
}
|
||||
|
||||
UnitEmitter* ue = emitHHBCUnitEmitter(ar, fsp, md5);
|
||||
assert(ue != NULL);
|
||||
assert(ue != nullptr);
|
||||
|
||||
if (Option::GenerateTextHHBC) {
|
||||
std::unique_ptr<Unit> unit(ue->create());
|
||||
@@ -7087,7 +7126,7 @@ static UnitEmitter* emitHHBCVisitor(AnalysisResultPtr ar, FileScopeRawPtr fsp) {
|
||||
class UEQ : public Synchronizable {
|
||||
public:
|
||||
void push(UnitEmitter* ue) {
|
||||
assert(ue != NULL);
|
||||
assert(ue != nullptr);
|
||||
Lock lock(this);
|
||||
m_ues.push_back(ue);
|
||||
notify();
|
||||
@@ -7097,12 +7136,12 @@ class UEQ : public Synchronizable {
|
||||
if (m_ues.empty()) {
|
||||
// Check for empty() after wait(), in case of spurious wakeup.
|
||||
if (!wait(sec, nsec) || m_ues.empty()) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
assert(m_ues.size() > 0);
|
||||
UnitEmitter* ue = m_ues.front();
|
||||
assert(ue != NULL);
|
||||
assert(ue != nullptr);
|
||||
m_ues.pop_front();
|
||||
return ue;
|
||||
}
|
||||
@@ -7264,7 +7303,7 @@ void emitAllHHBC(AnalysisResultPtr ar) {
|
||||
// Poll, but with a 100ms timeout so that this thread doesn't spin wildly
|
||||
// if it gets ahead of the workers.
|
||||
UnitEmitter* ue = s_ueq.tryPop(0, 100 * 1000 * 1000);
|
||||
if ((didPop = (ue != NULL))) {
|
||||
if ((didPop = (ue != nullptr))) {
|
||||
ues.push_back(ue);
|
||||
}
|
||||
if (ues.size() == kBatchSize
|
||||
@@ -7306,6 +7345,7 @@ Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
|
||||
for (auto& i : RuntimeOption::DynamicInvokeFunctions) {
|
||||
Option::DynamicInvokeFunctions.insert(i);
|
||||
}
|
||||
Option::RecordErrors = false;
|
||||
Option::OutputHHBC = true;
|
||||
Option::ParseTimeOpts = false;
|
||||
Option::WholeProgram = false;
|
||||
@@ -7315,7 +7355,7 @@ Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
|
||||
BuiltinSymbols::Load(ar, true);
|
||||
BuiltinSymbols::NoSuperGlobals = false;
|
||||
TypeConstraint tc;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -7350,15 +7390,13 @@ Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
|
||||
fsp->analyzeProgram(ar);
|
||||
|
||||
UnitEmitter* ue = emitHHBCUnitEmitter(ar, fsp, md5);
|
||||
if (RuntimeOption::RepoCommit) {
|
||||
Repo::get().commitUnit(ue, unitOrigin);
|
||||
}
|
||||
Repo::get().commitUnit(ue, unitOrigin);
|
||||
Unit* unit = ue->create();
|
||||
delete ue;
|
||||
return unit;
|
||||
} catch (const std::exception&) {
|
||||
// extern "C" function should not be throwing exceptions...
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,12 +379,20 @@ public:
|
||||
EXCEPTION_COMMON_IMPL(IncludeTimeFatalException);
|
||||
};
|
||||
|
||||
void pushIterId(Id id) { m_pendingIters.push_back(id); }
|
||||
void popIterId() { m_pendingIters.pop_back(); }
|
||||
enum IterKind {
|
||||
KindOfIter = 0,
|
||||
KindOfMIter = 1
|
||||
};
|
||||
|
||||
void pushIterScope(Id id, bool itRef = false) {
|
||||
IterKind itKind = itRef ? KindOfMIter : KindOfIter;
|
||||
m_pendingIters.push_back(std::pair<Id,IterKind>(id,itKind));
|
||||
}
|
||||
void popIterScope() { m_pendingIters.pop_back(); }
|
||||
private:
|
||||
typedef std::pair<StringData*, bool> ClosureUseVar; // (name, byRef)
|
||||
typedef std::vector<ClosureUseVar> ClosureUseVarVec;
|
||||
typedef std::vector<Id> IdVec;
|
||||
typedef std::vector<std::pair<Id,IterKind> > PendingIterVec;
|
||||
class PostponedMeth {
|
||||
public:
|
||||
PostponedMeth(MethodStatementPtr m, FuncEmitter* fe, bool top,
|
||||
@@ -427,10 +435,12 @@ private:
|
||||
};
|
||||
class ControlTargets {
|
||||
public:
|
||||
ControlTargets(Id itId, Label& brkTarg, Label& cntTarg, Label& brkHand,
|
||||
Label& cntHand) : m_itId(itId), m_brkTarg(brkTarg), m_cntTarg(cntTarg),
|
||||
m_brkHand(brkHand), m_cntHand(cntHand) {}
|
||||
ControlTargets(Id itId, bool itRef, Label& brkTarg, Label& cntTarg,
|
||||
Label& brkHand, Label& cntHand) :
|
||||
m_itId(itId), m_itRef(itRef), m_brkTarg(brkTarg), m_cntTarg(cntTarg),
|
||||
m_brkHand(brkHand), m_cntHand(cntHand) {}
|
||||
Id m_itId;
|
||||
bool m_itRef;
|
||||
Label& m_brkTarg; // Jump here for "break;" (after doing IterFree)
|
||||
Label& m_cntTarg; // Jump here for "continue;"
|
||||
Label& m_brkHand; // Push N and jump here for "break N;"
|
||||
@@ -438,9 +448,9 @@ private:
|
||||
};
|
||||
class ControlTargetPusher {
|
||||
public:
|
||||
ControlTargetPusher(EmitterVisitor* e, Id itId, Label& brkTarg,
|
||||
ControlTargetPusher(EmitterVisitor* e, Id itId, bool itRef, Label& brkTarg,
|
||||
Label& cntTarg, Label& brkHand, Label& cntHand) : m_e(e) {
|
||||
e->m_contTargets.push_front(ControlTargets(itId, brkTarg, cntTarg,
|
||||
e->m_contTargets.push_front(ControlTargets(itId, itRef, brkTarg, cntTarg,
|
||||
brkHand, cntHand));
|
||||
}
|
||||
~ControlTargetPusher() {
|
||||
@@ -505,7 +515,7 @@ private:
|
||||
std::deque<PostponedNonScalars> m_postponedSinits;
|
||||
std::deque<PostponedNonScalars> m_postponedCinits;
|
||||
std::deque<PostponedClosureCtor> m_postponedClosureCtors;
|
||||
IdVec m_pendingIters;
|
||||
PendingIterVec m_pendingIters;
|
||||
typedef std::map<const StringData*, Label*, string_data_lt> LabelMap;
|
||||
LabelMap m_methLabels;
|
||||
SymbolicStack m_evalStack;
|
||||
@@ -535,6 +545,12 @@ public:
|
||||
void buildVectorImm(std::vector<uchar>& vectorImm,
|
||||
int iFirst, int iLast, bool allowW,
|
||||
Emitter& e);
|
||||
enum class PassByRefKind {
|
||||
AllowCell,
|
||||
WarnOnCell,
|
||||
ErrorOnCell,
|
||||
};
|
||||
PassByRefKind getPassByRefKind(ExpressionPtr exp);
|
||||
void emitAGet(Emitter& e);
|
||||
void emitCGetL2(Emitter& e);
|
||||
void emitCGetL3(Emitter& e);
|
||||
@@ -561,6 +577,7 @@ public:
|
||||
void emitConvertToCellOrLoc(Emitter& e);
|
||||
void emitConvertSecondToCell(Emitter& e);
|
||||
void emitConvertToVar(Emitter& e);
|
||||
void emitFPass(Emitter& e, int paramID, PassByRefKind passByRefKind);
|
||||
void emitVirtualLocal(int localId, DataType dt = KindOfUnknown);
|
||||
template<class Expr> void emitVirtualClassBase(Emitter&, Expr* node);
|
||||
void emitResolveClsBase(Emitter& e, int pos);
|
||||
@@ -587,7 +604,7 @@ public:
|
||||
void emitAssignment(Emitter& e, ExpressionPtr c, int op, bool bind);
|
||||
void emitListAssignment(Emitter& e, ListAssignmentPtr lst);
|
||||
void postponeMeth(MethodStatementPtr m, FuncEmitter* fe, bool top,
|
||||
ClosureUseVarVec* useVars = NULL);
|
||||
ClosureUseVarVec* useVars = nullptr);
|
||||
void postponeCtor(InterfaceStatementPtr m, FuncEmitter* fe);
|
||||
void postponePinit(InterfaceStatementPtr m, FuncEmitter* fe, NonScalarVec* v);
|
||||
void postponeSinit(InterfaceStatementPtr m, FuncEmitter* fe, NonScalarVec* v);
|
||||
@@ -622,7 +639,8 @@ public:
|
||||
PreClass::Hoistable emitClass(Emitter& e, ClassScopePtr cNode,
|
||||
bool topLevel);
|
||||
void emitBreakHandler(Emitter& e, Label& brkTarg, Label& cntTarg,
|
||||
Label& brkHand, Label& cntHand, Id iter = -1);
|
||||
Label& brkHand, Label& cntHand, Id iter = -1,
|
||||
IterKind itKind = KindOfIter);
|
||||
void emitForeach(Emitter& e, ForEachStatementPtr fe);
|
||||
void emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc);
|
||||
void emitMakeUnitFatal(Emitter& e, const std::string& message);
|
||||
+1
-1
@@ -425,7 +425,7 @@ void FunctionContainer::outputCPPCodeInfoTable(
|
||||
vector<const char *> funcs;
|
||||
bool system = cg.getOutput() == CodeGenerator::SystemCPP;
|
||||
if (system) {
|
||||
outputCPPCallInfoTableSupport(cg, ar, 0, needGlobals, NULL);
|
||||
outputCPPCallInfoTableSupport(cg, ar, 0, needGlobals, nullptr);
|
||||
}
|
||||
for (StringToFunctionScopePtrMap::const_iterator iter = functions.begin(),
|
||||
end = functions.end(); iter != end; ++iter) {
|
||||
+2
-2
@@ -64,14 +64,14 @@ protected:
|
||||
void outputCPPJumpTableSupport(CodeGenerator &cg, AnalysisResultPtr ar,
|
||||
const StringToFunctionScopePtrVecMap *redec,
|
||||
bool &hasRedeclared,
|
||||
std::vector<const char *> *funcs = NULL);
|
||||
std::vector<const char *> *funcs = nullptr);
|
||||
void outputCPPJumpTableEvalSupport(
|
||||
CodeGenerator &cg, AnalysisResultPtr ar,
|
||||
const StringToFunctionScopePtrVecMap *redec, bool &hasRedeclared);
|
||||
void outputCPPCallInfoTableSupport(
|
||||
CodeGenerator &cg, AnalysisResultPtr ar,
|
||||
const StringToFunctionScopePtrVecMap *redec,
|
||||
bool &hasRedeclared, std::vector<const char *> *funcs = NULL);
|
||||
bool &hasRedeclared, std::vector<const char *> *funcs = nullptr);
|
||||
void outputCPPJumpTableSupportMethod(CodeGenerator &cg, AnalysisResultPtr ar,
|
||||
FunctionScopePtr func,
|
||||
const char *funcPrefix);
|
||||
+20
-17
@@ -2165,7 +2165,7 @@ void FunctionScope::outputCPPCallInfo(CodeGenerator &cg,
|
||||
Option::InvokePrefix, id.c_str(),
|
||||
Option::InvokeFewArgsPrefix, id.c_str());
|
||||
}
|
||||
cg.printf(", %d, %d, 0x%.16llXLL", m_maxParam, flags, refflags);
|
||||
cg.printf(", %d, %d, 0x%.16llXL", m_maxParam, flags, refflags);
|
||||
if (isRedeclaring()) {
|
||||
cg_printf("}, %d", getRedeclaringId());
|
||||
}
|
||||
@@ -2458,24 +2458,27 @@ FunctionScope::StringToFunctionInfoPtrMap FunctionScope::s_refParamInfo;
|
||||
static Mutex s_refParamInfoLock;
|
||||
|
||||
void FunctionScope::RecordFunctionInfo(string fname, FunctionScopePtr func) {
|
||||
if (!Option::WholeProgram) return; // Only needed in WholeProgram mode.
|
||||
Lock lock(s_refParamInfoLock);
|
||||
FunctionInfoPtr &info = s_refParamInfo[fname];
|
||||
if (!info) {
|
||||
info = FunctionInfoPtr(new FunctionInfo());
|
||||
}
|
||||
if (func->isStatic()) {
|
||||
info->setMaybeStatic();
|
||||
}
|
||||
if (func->isRefReturn()) {
|
||||
info->setMaybeRefReturn();
|
||||
}
|
||||
if (func->isReferenceVariableArgument()) {
|
||||
info->setRefVarArg(func->getMaxParamCount());
|
||||
}
|
||||
VariableTablePtr variables = func->getVariables();
|
||||
if (Option::WholeProgram) {
|
||||
Lock lock(s_refParamInfoLock);
|
||||
FunctionInfoPtr &info = s_refParamInfo[fname];
|
||||
if (!info) {
|
||||
info = FunctionInfoPtr(new FunctionInfo());
|
||||
}
|
||||
if (func->isStatic()) {
|
||||
info->setMaybeStatic();
|
||||
}
|
||||
if (func->isRefReturn()) {
|
||||
info->setMaybeRefReturn();
|
||||
}
|
||||
if (func->isReferenceVariableArgument()) {
|
||||
info->setRefVarArg(func->getMaxParamCount());
|
||||
}
|
||||
for (int i = 0; i < func->getMaxParamCount(); i++) {
|
||||
if (func->isRefParam(i)) info->setRefParam(i);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < func->getMaxParamCount(); i++) {
|
||||
if (func->isRefParam(i)) info->setRefParam(i);
|
||||
variables->addParam(func->getParamName(i),
|
||||
TypePtr(), AnalysisResultPtr(), ConstructPtr());
|
||||
}
|
||||
@@ -407,9 +407,9 @@ public:
|
||||
bool voidWrapperOff = false,
|
||||
bool fewArgs = false,
|
||||
bool ret = true,
|
||||
const char *extraArg = NULL,
|
||||
const char *extraArg = nullptr,
|
||||
bool constructor = false,
|
||||
const char *instance = NULL,
|
||||
const char *instance = nullptr,
|
||||
const char *class_name = "");
|
||||
|
||||
void outputCPPDef(CodeGenerator &cg);
|
||||
@@ -452,7 +452,7 @@ const Symbol *SymbolTable::getSymbolImpl(const std::string &name) const {
|
||||
if (it != m_symbolMap.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Symbol *SymbolTable::getSymbol(const std::string &name) {
|
||||
@@ -0,0 +1,876 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <compiler/analysis/type.h>
|
||||
#include <compiler/code_generator.h>
|
||||
#include <compiler/analysis/analysis_result.h>
|
||||
#include <compiler/analysis/class_scope.h>
|
||||
#include <compiler/analysis/file_scope.h>
|
||||
#include <compiler/expression/expression.h>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// statics
|
||||
|
||||
TypePtr Type::Null (new Type(Type::KindOfVoid ));
|
||||
TypePtr Type::Boolean (new Type(Type::KindOfBoolean ));
|
||||
TypePtr Type::Int32 (new Type(Type::KindOfInt32 ));
|
||||
TypePtr Type::Int64 (new Type(Type::KindOfInt64 ));
|
||||
TypePtr Type::Double (new Type(Type::KindOfDouble ));
|
||||
TypePtr Type::String (new Type(Type::KindOfString ));
|
||||
TypePtr Type::Array (new Type(Type::KindOfArray ));
|
||||
TypePtr Type::Object (new Type(Type::KindOfObject ));
|
||||
TypePtr Type::Variant (new Type(Type::KindOfVariant ));
|
||||
|
||||
TypePtr Type::Numeric (new Type(Type::KindOfNumeric ));
|
||||
TypePtr Type::PlusOperand (new Type(Type::KindOfPlusOperand ));
|
||||
TypePtr Type::Primitive (new Type(Type::KindOfPrimitive ));
|
||||
TypePtr Type::Sequence (new Type(Type::KindOfSequence ));
|
||||
|
||||
TypePtr Type::AutoSequence(new Type(Type::KindOfAutoSequence));
|
||||
TypePtr Type::AutoObject (new Type(Type::KindOfAutoObject ));
|
||||
|
||||
TypePtr Type::Any (new Type(Type::KindOfAny ));
|
||||
TypePtr Type::Some (new Type(Type::KindOfSome ));
|
||||
|
||||
Type::TypePtrMap Type::s_TypeHintTypes;
|
||||
|
||||
void Type::InitTypeHintMap() {
|
||||
assert(s_TypeHintTypes.empty());
|
||||
s_TypeHintTypes["array"] = Type::Array;
|
||||
if (Option::EnableHipHopSyntax) {
|
||||
s_TypeHintTypes["bool"] = Type::Boolean;
|
||||
s_TypeHintTypes["boolean"] = Type::Boolean;
|
||||
s_TypeHintTypes["int"] = Type::Int64;
|
||||
s_TypeHintTypes["integer"] = Type::Int64;
|
||||
s_TypeHintTypes["real"] = Type::Double;
|
||||
s_TypeHintTypes["double"] = Type::Double;
|
||||
s_TypeHintTypes["float"] = Type::Double;
|
||||
s_TypeHintTypes["string"] = Type::String;
|
||||
}
|
||||
}
|
||||
|
||||
const Type::TypePtrMap &Type::GetTypeHintTypes() {
|
||||
return s_TypeHintTypes;
|
||||
}
|
||||
|
||||
void Type::ResetTypeHintTypes() {
|
||||
s_TypeHintTypes.clear();
|
||||
}
|
||||
|
||||
TypePtr Type::CreateObjectType(const std::string &classname) {
|
||||
return TypePtr(new Type(KindOfObject, classname));
|
||||
}
|
||||
|
||||
TypePtr Type::GetType(KindOf kindOf,
|
||||
const std::string &clsname /* = "" */) {
|
||||
assert(kindOf);
|
||||
if (!clsname.empty()) return TypePtr(new Type(kindOf, clsname));
|
||||
|
||||
switch (kindOf) {
|
||||
case KindOfBoolean: return Type::Boolean;
|
||||
case KindOfInt32: return Type::Int32;
|
||||
case KindOfInt64: return Type::Int64;
|
||||
case KindOfDouble: return Type::Double;
|
||||
case KindOfString: return Type::String;
|
||||
case KindOfArray: return Type::Array;
|
||||
case KindOfVariant: return Type::Variant;
|
||||
case KindOfObject: return Type::Object;
|
||||
case KindOfNumeric: return Type::Numeric;
|
||||
case KindOfPrimitive: return Type::Primitive;
|
||||
case KindOfPlusOperand: return Type::PlusOperand;
|
||||
case KindOfSequence: return Type::Sequence;
|
||||
case KindOfSome: return Type::Some;
|
||||
case KindOfAny: return Type::Any;
|
||||
default: return TypePtr(new Type(kindOf));
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr Type::Intersection(AnalysisResultConstPtr ar,
|
||||
TypePtr from, TypePtr to) {
|
||||
// Special case: if we're casting to Some or Any, return the "from" type;
|
||||
// if we're casting to Variant, return Variant.
|
||||
if (to->m_kindOf == KindOfSome || to->m_kindOf == KindOfAny) {
|
||||
return from;
|
||||
} else if (to->m_kindOf == KindOfVariant) {
|
||||
return Variant;
|
||||
}
|
||||
|
||||
int resultKind = to->m_kindOf & from->m_kindOf;
|
||||
std::string resultName = "";
|
||||
|
||||
if (resultKind & KindOfObject) {
|
||||
// if they're the same, or we don't know one's name, then use
|
||||
// the other
|
||||
if (to->m_name == from->m_name || from->m_name.empty()) {
|
||||
resultName = to->m_name;
|
||||
} else if (to->m_name.empty()) {
|
||||
resultName = from->m_name;
|
||||
} else {
|
||||
// make sure there's a subclass relation
|
||||
ClassScopePtr cls = ar->findClass(from->m_name);
|
||||
if (cls) {
|
||||
if (cls->derivesFrom(ar, to->m_name, true, false)) {
|
||||
resultName = to->m_name;
|
||||
} else {
|
||||
resultKind &= ~KindOfObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr res;
|
||||
|
||||
// If there is overlap (for instance, they were the same, or we've narrowed
|
||||
// down something like Sequenece to be more specific), then return the
|
||||
// intersection of the types.
|
||||
if (resultKind) {
|
||||
res = GetType(resultKind, resultName);
|
||||
} else if (from->mustBe(KindOfObject) && to->m_kindOf == KindOfPrimitive) {
|
||||
// Special case Object -> Primitive: can we tostring it?
|
||||
if (!from->m_name.empty()) {
|
||||
ClassScopePtr cls = ar->findClass(from->m_name);
|
||||
if (cls && cls->findFunction(ar, "__tostring", true)) {
|
||||
res = Type::String;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, return Int32
|
||||
res = Int32;
|
||||
} else if (from->m_kindOf == KindOfBoolean
|
||||
&& to->mustBe(KindOfNumeric | KindOfArray | KindOfString)
|
||||
&& !IsExactType(to->m_kindOf)) {
|
||||
res = Int32;
|
||||
} else {
|
||||
res = to;
|
||||
}
|
||||
|
||||
if (from->mustBe(KindOfBoolean) && to->m_kindOf == KindOfPrimitive) {
|
||||
res = Int32;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Type::IsMappedToVariant(TypePtr t) {
|
||||
if (!t) return true;
|
||||
switch (t->m_kindOf) {
|
||||
case KindOfBoolean:
|
||||
case KindOfInt32 :
|
||||
case KindOfInt64 :
|
||||
case KindOfDouble :
|
||||
case KindOfString :
|
||||
case KindOfArray :
|
||||
case KindOfObject :
|
||||
return false;
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Type::IsCastNeeded(AnalysisResultConstPtr ar, TypePtr from, TypePtr to) {
|
||||
if (SameType(from, to)) return false;
|
||||
if (!from->m_kindOf) return true;
|
||||
if (!to->m_kindOf) return true;
|
||||
|
||||
// Special case: all Sequence operations are implemented on both String and
|
||||
// Array, and vice versa, therefore no need to cast between these types.
|
||||
if ((from->m_kindOf == KindOfSequence && to->mustBe(KindOfSequence))
|
||||
|| (to->m_kindOf == KindOfSequence && from->mustBe(KindOfSequence))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (to->m_kindOf) {
|
||||
case KindOfVariant:
|
||||
case KindOfNumeric:
|
||||
case KindOfPrimitive:
|
||||
case KindOfPlusOperand:
|
||||
case KindOfSome:
|
||||
case KindOfSequence:
|
||||
case KindOfAny:
|
||||
// Currently these types are all mapped to Variant in runtime/base, and
|
||||
// that's why these casting are not needed.
|
||||
return false;
|
||||
case KindOfObject:
|
||||
if (from->m_kindOf == KindOfObject && to->m_name.empty() &&
|
||||
!from->m_name.empty()) return false;
|
||||
else return true;
|
||||
default:
|
||||
// if we don't have a specific type narrowed down, then
|
||||
// it will be a Variant at at runtime, so no cast is needed.
|
||||
return IsExactType(to->m_kindOf);
|
||||
}
|
||||
}
|
||||
|
||||
bool Type::IsCoercionNeeded(AnalysisResultConstPtr ar, TypePtr t1, TypePtr t2) {
|
||||
if (t1->m_kindOf == KindOfSome ||
|
||||
t1->m_kindOf == KindOfAny ||
|
||||
t2->m_kindOf == KindOfSome ||
|
||||
t2->m_kindOf == KindOfAny) return true;
|
||||
|
||||
// special case: we always coerce to a specific object type so we can
|
||||
// type checking properties and methods
|
||||
if (t1->m_kindOf == KindOfObject && !t1->m_name.empty() &&
|
||||
t2->m_kindOf == KindOfObject && t2->m_name.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !Type::IsLegalCast(ar, t1, t2);
|
||||
}
|
||||
|
||||
TypePtr Type::Coerce(AnalysisResultConstPtr ar, TypePtr type1, TypePtr type2) {
|
||||
if (SameType(type1, type2)) return type1;
|
||||
if (type1->m_kindOf == KindOfVariant ||
|
||||
type2->m_kindOf == KindOfVariant) return Type::Variant;
|
||||
if (type1->m_kindOf > type2->m_kindOf) {
|
||||
TypePtr tmp = type1;
|
||||
type1 = type2;
|
||||
type2 = tmp;
|
||||
}
|
||||
if (type1->m_kindOf == KindOfVoid &&
|
||||
(type2->m_kindOf == KindOfString ||
|
||||
type2->m_kindOf == KindOfArray ||
|
||||
type2->m_kindOf == KindOfObject)) {
|
||||
return type2;
|
||||
}
|
||||
if (type2->m_kindOf == KindOfSome ||
|
||||
type2->m_kindOf == KindOfAny) return type1;
|
||||
|
||||
if (type2->m_kindOf & KindOfAuto) {
|
||||
if (type1->mustBe(type2->m_kindOf & ~KindOfAuto)) {
|
||||
if (!(type1->m_kindOf & Type::KindOfString)) {
|
||||
return type1;
|
||||
}
|
||||
if (type2->m_kindOf == KindOfAutoSequence) {
|
||||
return Type::Sequence;
|
||||
}
|
||||
return GetType((KindOf)(type2->m_kindOf & ~KindOfAuto));
|
||||
}
|
||||
return Type::Variant;
|
||||
}
|
||||
|
||||
if (type1->mustBe(KindOfInteger)) {
|
||||
if (type2->mustBe(KindOfInteger)) {
|
||||
return type2;
|
||||
} else if (type2->mustBe(KindOfDouble)) {
|
||||
return Type::Numeric;
|
||||
}
|
||||
}
|
||||
|
||||
if (type1->mustBe(Type::KindOfObject) &&
|
||||
type2->mustBe(Type::KindOfObject)) {
|
||||
if (type1->m_name.empty()) return type1;
|
||||
if (type2->m_name.empty()) return type2;
|
||||
ClassScopePtr cls1 = ar->findClass(type1->m_name);
|
||||
if (cls1 && !cls1->isRedeclaring() &&
|
||||
cls1->derivesFrom(ar, type2->m_name, true, false)) {
|
||||
return type2;
|
||||
}
|
||||
ClassScopePtr cls2 = ar->findClass(type2->m_name);
|
||||
if (cls2 && !cls2->isRedeclaring() &&
|
||||
cls2->derivesFrom(ar, type1->m_name, true, false)) {
|
||||
return type1;
|
||||
}
|
||||
if (cls1 && cls2 &&
|
||||
!cls1->isRedeclaring() && !cls2->isRedeclaring()) {
|
||||
ClassScopePtr parent =
|
||||
ClassScope::FindCommonParent(ar, type1->m_name,
|
||||
type2->m_name);
|
||||
if (parent) {
|
||||
return Type::CreateObjectType(parent->getName());
|
||||
}
|
||||
}
|
||||
return Type::Object;
|
||||
}
|
||||
|
||||
if (type1->mustBe(type2->m_kindOf)) {
|
||||
return type2;
|
||||
}
|
||||
|
||||
static_assert(Type::KindOfString < Type::KindOfArray,
|
||||
"Expected Type::KindOfString < Type::KindOfArray");
|
||||
if (type1->m_kindOf == Type::KindOfString &&
|
||||
type2->m_kindOf == Type::KindOfArray) {
|
||||
return Type::Sequence;
|
||||
}
|
||||
|
||||
return Type::Variant;
|
||||
}
|
||||
|
||||
TypePtr Type::Union(AnalysisResultConstPtr ar, TypePtr type1, TypePtr type2) {
|
||||
if (SameType(type1, type2)) {
|
||||
return type1;
|
||||
}
|
||||
|
||||
int resultKind = type1->m_kindOf | type2->m_kindOf;
|
||||
if (resultKind == KindOfObject) {
|
||||
std::string resultName("");
|
||||
|
||||
// if they're the same, or we don't know one's name, then use
|
||||
// the other
|
||||
if (type1->m_name == type2->m_name) {
|
||||
resultName = type1->m_name;
|
||||
} else if (type1->m_name.empty() || type2->m_name.empty()) {
|
||||
// resultName was initialized to "", so leave it as such;
|
||||
// we know it's an object but not what kind.
|
||||
} else {
|
||||
// take the superclass
|
||||
ClassScopePtr res =
|
||||
ClassScope::FindCommonParent(ar, type1->m_name,
|
||||
type2->m_name);
|
||||
if (res) resultName = res->getName();
|
||||
}
|
||||
return TypePtr(Type::CreateObjectType(resultName));
|
||||
}
|
||||
|
||||
return GetType((KindOf)resultKind);
|
||||
}
|
||||
|
||||
bool Type::SameType(TypePtr type1, TypePtr type2) {
|
||||
if (!type1 && !type2) return true;
|
||||
if (!type1 || !type2) return false;
|
||||
if (type1->m_kindOf == type2->m_kindOf) {
|
||||
if ((type1->m_kindOf & KindOfObject) &&
|
||||
type1->m_name != type2->m_name) return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Type::SubType(AnalysisResultConstPtr ar, TypePtr type1, TypePtr type2) {
|
||||
if (!type1 && !type2) return true;
|
||||
if (!type1 || !type2) return false;
|
||||
if (type1->m_kindOf != type2->m_kindOf) return false;
|
||||
if (!(type1->m_kindOf & KindOfObject)) return true;
|
||||
// both are objects...
|
||||
if (type1->m_name == type2->m_name) return true;
|
||||
// ... with different classnames; check subtype relationship.
|
||||
ClassScopePtr cls1 = ar->findClass(type1->m_name);
|
||||
return cls1 && !cls1->isRedeclaring() &&
|
||||
cls1->derivesFrom(ar, type2->m_name, true, false);
|
||||
}
|
||||
|
||||
bool Type::IsExactType(KindOf kindOf) {
|
||||
// clever trick thanks to mwilliams - this will evaluate
|
||||
// to true iff exactly one bit is set in kindOf
|
||||
return kindOf && !(kindOf & (kindOf-1));
|
||||
}
|
||||
|
||||
bool Type::HasFastCastMethod(TypePtr t) {
|
||||
switch (t->getKindOf()) {
|
||||
case Type::KindOfBoolean:
|
||||
case Type::KindOfInt32:
|
||||
case Type::KindOfInt64:
|
||||
case Type::KindOfDouble:
|
||||
case Type::KindOfString:
|
||||
case Type::KindOfArray:
|
||||
case Type::KindOfObject:
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
string Type::GetFastCastMethod(
|
||||
TypePtr dst, bool allowRef, bool forConst) {
|
||||
const char *prefix0 = allowRef ? "to" : "as";
|
||||
const char *prefix1 = forConst ? "C" : "";
|
||||
const char *prefix2 = "Ref";
|
||||
const char *type ATTRIBUTE_UNUSED;
|
||||
|
||||
switch (dst->getKindOf()) {
|
||||
case Type::KindOfBoolean:
|
||||
case Type::KindOfInt32:
|
||||
case Type::KindOfInt64:
|
||||
case Type::KindOfDouble:
|
||||
prefix0 = "to";
|
||||
prefix1 = "";
|
||||
prefix2 = "Val";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch (dst->getKindOf()) {
|
||||
case Type::KindOfBoolean:
|
||||
type = "Boolean";
|
||||
break;
|
||||
case Type::KindOfInt32:
|
||||
case Type::KindOfInt64:
|
||||
type = "Int64";
|
||||
break;
|
||||
case Type::KindOfDouble:
|
||||
type = "Double";
|
||||
break;
|
||||
case Type::KindOfString:
|
||||
type = "Str";
|
||||
break;
|
||||
case Type::KindOfArray:
|
||||
type = "Arr";
|
||||
break;
|
||||
case Type::KindOfObject:
|
||||
type = "Obj";
|
||||
break;
|
||||
default:
|
||||
type = ""; // make the compiler happy
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return string(prefix0) + string(prefix1) + string(type) + string(prefix2);
|
||||
}
|
||||
|
||||
/* This new IsLegalCast returns true in a few cases where the old version
|
||||
* (which was basically a hardcoded truth table) returned false; it seems
|
||||
* like "true" is in fact the right thing to return. The cases that appear
|
||||
* when compiling www are:
|
||||
* Sequence -> Array
|
||||
* PlusOperand -> Array
|
||||
* String -> PlusOperand
|
||||
* Boolean -> PlusOperand
|
||||
*/
|
||||
|
||||
bool Type::IsLegalCast(AnalysisResultConstPtr ar, TypePtr from, TypePtr to) {
|
||||
if (!from->m_kindOf) return true;
|
||||
|
||||
// since both 'from' and 'to' represent sets of types, we do
|
||||
// this by computing the set of types that we could possibly cast 'from'
|
||||
// to, and then determining whether that overlaps with 'to'.
|
||||
int canCastTo = KindOfBoolean | from->m_kindOf;
|
||||
|
||||
if (from->m_kindOf & KindOfVoid) canCastTo |= KindOfVoid;
|
||||
|
||||
// Boolean, Numeric, and String can all be cast among each other
|
||||
if (from->m_kindOf & (KindOfBoolean | KindOfNumeric | KindOfString)) {
|
||||
canCastTo |= KindOfNumeric | KindOfString;
|
||||
}
|
||||
|
||||
if (from->m_kindOf & KindOfObject) {
|
||||
// Objects can only cast to string if they have __tostring
|
||||
if (from->m_name.empty()) {
|
||||
canCastTo |= KindOfString; // we don't know which class it is
|
||||
} else {
|
||||
ClassScopePtr cls = ar->findClass(from->m_name);
|
||||
if (!cls || cls->isRedeclaring() ||
|
||||
cls->findFunction(ar, "__tostring", true)) {
|
||||
canCastTo |= KindOfString;
|
||||
}
|
||||
}
|
||||
|
||||
// can only cast between objects if there's a subclass relation
|
||||
if ((to->m_kindOf & KindOfObject) && !to->m_name.empty() &&
|
||||
!from->m_name.empty() && to->m_name != from->m_name) {
|
||||
ClassScopePtr cls = ar->findClass(from->m_name);
|
||||
if (cls && (cls->isRedeclaring() ||
|
||||
!cls->derivesFrom(ar, to->m_name, true, true))) {
|
||||
canCastTo &= ~KindOfObject;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool overlap = (to->m_kindOf & canCastTo);
|
||||
return overlap;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Type::Type(KindOf kindOf) : m_kindOf(kindOf) {
|
||||
}
|
||||
|
||||
Type::Type(KindOf kindOf, const std::string &name)
|
||||
: m_kindOf(kindOf), m_name(name) {
|
||||
|
||||
// m_name must not be empty only when this type could
|
||||
// be an object
|
||||
assert(m_name.empty() || (m_kindOf & KindOfObject));
|
||||
}
|
||||
|
||||
bool Type::isInteger() const {
|
||||
switch (m_kindOf) {
|
||||
case KindOfInt32:
|
||||
case KindOfInt64:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Type::isStandardObject() const {
|
||||
return m_kindOf == KindOfObject && m_name.empty();
|
||||
}
|
||||
|
||||
bool Type::isSpecificObject() const {
|
||||
return m_kindOf == KindOfObject && !m_name.empty();
|
||||
}
|
||||
|
||||
bool Type::isNonConvertibleType() const {
|
||||
return m_kindOf == KindOfObject || m_kindOf == KindOfArray;
|
||||
}
|
||||
|
||||
bool Type::isNoObjectInvolved() const {
|
||||
if (couldBe(KindOfObject)
|
||||
|| couldBe(KindOfArray))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
TypePtr Type::combinedArithmeticType(TypePtr t1, TypePtr t2) {
|
||||
KindOf kind = KindOfAny;
|
||||
|
||||
if ((t1 && t1->is(Type::KindOfArray)) ||
|
||||
(t2 && t2->is(Type::KindOfArray))) {
|
||||
return TypePtr();
|
||||
}
|
||||
|
||||
if (t1 && t1->isPrimitive()) {
|
||||
if (t2 && t2->isPrimitive()) {
|
||||
if (t2->getKindOf() > t1->getKindOf()) {
|
||||
kind = t2->getKindOf();
|
||||
} else {
|
||||
kind = t1->getKindOf();
|
||||
}
|
||||
} else if (t1->is(KindOfDouble)) {
|
||||
kind = KindOfDouble;
|
||||
} else {
|
||||
kind = KindOfNumeric;
|
||||
}
|
||||
} else if (t2 && t2->isPrimitive()) {
|
||||
if (t2->is(KindOfDouble)) {
|
||||
kind = KindOfDouble;
|
||||
} else {
|
||||
kind = KindOfNumeric;
|
||||
}
|
||||
} else if ((t1 && t1->mustBe(KindOfNumeric)) ||
|
||||
(t2 && t2->mustBe(KindOfNumeric))) {
|
||||
kind = KindOfNumeric;
|
||||
}
|
||||
|
||||
if (kind < KindOfInt64) {
|
||||
kind = KindOfInt64;
|
||||
}
|
||||
|
||||
if (kind != KindOfAny) {
|
||||
return GetType(kind);
|
||||
}
|
||||
|
||||
return TypePtr();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassScopePtr Type::getClass(AnalysisResultConstPtr ar,
|
||||
BlockScopeRawPtr scope) const {
|
||||
if (m_name.empty()) return ClassScopePtr();
|
||||
ClassScopePtr cls = ar->findClass(m_name);
|
||||
if (cls && cls->isRedeclaring()) {
|
||||
if (!scope) {
|
||||
cls.reset();
|
||||
} else {
|
||||
cls = scope->findExactClass(cls);
|
||||
}
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
||||
string Type::getCPPDecl(AnalysisResultConstPtr ar,
|
||||
BlockScopeRawPtr scope,
|
||||
CodeGenerator *cg /* = 0 */) {
|
||||
switch (m_kindOf) {
|
||||
case KindOfBoolean: return "bool";
|
||||
case KindOfInt32: return "int";
|
||||
case KindOfInt64: return "int64";
|
||||
case KindOfDouble: return "double";
|
||||
case KindOfString: return "String";
|
||||
case KindOfArray: return "Array";
|
||||
case KindOfObject:{
|
||||
ClassScopePtr cls(getClass(ar, scope));
|
||||
if (!cls) return "Object";
|
||||
if (cg && cg->isFileOrClassHeader() && scope) {
|
||||
if (scope->getContainingClass()) {
|
||||
scope->getContainingClass()->addUsedClassHeader(cls);
|
||||
} else if (scope->getContainingFile()) {
|
||||
scope->getContainingFile()->addUsedClassHeader(cls);
|
||||
}
|
||||
}
|
||||
return Option::SmartPtrPrefix + cls->getId();
|
||||
}
|
||||
case KindOfNumeric: return "Numeric";
|
||||
case KindOfPrimitive: return "Primitive";
|
||||
case KindOfPlusOperand: return "PlusOperand";
|
||||
case KindOfSequence: return "Sequence";
|
||||
default:
|
||||
return "Variant";
|
||||
}
|
||||
}
|
||||
|
||||
DataType Type::getDataType() const {
|
||||
switch (m_kindOf) {
|
||||
case KindOfBoolean: return HPHP::KindOfBoolean;
|
||||
case KindOfInt32:
|
||||
case KindOfInt64: return HPHP::KindOfInt64;
|
||||
case KindOfDouble: return HPHP::KindOfDouble;
|
||||
case KindOfString: return HPHP::KindOfString;
|
||||
case KindOfArray: return HPHP::KindOfArray;
|
||||
case KindOfObject: return HPHP::KindOfObject;
|
||||
case KindOfNumeric:
|
||||
case KindOfPrimitive:
|
||||
case KindOfPlusOperand:
|
||||
case KindOfSequence:
|
||||
default: return HPHP::KindOfUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
// This is similar to getDataType() except that it returns
|
||||
// HPHP::KindOfNull for KindOfVoid;
|
||||
DataType Type::getHhvmDataType() const {
|
||||
switch (m_kindOf) {
|
||||
case KindOfVoid: return HPHP::KindOfNull;
|
||||
default: return getDataType();
|
||||
}
|
||||
}
|
||||
|
||||
void Type::outputCPPDecl(CodeGenerator &cg, AnalysisResultConstPtr ar,
|
||||
BlockScopeRawPtr scope) {
|
||||
cg_print(getCPPDecl(ar, scope, &cg).c_str());
|
||||
}
|
||||
|
||||
void Type::outputCPPFastObjectCast(CodeGenerator &cg,
|
||||
AnalysisResultConstPtr ar,
|
||||
BlockScopeRawPtr scope,
|
||||
bool isConst) {
|
||||
assert(isSpecificObject());
|
||||
ClassScopePtr cls(getClass(ar, scope));
|
||||
assert(cls);
|
||||
const string &cppClsName = cls->getId();
|
||||
cg_printf("(%s%s%s&)",
|
||||
isConst ? "const " : "",
|
||||
Option::SmartPtrPrefix,
|
||||
cppClsName.c_str());
|
||||
}
|
||||
|
||||
void Type::outputCPPCast(CodeGenerator &cg, AnalysisResultConstPtr ar,
|
||||
BlockScopeRawPtr scope) {
|
||||
switch (m_kindOf) {
|
||||
case KindOfBoolean: cg_printf("toBoolean"); break;
|
||||
case KindOfInt32: cg_printf("toInt32"); break;
|
||||
case KindOfInt64: cg_printf("toInt64"); break;
|
||||
case KindOfDouble: cg_printf("toDouble"); break;
|
||||
case KindOfString: cg_printf("toString"); break;
|
||||
case KindOfArray: cg_printf("toArray"); break;
|
||||
case KindOfNumeric: cg_printf("Numeric"); break;
|
||||
case KindOfPrimitive: cg_printf("Primitive"); break;
|
||||
case KindOfPlusOperand: cg_printf("PlusOperand"); break;
|
||||
case KindOfSequence: cg_printf("Sequence"); break;
|
||||
case KindOfObject: {
|
||||
ClassScopePtr cls(getClass(ar, scope));
|
||||
if (!cls) {
|
||||
cg_printf("toObject");
|
||||
} else {
|
||||
cg_printf("%s%s", Option::SmartPtrPrefix, cls->getId().c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cg_printf("Variant");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Type::getCPPInitializer() {
|
||||
switch (m_kindOf) {
|
||||
case KindOfBoolean: return "false";
|
||||
case KindOfInt32:
|
||||
case KindOfInt64: return "0";
|
||||
case KindOfNumeric:
|
||||
case KindOfPrimitive:
|
||||
case KindOfPlusOperand: return "0";
|
||||
case KindOfDouble: return "0.0";
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Type::getPHPName() {
|
||||
switch (m_kindOf) {
|
||||
case KindOfArray: return "array";
|
||||
case KindOfObject: return m_name;
|
||||
default: break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Type::toString() const {
|
||||
switch (m_kindOf) {
|
||||
case KindOfBoolean: return "Boolean";
|
||||
case KindOfInt32: return "Int32";
|
||||
case KindOfInt64: return "Int64";
|
||||
case KindOfDouble: return "Double";
|
||||
case KindOfString: return "String";
|
||||
case KindOfArray: return "Array";
|
||||
case KindOfVariant: return "Variant";
|
||||
case KindOfSome: return "Some";
|
||||
case KindOfAny: return "Any";
|
||||
case KindOfObject: return string("Object - ") + m_name;
|
||||
case KindOfNumeric: return "Numeric";
|
||||
case KindOfPrimitive: return "Primitive";
|
||||
case KindOfPlusOperand: return "PlusOperand";
|
||||
case KindOfSequence: return "Sequence";
|
||||
default:
|
||||
return boost::str(boost::format("[0x%x]") % m_kindOf);
|
||||
}
|
||||
return "(unknown)";
|
||||
}
|
||||
|
||||
void Type::Dump(TypePtr type, const char *fmt /* = "%s" */) {
|
||||
printf(fmt, type ? type->toString().c_str() : "(null)");
|
||||
}
|
||||
|
||||
void Type::Dump(ExpressionPtr exp) {
|
||||
Dump(exp->getExpectedType(), "Expected: %s\t");
|
||||
Dump(exp->getActualType(), "Actual: %s\n");
|
||||
}
|
||||
|
||||
void Type::serialize(JSON::CodeError::OutputStream &out) const {
|
||||
out << toString();
|
||||
}
|
||||
|
||||
void Type::serialize(JSON::DocTarget::OutputStream &out) const {
|
||||
string s("any");
|
||||
switch (m_kindOf) {
|
||||
case KindOfBoolean: s = "boolean"; break;
|
||||
case KindOfInt32:
|
||||
case KindOfInt64: s = "integer"; break;
|
||||
case KindOfDouble: s = "double"; break;
|
||||
case KindOfString: s = "string"; break;
|
||||
case KindOfArray: s = "array"; break;
|
||||
case KindOfVariant:
|
||||
case KindOfSome:
|
||||
case KindOfAny: s = "any"; break;
|
||||
case KindOfObject:
|
||||
{
|
||||
if (m_name.empty()) s = "object";
|
||||
else {
|
||||
ClassScopePtr c(getClass(out.analysisResult(), BlockScopeRawPtr()));
|
||||
if (c) {
|
||||
s = c->getOriginalName();
|
||||
} else {
|
||||
s = "object";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KindOfNumeric: s = "numeric"; break;
|
||||
case KindOfPrimitive: s = "primitive"; break;
|
||||
case KindOfPlusOperand: s = "any"; break;
|
||||
case KindOfSequence: s = "sequence"; break;
|
||||
}
|
||||
out << s;
|
||||
}
|
||||
|
||||
void Type::count(std::map<std::string, int> &counts) {
|
||||
if (is(Type::KindOfObject)) {
|
||||
if (isSpecificObject()) {
|
||||
counts["Object - Specific"]++;
|
||||
} else {
|
||||
counts["Object"]++;
|
||||
}
|
||||
} else {
|
||||
counts[toString()]++;
|
||||
}
|
||||
|
||||
if (IsExactType(m_kindOf)) {
|
||||
counts["_strong"]++;
|
||||
} else {
|
||||
counts["_weak"]++;
|
||||
}
|
||||
|
||||
counts["_all"]++;
|
||||
}
|
||||
|
||||
TypePtr Type::InferredObject(AnalysisResultConstPtr ar,
|
||||
TypePtr type1,
|
||||
TypePtr type2) {
|
||||
assert(type1->m_kindOf == KindOfObject);
|
||||
assert(type2->m_kindOf == KindOfObject);
|
||||
|
||||
TypePtr resultType = Type::Object;
|
||||
// if they're the same, or we don't know one's name, then use
|
||||
// the other
|
||||
if (type1->m_name == type2->m_name || type1->m_name.empty()) {
|
||||
resultType = type2;
|
||||
} else if (type2->m_name.empty()) {
|
||||
resultType = type1;
|
||||
} else {
|
||||
// take the subclass
|
||||
ClassScopePtr cls1 = ar->findClass(type1->m_name);
|
||||
ClassScopePtr cls2 = ar->findClass(type2->m_name);
|
||||
bool c1ok = cls1 && !cls1->isRedeclaring();
|
||||
bool c2ok = cls2 && !cls2->isRedeclaring();
|
||||
|
||||
if (c1ok && cls1->derivesFrom(ar, type2->m_name, true, false)) {
|
||||
resultType = type1;
|
||||
} else if (c2ok && cls2->derivesFrom(ar, type1->m_name, true, false)) {
|
||||
resultType = type2;
|
||||
} else if (c1ok && c2ok && cls1->derivedByDynamic() &&
|
||||
cls2->derivesFromRedeclaring()) {
|
||||
resultType = type2;
|
||||
} else {
|
||||
resultType = type1;
|
||||
}
|
||||
}
|
||||
return resultType;
|
||||
}
|
||||
|
||||
/* We have inferred type1 and type2 as the actual types for the same
|
||||
expression.
|
||||
Check that the types are compatible (it cant be both a string and
|
||||
an integer, for example), and return the combined type. If they
|
||||
are not compatible, return a null pointer.
|
||||
*/
|
||||
TypePtr Type::Inferred(AnalysisResultConstPtr ar,
|
||||
TypePtr type1, TypePtr type2) {
|
||||
if (!type1) return type2;
|
||||
if (!type2) return type1;
|
||||
KindOf k1 = type1->m_kindOf;
|
||||
KindOf k2 = type2->m_kindOf;
|
||||
|
||||
if (k1 == k2) {
|
||||
return k1 == KindOfObject ?
|
||||
Type::InferredObject(ar, type1, type2) : type1;
|
||||
}
|
||||
|
||||
// If one set is a subset of the other, return the subset.
|
||||
if ((k1 & k2) == k1) return type1;
|
||||
if ((k1 & k2) == k2) return type2;
|
||||
|
||||
// If one type must be numeric and the other might be, then assume numeric
|
||||
if (type1->mustBe(KindOfNumeric) && type2->couldBe(KindOfNumeric)) {
|
||||
return type1;
|
||||
}
|
||||
if (type2->mustBe(KindOfNumeric) && type1->couldBe(KindOfNumeric)) {
|
||||
return type2;
|
||||
}
|
||||
|
||||
// Otherwise, take the intersection
|
||||
int resultKind = type1->m_kindOf & type2->m_kindOf;
|
||||
if (resultKind == KindOfObject) {
|
||||
return Type::InferredObject(ar, type1, type2);
|
||||
}
|
||||
return resultKind ? GetType(resultKind) : TypePtr();
|
||||
}
|
||||
+7
-7
@@ -527,7 +527,7 @@ Symbol *VariableTable::findProperty(ClassScopePtr &cls,
|
||||
return sym;
|
||||
}
|
||||
assert(!sym->isStatic());
|
||||
sym = NULL;
|
||||
sym = nullptr;
|
||||
}
|
||||
|
||||
if (!sym) {
|
||||
@@ -733,7 +733,7 @@ bool VariableTable::isConvertibleSuperGlobal(const string &name) const {
|
||||
ClassScopePtr VariableTable::findParent(AnalysisResultConstPtr ar,
|
||||
const string &name,
|
||||
const Symbol *&sym) const {
|
||||
sym = NULL;
|
||||
sym = nullptr;
|
||||
for (ClassScopePtr parent = m_blockScope.getParentScope(ar);
|
||||
parent && !parent->isRedeclaring();
|
||||
parent = parent->getParentScope(ar)) {
|
||||
@@ -1302,7 +1302,7 @@ void VariableTable::outputCPPGVHashTableGetImpl(CodeGenerator &cg,
|
||||
string escaped = CodeGenerator::EscapeLabel(name);
|
||||
string varName = string("gvm_") + CodeGenerator::FormatLabel(name);
|
||||
cg_printf(" (const char *)\"%s\",\n"
|
||||
" (const char *)%lld,\n"
|
||||
" (const char *)%" PRId64 ",\n"
|
||||
" (const char *)GET_GV_OFFSET(%s),\n"
|
||||
" (const char *)%u,\n",
|
||||
escaped.c_str(),
|
||||
@@ -1625,7 +1625,7 @@ void VariableTable::outputCPPVariableTable(CodeGenerator &cg,
|
||||
|
||||
if (m_forcedVariants) {
|
||||
cg_indentBegin("virtual Variant &getImpl(CStrRef s) {\n");
|
||||
if (!outputCPPJumpTable(cg, ar, NULL, true, true, EitherStatic,
|
||||
if (!outputCPPJumpTable(cg, ar, nullptr, true, true, EitherStatic,
|
||||
JumpReturnString)) {
|
||||
m_emptyJumpTables.insert(JumpTableLocalGetImpl);
|
||||
}
|
||||
@@ -1634,7 +1634,7 @@ void VariableTable::outputCPPVariableTable(CodeGenerator &cg,
|
||||
|
||||
if (getAttribute(ContainsExtract)) {
|
||||
cg_indentBegin("virtual bool exists(CStrRef s) const {\n");
|
||||
if (!outputCPPJumpTable(cg, ar, NULL, true, false,
|
||||
if (!outputCPPJumpTable(cg, ar, nullptr, true, false,
|
||||
EitherStatic, JumpInitializedString)) {
|
||||
m_emptyJumpTables.insert(JumpTableLocalExists);
|
||||
}
|
||||
@@ -1643,7 +1643,7 @@ void VariableTable::outputCPPVariableTable(CodeGenerator &cg,
|
||||
}
|
||||
} else {
|
||||
cg_indentBegin("virtual Variant getImpl(CStrRef s) {\n");
|
||||
if (!outputCPPJumpTable(cg, ar, NULL, true, false, EitherStatic,
|
||||
if (!outputCPPJumpTable(cg, ar, nullptr, true, false, EitherStatic,
|
||||
JumpReturnString)) {
|
||||
m_emptyJumpTables.insert(JumpTableLocalGetImpl);
|
||||
}
|
||||
@@ -1653,7 +1653,7 @@ void VariableTable::outputCPPVariableTable(CodeGenerator &cg,
|
||||
|
||||
if (getAttribute(ContainsCompact)) {
|
||||
cg_indentBegin("virtual bool exists(CStrRef s) const {\n");
|
||||
if (!outputCPPJumpTable(cg, ar, NULL, true, false,
|
||||
if (!outputCPPJumpTable(cg, ar, nullptr, true, false,
|
||||
EitherStatic, JumpInitializedString)) {
|
||||
m_emptyJumpTables.insert(JumpTableLocalExists);
|
||||
}
|
||||
@@ -394,7 +394,7 @@ private:
|
||||
bool variantOnly, StaticSelection staticVar,
|
||||
JumpTableType type = JumpReturn,
|
||||
PrivateSelection privateVar = NonPrivate,
|
||||
bool *declaredGlobals = NULL);
|
||||
bool *declaredGlobals = nullptr);
|
||||
bool outputCPPPrivateSelector(CodeGenerator &cg, AnalysisResultPtr ar,
|
||||
const char *op, const char *args);
|
||||
void outputCPPVariableInit(CodeGenerator &cg, AnalysisResultPtr ar,
|
||||
@@ -60,21 +60,21 @@ const char *BuiltinSymbols::ExtensionFunctions[] = {
|
||||
#define T(t) (const char *)Type::KindOf ## t
|
||||
#define EXT_TYPE 0
|
||||
#include <system/ext.inc>
|
||||
NULL,
|
||||
nullptr,
|
||||
};
|
||||
#undef EXT_TYPE
|
||||
|
||||
const char *BuiltinSymbols::ExtensionConsts[] = {
|
||||
#define EXT_TYPE 1
|
||||
#include <system/ext.inc>
|
||||
NULL,
|
||||
nullptr,
|
||||
};
|
||||
#undef EXT_TYPE
|
||||
|
||||
const char *BuiltinSymbols::ExtensionClasses[] = {
|
||||
#define EXT_TYPE 2
|
||||
#include <system/ext.inc>
|
||||
NULL,
|
||||
nullptr,
|
||||
};
|
||||
#undef EXT_TYPE
|
||||
|
||||
@@ -109,14 +109,14 @@ const char *BuiltinSymbols::SystemClasses[] = {
|
||||
"directoryiterator",
|
||||
"soapfault",
|
||||
"fbmysqllexer",
|
||||
NULL
|
||||
nullptr
|
||||
};
|
||||
|
||||
StringToClassScopePtrMap BuiltinSymbols::s_classes;
|
||||
VariableTablePtr BuiltinSymbols::s_variables;
|
||||
ConstantTablePtr BuiltinSymbols::s_constants;
|
||||
StringToTypePtrMap BuiltinSymbols::s_superGlobals;
|
||||
void *BuiltinSymbols::s_handle_main = NULL;
|
||||
void *BuiltinSymbols::s_handle_main = nullptr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -150,7 +150,7 @@ void BuiltinSymbols::ParseExtConsts(AnalysisResultPtr ar, const char **p,
|
||||
}
|
||||
|
||||
TypePtr BuiltinSymbols::ParseType(const char **&p) {
|
||||
const char *clsname = NULL;
|
||||
const char *clsname = nullptr;
|
||||
Type::KindOf ktype = (Type::KindOf)(long)(*p++);
|
||||
if (ktype == CLASS_TYPE) {
|
||||
clsname = *p++;
|
||||
@@ -277,7 +277,7 @@ FunctionScopePtr BuiltinSymbols::ParseExtFunction(AnalysisResultPtr ar,
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
const char *paramName = NULL;
|
||||
const char *paramName = nullptr;
|
||||
while ((paramName = *p++ /* argName */)) {
|
||||
TypePtr argType = ParseType(p);
|
||||
const char *argDefault = *p++;
|
||||
@@ -342,11 +342,11 @@ bool BuiltinSymbols::LoadSepExtensionSymbols(AnalysisResultPtr ar,
|
||||
const std::string &soname) {
|
||||
string mapname = name + "_map";
|
||||
|
||||
const char ***symbols = NULL;
|
||||
const char ***symbols = nullptr;
|
||||
|
||||
// If we linked with .a, the symbol is already in main program.
|
||||
if (s_handle_main == NULL) {
|
||||
s_handle_main = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (s_handle_main == nullptr) {
|
||||
s_handle_main = dlopen(nullptr, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!s_handle_main) {
|
||||
const char *error = dlerror();
|
||||
Logger::Error("Unable to load main program's symbols: %s",
|
||||
@@ -358,7 +358,7 @@ bool BuiltinSymbols::LoadSepExtensionSymbols(AnalysisResultPtr ar,
|
||||
}
|
||||
|
||||
// Otherwise, look for .so to load it.
|
||||
void *handle = NULL;
|
||||
void *handle = nullptr;
|
||||
if (!symbols) {
|
||||
handle = dlopen(soname.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!handle) {
|
||||
@@ -60,11 +60,11 @@ const char *CodeGenerator::HASH_INCLUDE =
|
||||
CodeGenerator::CodeGenerator(std::ostream *primary,
|
||||
Output output /* = PickledPHP */,
|
||||
const std::string *filename /* = NULL */)
|
||||
: m_out(NULL), m_output(output),
|
||||
: m_out(nullptr), m_output(output),
|
||||
m_hoistedClasses(0), m_collectHoistedClasses(false),
|
||||
m_context(NoContext), m_insideScalarArray(false), m_itemIndex(-1) {
|
||||
for (int i = 0; i < StreamCount; i++) {
|
||||
m_streams[i] = NULL;
|
||||
m_streams[i] = nullptr;
|
||||
m_indentation[i] = 0;
|
||||
m_indentPending[i] = true;
|
||||
m_lineNo[i] = 1;
|
||||
@@ -87,7 +87,7 @@ void CodeGenerator::useStream(Stream stream) {
|
||||
assert(stream >= NullStream && stream < StreamCount);
|
||||
m_curStream = stream;
|
||||
if (stream == NullStream) {
|
||||
m_out = NULL;
|
||||
m_out = nullptr;
|
||||
} else {
|
||||
m_out = m_streams[stream];
|
||||
}
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
public:
|
||||
CodeGenerator() {} // only for creating a dummy code generator
|
||||
CodeGenerator(std::ostream *primary, Output output = PickledPHP,
|
||||
const std::string *filename = NULL);
|
||||
const std::string *filename = nullptr);
|
||||
|
||||
/**
|
||||
* ...if it was passed in from constructor.
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
void printImplSplitter(); // marker to split .cpp into smaller files
|
||||
const char *getGlobals(AnalysisResultPtr ar);
|
||||
static std::string FormatLabel(const std::string &name);
|
||||
static std::string EscapeLabel(const std::string &name, bool *binary = NULL);
|
||||
static std::string EscapeLabel(const std::string &name, bool *binary = nullptr);
|
||||
|
||||
/**
|
||||
* Make sure PHP variables, functions and typenames are unique and
|
||||
@@ -887,11 +887,11 @@ void hhbcTargetInit(const CompilerOptions &po, AnalysisResultPtr ar) {
|
||||
ar->setOutputPath(po.syncDir);
|
||||
}
|
||||
// Propagate relevant compiler-specific options to the runtime.
|
||||
RuntimeOption::RepoLocalPath = ar->getOutputPath() + '/' + po.program;
|
||||
RuntimeOption::RepoCentralPath = ar->getOutputPath() + '/' + po.program;
|
||||
if (po.format.find("exe") != string::npos) {
|
||||
RuntimeOption::RepoLocalPath += ".hhbc";
|
||||
RuntimeOption::RepoCentralPath += ".hhbc";
|
||||
}
|
||||
RuntimeOption::RepoLocalMode = "rw";
|
||||
RuntimeOption::RepoLocalMode = "--";
|
||||
RuntimeOption::RepoDebugInfo = Option::RepoDebugInfo;
|
||||
RuntimeOption::RepoJournal = "memory";
|
||||
RuntimeOption::EnableHipHopSyntax = Option::EnableHipHopSyntax;
|
||||
@@ -960,7 +960,7 @@ int hhbcTarget(const CompilerOptions &po, AnalysisResultPtr ar,
|
||||
const char *argv[] = { "objcopy", "--add-section", repo.c_str(),
|
||||
buf, exe.c_str(), 0 };
|
||||
string out;
|
||||
ret = Process::Exec(argv[0], argv, NULL, out, NULL) ? 0 : 1;
|
||||
ret = Process::Exec(argv[0], argv, nullptr, out, nullptr) ? 0 : 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1007,7 +1007,7 @@ int cppTarget(const CompilerOptions &po, AnalysisResultPtr ar,
|
||||
Timer timer(Timer::WallTime, "creating CPP files");
|
||||
if (po.syncDir.empty()) {
|
||||
ar->setOutputPath(po.outputDir);
|
||||
ar->outputAllCPP(format, clusterCount, NULL);
|
||||
ar->outputAllCPP(format, clusterCount, nullptr);
|
||||
} else {
|
||||
ar->setOutputPath(po.syncDir);
|
||||
ar->outputAllCPP(format, clusterCount, &po.outputDir);
|
||||
@@ -1036,7 +1036,7 @@ int buildTarget(const CompilerOptions &po) {
|
||||
if (!HPHP_HOME || !*HPHP_HOME) {
|
||||
throw Exception("Environment variable HPHP_HOME is not set.");
|
||||
}
|
||||
string cmd = string(HPHP_HOME) + "/src/legacy/run.sh";
|
||||
string cmd = string(HPHP_HOME) + "/hphp/legacy/run.sh";
|
||||
string flags;
|
||||
if (getenv("RELEASE")) flags += "RELEASE=1 ";
|
||||
if (getenv("SHOW_LINK")) flags += "SHOW_LINK=1 ";
|
||||
@@ -1044,7 +1044,7 @@ int buildTarget(const CompilerOptions &po) {
|
||||
if (po.format == "lib") flags += "HPHP_BUILD_LIBRARY=1 ";
|
||||
if (Option::GenerateFFI) flags += "HPHP_BUILD_FFI=1 ";
|
||||
const char *argv[] = {"", po.outputDir.c_str(),
|
||||
po.program.c_str(), flags.c_str(), NULL};
|
||||
po.program.c_str(), flags.c_str(), nullptr};
|
||||
|
||||
if (getenv("SHOW_COMPILE")) {
|
||||
Logger::Info ("Compile command: %s %s %s", po.outputDir.c_str(),
|
||||
@@ -1052,7 +1052,7 @@ int buildTarget(const CompilerOptions &po) {
|
||||
}
|
||||
Timer timer(Timer::WallTime, "compiling and linking CPP files");
|
||||
string out, err;
|
||||
bool ret = Process::Exec(cmd.c_str(), argv, NULL, out, &err);
|
||||
bool ret = Process::Exec(cmd.c_str(), argv, nullptr, out, &err);
|
||||
if (getenv("SHOW_COMPILE")) {
|
||||
Logger::Info("%s", out.c_str());
|
||||
} else {
|
||||
@@ -364,7 +364,7 @@ void Construct::dumpNode(int spc) {
|
||||
}
|
||||
|
||||
string refstr;
|
||||
if (dynamic_cast<SimpleVariable*>(this) != NULL) {
|
||||
if (dynamic_cast<SimpleVariable*>(this) != nullptr) {
|
||||
if (isReferencedValid()) {
|
||||
if (isReferenced()) {
|
||||
refstr += ",Referenced";
|
||||
@@ -380,7 +380,7 @@ void Construct::dumpNode(int spc) {
|
||||
if (refstr != "") refstr = " (" + refstr.substr(1) + ")";
|
||||
|
||||
string objstr;
|
||||
if (dynamic_cast<SimpleVariable*>(this) != NULL) {
|
||||
if (dynamic_cast<SimpleVariable*>(this) != nullptr) {
|
||||
if (isNeededValid()) {
|
||||
if (isNeeded()) {
|
||||
objstr += "Object";
|
||||
+1
-1
@@ -164,7 +164,7 @@ bool ArrayPairExpression::outputCPPName(CodeGenerator &cg,
|
||||
string s = sc->getLiteralString();
|
||||
int64 res;
|
||||
if (is_strictly_integer(s.c_str(), s.size(), res)) {
|
||||
cg_printf("%sLL", s.c_str());
|
||||
cg_printf("%sL", s.c_str());
|
||||
} else {
|
||||
m_name->outputCPP(cg, ar);
|
||||
}
|
||||
+1
-1
@@ -489,7 +489,7 @@ void AssignmentExpression::outputCPPImpl(CodeGenerator &cg,
|
||||
|
||||
bool setNull = false;
|
||||
|
||||
if (SpecialAssignment(cg, ar, m_variable, m_value, NULL, ref)) {
|
||||
if (SpecialAssignment(cg, ar, m_variable, m_value, nullptr, ref)) {
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ ClassConstantExpression::ClassConstantExpression
|
||||
ExpressionPtr classExp, const std::string &varName)
|
||||
: Expression(
|
||||
EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClassConstantExpression)),
|
||||
StaticClassName(classExp), m_varName(varName), m_defScope(NULL),
|
||||
StaticClassName(classExp), m_varName(varName), m_defScope(nullptr),
|
||||
m_valid(false), m_depsSet(false) {
|
||||
}
|
||||
|
||||
+1
-1
@@ -255,7 +255,7 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
// read value and dynamic-ness together + check() atomically
|
||||
value = constants->getValue(m_name);
|
||||
isDynamic = constants->isDynamic(m_name);
|
||||
BlockScope *defScope = NULL;
|
||||
BlockScope *defScope = nullptr;
|
||||
std::vector<std::string> bases;
|
||||
actualType = constants->check(getScope(), m_name, type, coerce,
|
||||
ar, self, bases, defScope);
|
||||
@@ -484,7 +484,7 @@ TypePtr Expression::inferAssignmentTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
// ...as in ClassConstant statement
|
||||
ConstantExpressionPtr exp =
|
||||
dynamic_pointer_cast<ConstantExpression>(variable);
|
||||
BlockScope *defScope = NULL;
|
||||
BlockScope *defScope = nullptr;
|
||||
std::vector<std::string> bases;
|
||||
scope->getConstants()->check(getScope(), exp->getName(), ret,
|
||||
true, ar, variable,
|
||||
+2
-2
@@ -124,7 +124,7 @@ bool ExpressionList::isScalar() const {
|
||||
bool ExpressionList::isNoObjectInvolved() const {
|
||||
for (unsigned int i = 0; i < m_exps.size(); i++) {
|
||||
TypePtr t = m_exps[i]->getActualType();
|
||||
if (t == NULL || !t->isNoObjectInvolved())
|
||||
if (t == nullptr || !t->isNoObjectInvolved())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -674,7 +674,7 @@ void ExpressionList::outputCPPUniqLitKeyArrayInit(
|
||||
bool arrayElements /* = true */, unsigned int start /* = 0 */) {
|
||||
if (arrayElements) assert(m_arrayElements && !m_collectionType);
|
||||
unsigned int n = m_exps.size();
|
||||
cg_printf("array_createv%c(%lld, ", litstrKeys ? 's' : 'i', num);
|
||||
cg_printf("array_createv%c(%" PRId64 ", ", litstrKeys ? 's' : 'i', num);
|
||||
always_assert(n - start == num);
|
||||
for (unsigned int i = start; i < n; i++) {
|
||||
ExpressionPtr exp = m_exps[i];
|
||||
+2
-3
@@ -59,10 +59,9 @@ FunctionCall::FunctionCall
|
||||
m_nameExp->getKindOf() == Expression::KindOfScalarExpression) {
|
||||
assert(m_name.empty());
|
||||
ScalarExpressionPtr c = dynamic_pointer_cast<ScalarExpression>(m_nameExp);
|
||||
m_origName = c->getString();
|
||||
m_origName = c->getOriginalLiteralString();
|
||||
c->toLower(true /* func call*/);
|
||||
m_name = c->getString();
|
||||
assert(!m_name.empty());
|
||||
m_name = c->getLiteralString();
|
||||
} else {
|
||||
m_origName = name;
|
||||
m_name = Util::toLower(name);
|
||||
+22
-11
@@ -38,7 +38,7 @@ ObjectPropertyExpression::ObjectPropertyExpression
|
||||
: Expression(
|
||||
EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ObjectPropertyExpression)),
|
||||
LocalEffectsContainer(AccessorEffect),
|
||||
m_object(object), m_property(property), m_propSym(NULL) {
|
||||
m_object(object), m_property(property), m_propSym(nullptr) {
|
||||
m_valid = false;
|
||||
m_propSymValid = false;
|
||||
m_object->setContext(Expression::ObjectContext);
|
||||
@@ -72,7 +72,10 @@ bool ObjectPropertyExpression::isNonPrivate(AnalysisResultPtr ar) {
|
||||
}
|
||||
ScalarExpressionPtr name =
|
||||
dynamic_pointer_cast<ScalarExpression>(m_property);
|
||||
string propName = name->getString();
|
||||
string propName = name->getLiteralString();
|
||||
if (propName.empty()) {
|
||||
return false;
|
||||
}
|
||||
Symbol *sym = cls->getVariables()->getSymbol(propName);
|
||||
if (!sym || sym->isStatic() || !sym->isPrivate()) return true;
|
||||
return false;
|
||||
@@ -200,20 +203,24 @@ TypePtr ObjectPropertyExpression::inferTypes(AnalysisResultPtr ar,
|
||||
|
||||
if (!m_property->is(Expression::KindOfScalarExpression)) {
|
||||
m_property->inferAndCheck(ar, Type::String, false);
|
||||
|
||||
// we also lost track of which class variable an expression is about, hence
|
||||
// any type inference could be wrong. Instead, we just force variants on
|
||||
// all class variables.
|
||||
if (m_context & (LValue | RefValue)) {
|
||||
ar->forceClassVariants(getOriginalClass(), false, true);
|
||||
}
|
||||
|
||||
return Type::Variant; // we have to use a variant to hold dynamic value
|
||||
}
|
||||
|
||||
ScalarExpressionPtr exp = dynamic_pointer_cast<ScalarExpression>(m_property);
|
||||
const string &name = exp->getString();
|
||||
assert(!name.empty());
|
||||
const string &name = exp->getLiteralString();
|
||||
if (name.empty()) {
|
||||
m_property->inferAndCheck(ar, Type::String, false);
|
||||
if (m_context & (LValue | RefValue)) {
|
||||
ar->forceClassVariants(getOriginalClass(), false, true);
|
||||
}
|
||||
return Type::Variant; // we have to use a variant to hold dynamic value
|
||||
}
|
||||
|
||||
m_property->inferAndCheck(ar, Type::String, false);
|
||||
|
||||
@@ -456,7 +463,7 @@ void ObjectPropertyExpression::outputCPPObjProperty(CodeGenerator &cg,
|
||||
}
|
||||
cg_printf("(((%s%s*)obj_tmp)->%s%s)",
|
||||
Option::ClassPrefix, cls->getId().c_str(),
|
||||
Option::PropertyPrefix, name->getString().c_str());
|
||||
Option::PropertyPrefix, name->getLiteralString().c_str());
|
||||
|
||||
if (!write_context) {
|
||||
cg_printf(" : (raise_null_object_prop(),%s)",
|
||||
@@ -483,7 +490,8 @@ void ObjectPropertyExpression::outputCPPObjProperty(CodeGenerator &cg,
|
||||
m_object->getActualType()->isSpecificObject());
|
||||
ScalarExpressionPtr name =
|
||||
dynamic_pointer_cast<ScalarExpression>(m_property);
|
||||
cg_printf("%s%s", Option::PropertyPrefix, name->getString().c_str());
|
||||
cg_printf("%s%s", Option::PropertyPrefix,
|
||||
name->getLiteralString().c_str());
|
||||
if (doExist || doUnset) cg_printf(")");
|
||||
} else {
|
||||
cg_printf("%s(", func.c_str());
|
||||
@@ -628,10 +636,13 @@ void ObjectPropertyExpression::outputCPPProperty(CodeGenerator &cg,
|
||||
if (m_property->getKindOf() == Expression::KindOfScalarExpression) {
|
||||
ScalarExpressionPtr name =
|
||||
dynamic_pointer_cast<ScalarExpression>(m_property);
|
||||
cg_printString(name->getString(), ar, shared_from_this());
|
||||
} else {
|
||||
m_property->outputCPP(cg, ar);
|
||||
string propName = name->getLiteralString();
|
||||
if (!propName.empty()) {
|
||||
cg_printString(propName, ar, shared_from_this());
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_property->outputCPP(cg, ar);
|
||||
}
|
||||
|
||||
void ObjectPropertyExpression::outputCPPExistTest(CodeGenerator &cg,
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário