From 1c5e1c2fceb777a159c1a7ab651a08562691cdaf Mon Sep 17 00:00:00 2001 From: nemerle Date: Fri, 28 Feb 2014 11:26:02 +0100 Subject: [PATCH] replace boolT with plain old bool in a few places --- CMakeLists.txt | 4 +- CMakeScripts/cotire.cmake | 2762 +++++++++++++++++++++++++++++++++++ include/BasicBlock.h | 2 +- include/Enums.h | 2 +- include/Procedure.h | 2 + include/ast.h | 2 + include/dcc.h | 20 +- include/icode.h | 24 +- include/project.h | 4 + include/state.h | 2 +- src/BasicBlock.cpp | 16 +- src/RegisterNode.cpp | 119 ++ src/ast.cpp | 18 +- src/backend.cpp | 9 +- src/chklib.cpp | 12 +- src/control.cpp | 6 +- src/dataflow.cpp | 50 +- src/dcc.cpp | 58 +- src/disassem.cpp | 6 +- src/fixwild.cpp | 3 +- src/frontend.cpp | 4 +- src/graph.cpp | 18 +- src/hlicode.cpp | 65 +- src/hltype.cpp | 2 +- src/idioms.cpp | 6 +- src/idioms/mov_idioms.cpp | 3 +- src/idioms/neg_idioms.cpp | 2 +- src/idioms/shift_idioms.cpp | 6 +- src/liveness_set.cpp | 54 + src/parser.cpp | 7 +- src/procs.cpp | 7 +- src/project.cpp | 4 +- src/proplong.cpp | 2 +- src/reducible.cpp | 16 +- src/scanner.cpp | 42 +- src/symtab.cpp | 4 +- src/udm.cpp | 2 +- 37 files changed, 3154 insertions(+), 211 deletions(-) create mode 100644 CMakeScripts/cotire.cmake create mode 100644 src/RegisterNode.cpp create mode 100644 src/liveness_set.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a454609..60d6cd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,11 +113,11 @@ SOURCE_GROUP(Source FILES ${dcc_SOURCES}) SOURCE_GROUP(Headers FILES ${dcc_HEADERS}) ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS}) -cotire(dcc_lib) +#cotire(dcc_lib) ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS}) ADD_DEPENDENCIES(dcc_original dcc_lib) -TARGET_LINK_LIBRARIES(dcc_original dcc_lib disasm_s ${REQ_LLVM_LIBRARIES}) +TARGET_LINK_LIBRARIES(dcc_original dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} ncurses) if(dcc_build_tests) ADD_SUBDIRECTORY(src) endif() diff --git a/CMakeScripts/cotire.cmake b/CMakeScripts/cotire.cmake new file mode 100644 index 0000000..3cd4c05 --- /dev/null +++ b/CMakeScripts/cotire.cmake @@ -0,0 +1,2762 @@ +# - cotire (compile time reducer) +# +# See the cotire manual for usage hints. +# +#============================================================================= +# Copyright 2012 Sascha Kratky +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +#============================================================================= + +if(__COTIRE_INCLUDED) + return() +endif() +set(__COTIRE_INCLUDED TRUE) + +# we need the CMake variables CMAKE_SCRIPT_MODE_FILE and CMAKE_ARGV available since 2.8.5 +# we need APPEND_STRING option for set_property available since 2.8.6 +cmake_minimum_required(VERSION 2.8.6) + +set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") +set (COTIRE_CMAKE_MODULE_VERSION "1.1.2") + +include(CMakeParseArguments) + +function (cotire_determine_compiler_version _language _versionPrefix) + if (NOT ${_versionPrefix}_VERSION) + if (MSVC) + # use CMake's predefined version variable for MSVC, if available + if (DEFINED MSVC_VERSION) + set (${_versionPrefix}_VERSION "${MSVC_VERSION}") + else() + # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared + unset (ENV{VS_UNICODE_OUTPUT}) + string (STRIP "${CMAKE_${_language}_COMPILER_ARG1}" _compilerArg1) + execute_process (COMMAND ${CMAKE_${_language}_COMPILER} ${_compilerArg1} + ERROR_VARIABLE _versionLine OUTPUT_QUIET TIMEOUT 10) + string (REGEX REPLACE ".*Version *([0-9]+(\\.[0-9]+)*).*" "\\1" + ${_versionPrefix}_VERSION "${_versionLine}") + endif() + else() + # use CMake's predefined compiler version variable (available since CMake 2.8.8) + if (DEFINED CMAKE_${_language}_COMPILER_VERSION) + set (${_versionPrefix}_VERSION "${CMAKE_${_language}_COMPILER_VERSION}") + else() + # assume GCC like command line interface + string (STRIP "${CMAKE_${_language}_COMPILER_ARG1}" _compilerArg1) + execute_process (COMMAND ${CMAKE_${_language}_COMPILER} ${_compilerArg1} "-dumpversion" + OUTPUT_VARIABLE ${_versionPrefix}_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE TIMEOUT 10) + endif() + endif() + if (${_versionPrefix}_VERSION) + set (${_versionPrefix}_VERSION "${${_versionPrefix}_VERSION}" CACHE INTERNAL "${_language} compiler version") + endif() + set (${_versionPrefix}_VERSION "${${_versionPrefix}_VERSION}" PARENT_SCOPE) + if (COTIRE_DEBUG) + message (STATUS "${CMAKE_${_language}_COMPILER} version ${${_versionPrefix}_VERSION}") + endif() + endif() +endfunction() + +function (cotire_get_source_file_extension _sourceFile _extVar) + # get_filename_component returns extension from first occurrence of . in file name + # this function computes the extension from last occurrence of . in file name + string (FIND "${_sourceFile}" "." _index REVERSE) + if (_index GREATER -1) + math (EXPR _index "${_index} + 1") + string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) + else() + set (_sourceExt "") + endif() + set (${_extVar} "${_sourceExt}" PARENT_SCOPE) +endfunction() + +macro (cotire_check_is_path_relative_to _path _isRelativeVar) + set (${_isRelativeVar} FALSE) + if (IS_ABSOLUTE "${_path}") + foreach (_dir ${ARGN}) + file (RELATIVE_PATH _relPath "${_dir}" "${_path}") + if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) + set (${_isRelativeVar} TRUE) + break() + endif() + endforeach() + endif() +endmacro() + +function (cotire_filter_language_source_files _language _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) + set (_sourceFiles "") + set (_excludedSourceFiles "") + set (_cotiredSourceFiles "") + if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) + set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") + else() + set (_languageExtensions "") + endif() + if (CMAKE_${_language}_IGNORE_EXTENSIONS) + set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") + else() + set (_ignoreExtensions "") + endif() + if (COTIRE_DEBUG) + message (STATUS "${_language} source file extensions: ${_languageExtensions}") + message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") + endif() + foreach (_sourceFile ${ARGN}) + get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) + get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) + get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) + get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) + set (_sourceIsFiltered FALSE) + if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) + cotire_get_source_file_extension("${_sourceFile}" _sourceExt) + if (_sourceExt) + list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) + list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) + if (_sourceIndex GREATER -1 AND _ignoreIndex LESS 0) + set (_sourceIsFiltered TRUE) + endif() + endif() + endif() + if (COTIRE_DEBUG) + message (STATUS "${_sourceFile} filtered=${_sourceIsFiltered} language=${_sourceLanguage} header=${_sourceIsHeaderOnly}") + endif() + if (_sourceIsFiltered) + get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) + get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) + get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) + if (COTIRE_DEBUG) + message (STATUS "${_sourceFile} excluded=${_sourceIsExcluded} cotired=${_sourceIsCotired}") + endif() + if (_sourceIsCotired) + list (APPEND _cotiredSourceFiles "${_sourceFile}") + elseif (_sourceIsExcluded OR _sourceCompileFlags) + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + list (APPEND _sourceFiles "${_sourceFile}") + endif() + endif() + endforeach() + if (COTIRE_DEBUG) + message (STATUS "All: ${ARGN}") + message (STATUS "${_language}: ${_sourceFiles}") + message (STATUS "Excluded: ${_excludedSourceFiles}") + message (STATUS "Cotired: ${_cotiredSourceFiles}") + endif() + set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) + set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) + set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) +endfunction() + +function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) + set (_filteredObjects "") + foreach (_object ${ARGN}) + get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (_propertyValue) + list (APPEND _filteredObjects "${_object}") + endif() + endif() + endforeach() + set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) +endfunction() + +function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) + set (_filteredObjects "") + foreach (_object ${ARGN}) + get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (NOT _propertyValue) + list (APPEND _filteredObjects "${_object}") + endif() + endif() + endforeach() + set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_file_property_values _valuesVar _property) + set (_values "") + foreach (_sourceFile ${ARGN}) + get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) + if (_propertyValue) + list (APPEND _values "${_propertyValue}") + endif() + endforeach() + set (${_valuesVar} ${_values} PARENT_SCOPE) +endfunction() + +function (cotrie_resolve_config_properites _configurations _propertiesVar) + set (_properties "") + foreach (_property ${ARGN}) + if ("${_property}" MATCHES "") + foreach (_config ${_configurations}) + string (TOUPPER "${_config}" _upperConfig) + string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") + list (APPEND _properties ${_configProperty}) + endforeach() + else() + list (APPEND _properties ${_property}) + endif() + endforeach() + set (${_propertiesVar} ${_properties} PARENT_SCOPE) +endfunction() + +function (cotrie_copy_set_properites _configurations _type _source _target) + cotrie_resolve_config_properites("${_configurations}" _properties ${ARGN}) + foreach (_property ${_properties}) + get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) + set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") + endif() + endforeach() +endfunction() + +function (cotire_filter_compile_flags _flagFilter _matchedOptionsVar _unmatchedOptionsVar) + if (MSVC) + set (_flagPrefix "[/-]") + else() + set (_flagPrefix "--?") + endif() + set (_optionFlag "") + set (_matchedOptions "") + set (_unmatchedOptions "") + foreach (_compileFlag ${ARGN}) + if (_compileFlag) + if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") + # option with separate argument + list (APPEND _matchedOptions "${_compileFlag}") + set (_optionFlag "") + elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") + # remember option + set (_optionFlag "${CMAKE_MATCH_2}") + elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") + # option with joined argument + list (APPEND _matchedOptions "${CMAKE_MATCH_3}") + set (_optionFlag "") + else() + # flush remembered option + if (_optionFlag) + list (APPEND _matchedOptions "${_optionFlag}") + set (_optionFlag "") + endif() + # add to unfiltered options + list (APPEND _unmatchedOptions "${_compileFlag}") + endif() + endif() + endforeach() + if (_optionFlag) + list (APPEND _matchedOptions "${_optionFlag}") + endif() + if (COTIRE_DEBUG) + message (STATUS "Filter ${_flagFilter}") + if (_matchedOptions) + message (STATUS "Matched ${_matchedOptions}") + endif() + if (_unmatchedOptions) + message (STATUS "Unmatched ${_unmatchedOptions}") + endif() + endif() + set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) + set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compile_flags _config _language _directory _target _flagsVar) + string (TOUPPER "${_config}" _upperConfig) + # collect options from CMake language variables + set (_compileFlags "") + if (CMAKE_${_language}_FLAGS) + set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") + endif() + if (CMAKE_${_language}_FLAGS_${_upperConfig}) + set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") + endif() + if (_target) + # add option from CMake target type variable + get_target_property(_targetType ${_target} TYPE) + if (_targetType STREQUAL "MODULE_LIBRARY") + # flags variable for module library uses different name SHARED_MODULE + # (e.g., CMAKE_SHARED_MODULE_C_FLAGS) + set (_targetType SHARED_MODULE) + endif() + if (CMAKE_${_targetType}_${_language}_FLAGS) + set (_compileFlags "${_compileFlags} ${CMAKE_${_targetType}_${_language}_FLAGS}") + endif() + endif() + if (_directory) + # add_definitions may have been used to add flags to the compiler command + get_directory_property(_dirDefinitions DIRECTORY "${_directory}" DEFINITIONS) + if (_dirDefinitions) + set (_compileFlags "${_compileFlags} ${_dirDefinitions}") + endif() + endif() + if (_target) + # add target compile options + get_target_property(_targetflags ${_target} COMPILE_FLAGS) + if (_targetflags) + set (_compileFlags "${_compileFlags} ${_targetflags}") + endif() + endif() + if (UNIX) + separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") + elseif(WIN32) + separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") + else() + separate_arguments(_compileFlags) + endif() + # platform specific flags + if (APPLE) + get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) + if (NOT _architectures) + get_target_property(_architectures ${_target} OSX_ARCHITECTURES) + endif() + foreach (_arch ${_architectures}) + list (APPEND _compileFlags "-arch" "${_arch}") + endforeach() + if (CMAKE_OSX_SYSROOT AND CMAKE_OSX_SYSROOT_DEFAULT AND CMAKE_${_language}_HAS_ISYSROOT) + if (NOT "${CMAKE_OSX_SYSROOT}" STREQUAL "${CMAKE_OSX_SYSROOT_DEFAULT}") + list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") + endif() + endif() + if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) + list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + endif() + if (COTIRE_DEBUG AND _compileFlags) + message (STATUS "Target ${_target} compile flags ${_compileFlags}") + endif() + set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_include_directories _config _language _directory _target _includeDirsVar) + set (_includeDirs "") + # default include dirs + if (CMAKE_INCLUDE_CURRENT_DIR) + list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}") + list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}") + endif() + # parse additional include directories from target compile flags + cotire_get_target_compile_flags("${_config}" "${_language}" "${_directory}" "${_target}" _targetFlags) + cotire_filter_compile_flags("I" _dirs _ignore ${_targetFlags}) + if (_dirs) + list (APPEND _includeDirs ${_dirs}) + endif() + # target include directories + get_directory_property(_dirs DIRECTORY "${_directory}" INCLUDE_DIRECTORIES) + if (_target) + get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + list (REMOVE_DUPLICATES _dirs) + endif() + endif() + list (LENGTH _includeDirs _projectInsertIndex) + foreach (_dir ${_dirs}) + if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) + cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") + if (_isRelative) + list (INSERT _includeDirs _projectInsertIndex "${_dir}") + math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") + else() + list (APPEND _includeDirs "${_dir}") + endif() + else() + list (APPEND _includeDirs "${_dir}") + endif() + endforeach() + list (REMOVE_DUPLICATES _includeDirs) + if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) + list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) + endif() + if (COTIRE_DEBUG AND _includeDirs) + message (STATUS "Target ${_target} include dirs ${_includeDirs}") + endif() + set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) +endfunction() + +macro (cotire_make_C_identifier _identifierVar _str) + # mimic CMake SystemTools::MakeCindentifier behavior + if ("${_str}" MATCHES "^[0-9].+$") + set (_str "_${str}") + endif() + string (REGEX REPLACE "[^a-zA-Z0-9]" "_" ${_identifierVar} "${_str}") +endmacro() + +function (cotire_get_target_export_symbol _target _exportSymbolVar) + set (_exportSymbol "") + get_target_property(_targetType ${_target} TYPE) + get_target_property(_enableExports ${_target} ENABLE_EXPORTS) + if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR + (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) + get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) + if (NOT _exportSymbol) + set (_exportSymbol "${_target}_EXPORTS") + endif() + cotire_make_C_identifier(_exportSymbol "${_exportSymbol}") + endif() + set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compile_definitions _config _language _directory _target _definitionsVar) + string (TOUPPER "${_config}" _upperConfig) + set (_configDefinitions "") + # CMAKE_INTDIR for multi-configuration build systems + if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") + list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") + endif() + # target export define symbol + cotire_get_target_export_symbol("${_target}" _defineSymbol) + if (_defineSymbol) + list (APPEND _configDefinitions "${_defineSymbol}") + endif() + # directory compile definitions + get_directory_property(_definitions DIRECTORY "${_directory}" COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + get_directory_property(_definitions DIRECTORY "${_directory}" COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + # target compile definitions + get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + # parse additional compile definitions from target compile flags + # and don't look at directory compile definitions, which we already handled + cotire_get_target_compile_flags("${_config}" "${_language}" "" "${_target}" _targetFlags) + cotire_filter_compile_flags("D" _definitions _ignore ${_targetFlags}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + list (REMOVE_DUPLICATES _configDefinitions) + if (COTIRE_DEBUG AND _configDefinitions) + message (STATUS "Target ${_target} compile definitions ${_configDefinitions}") + endif() + set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compiler_flags _config _language _directory _target _compilerFlagsVar) + # parse target compile flags omitting compile definitions and include directives + cotire_get_target_compile_flags("${_config}" "${_language}" "${_directory}" "${_target}" _targetFlags) + cotire_filter_compile_flags("[ID]" _ignore _compilerFlags ${_targetFlags}) + if (COTIRE_DEBUG AND _compileFlags) + message (STATUS "Target ${_target} compiler flags ${_compileFlags}") + endif() + set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) +endfunction() + +function (cotire_add_sys_root_paths _pathsVar) + if (APPLE) + if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) + foreach (_path IN LISTS ${_pathsVar}) + if (IS_ABSOLUTE "${_path}") + get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) + if (EXISTS "${_path}") + list (APPEND ${_pathsVar} "${_path}") + endif() + endif() + endforeach() + endif() + endif() + set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) + if (COTIRE_DEBUG) + message (STATUS "${_pathsVar}=${${_pathsVar}}") + endif() +endfunction() + +function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) + set (_extraProperties ${ARGN}) + set (_result "") + if (_extraProperties) + list (FIND _extraProperties "${_sourceFile}" _index) + if (_index GREATER -1) + math (EXPR _index "${_index} + 1") + list (LENGTH _extraProperties _len) + math (EXPR _len "${_len} - 1") + foreach (_index RANGE ${_index} ${_len}) + list (GET _extraProperties ${_index} _value) + if ("${_value}" MATCHES "${_pattern}") + list (APPEND _result "${_value}") + else() + break() + endif() + endforeach() + endif() + endif() + set (${_resultVar} ${_result} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) + set (_compileDefinitions "") + if (NOT CMAKE_SCRIPT_MODE_FILE) + string (TOUPPER "${_config}" _upperConfig) + get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + endif() + cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + if (COTIRE_DEBUG AND _compileDefinitions) + message (STATUS "Source ${_sourceFile} compile definitions ${_compileDefinitions}") + endif() + set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) + set (_configDefinitions "") + foreach (_sourceFile ${ARGN}) + cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) + if (_sourceDefinitions) + list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") + endif() + endforeach() + set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) + set (_sourceUndefs "") + if (NOT CMAKE_SCRIPT_MODE_FILE) + get_source_file_property(_undefs "${_sourceFile}" ${_property}) + if (_undefs) + list (APPEND _sourceUndefs ${_undefs}) + endif() + endif() + cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) + if (_undefs) + list (APPEND _sourceUndefs ${_undefs}) + endif() + if (COTIRE_DEBUG AND _sourceUndefs) + message (STATUS "Source ${_sourceFile} ${_property} undefs ${_sourceUndefs}") + endif() + set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_files_undefs _property _sourceUndefsVar) + set (_sourceUndefs "") + foreach (_sourceFile ${ARGN}) + cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) + if (_undefs) + list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") + endif() + endforeach() + set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) +endfunction() + +macro (cotire_set_cmd_to_prologue _cmdVar) + set (${_cmdVar} "${CMAKE_COMMAND}") + list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") + if (COTIRE_VERBOSE) + list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") + elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") + list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") + endif() +endmacro() + +function (cotire_init_compile_cmd _cmdVar _language _compilerExe _compilerArg1) + if (NOT _compilerExe) + set (_compilerExe "${CMAKE_${_language}_COMPILER") + endif() + if (NOT _compilerArg1) + set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) + endif() + string (STRIP "${_compilerArg1}" _compilerArg1) + set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) +endfunction() + +macro (cotire_add_definitions_to_cmd _cmdVar) + foreach (_definition ${ARGN}) + if (MSVC) + list (APPEND ${_cmdVar} "/D${_definition}") + else() + list (APPEND ${_cmdVar} "-D${_definition}") + endif() + endforeach() +endmacro() + +macro (cotire_add_includes_to_cmd _cmdVar) + foreach (_include ${ARGN}) + if (MSVC) + file (TO_NATIVE_PATH "${_include}" _include) + list (APPEND ${_cmdVar} "/I${_include}") + else() + list (APPEND ${_cmdVar} "-I${_include}") + endif() + endforeach() +endmacro() + +macro (cotire_add_compile_flags_to_cmd _cmdVar) + foreach (_flag ${ARGN}) + list (APPEND ${_cmdVar} "${_flag}") + endforeach() +endmacro() + +function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) + set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) + set (_triggerFile "") + foreach (_dependencyFile ${ARGN}) + if (EXISTS "${_dependencyFile}" AND "${_dependencyFile}" IS_NEWER_THAN "${_file}") + set (_triggerFile "${_dependencyFile}") + break() + endif() + endforeach() + get_filename_component(_fileName "${_file}" NAME) + if (EXISTS "${_file}") + if (_triggerFile) + if (COTIRE_VERBOSE) + message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") + endif() + else() + if (COTIRE_VERBOSE) + message (STATUS "${_fileName} is up-to-date.") + endif() + set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) + endif() + else() + if (COTIRE_VERBOSE) + message (STATUS "${_fileName} does not exist yet.") + endif() + endif() +endfunction() + +macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) + set (${_relPathVar} "") + foreach (_includeDir ${_includeDirs}) + if (IS_DIRECTORY "${_includeDir}") + file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") + if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") + string (LENGTH "${${_relPathVar}}" _closestLen) + string (LENGTH "${_relPath}" _relLen) + if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) + set (${_relPathVar} "${_relPath}") + endif() + endif() + elseif ("${_includeDir}" STREQUAL "${_headerFile}") + # if path matches exactly, return short non-empty string + set (${_relPathVar} "1") + break() + endif() + endforeach() +endmacro() + +macro (cotire_check_header_file_location _headerFile _insideIncudeDirs _outsideIncudeDirs _headerIsInside) + # check header path against ignored and honored include directories + cotire_find_closest_relative_path("${_headerFile}" "${_insideIncudeDirs}" _insideRelPath) + if (_insideRelPath) + # header is inside, but could be become outside if there is a shorter outside match + cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncudeDirs}" _outsideRelPath) + if (_outsideRelPath) + string (LENGTH "${_insideRelPath}" _insideRelPathLen) + string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) + if (_outsideRelPathLen LESS _insideRelPathLen) + set (${_headerIsInside} FALSE) + else() + set (${_headerIsInside} TRUE) + endif() + else() + set (${_headerIsInside} TRUE) + endif() + else() + # header is outside + set (${_headerIsInside} FALSE) + endif() +endmacro() + +macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) + if (NOT EXISTS "${_headerFile}") + set (${_headerIsIgnoredVar} TRUE) + elseif (IS_DIRECTORY "${_headerFile}") + set (${_headerIsIgnoredVar} TRUE) + elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed" AND "${_headerFile}" MATCHES "\\.h$") + # heuristic: ignore C headers with embedded parent directory references or "-fixed" or "_fixed" in path + # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation + # with the error message "error: no include path in which to search for header.h" + set (${_headerIsIgnoredVar} TRUE) + else() + set (${_headerIsIgnoredVar} FALSE) + endif() +endmacro() + +macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) + # check header file extension + cotire_get_source_file_extension("${_headerFile}" _headerFileExt) + set (${_headerIsIgnoredVar} FALSE) + if (_headerFileExt) + list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) + if (_index GREATER -1) + set (${_headerIsIgnoredVar} TRUE) + endif() + endif() +endmacro() + +macro (cotire_parse_line _line _headerFileVar _headerDepthVar) + if (MSVC) + # cl.exe /showIncludes output looks different depending on the language pack used, e.g.: + # English: "Note: including file: C:\directory\file" + # German: "Hinweis: Einlesen der Datei: C:\directory\file" + # We use a very general regular expression, relying on the presence of the : characters + if ("${_line}" MATCHES ":( +)([^:]+:[^:]+)$") + # Visual Studio compiler output + string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) + get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) + else() + set (${_headerFileVar} "") + set (${_headerDepthVar} 0) + endif() + else() + if ("${_line}" MATCHES "^(\\.+) (.*)$") + # GCC like output + string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) + if (IS_ABSOLUTE "${CMAKE_MATCH_2}") + set (${_headerFileVar} "${CMAKE_MATCH_2}") + else() + get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) + endif() + else() + set (${_headerFileVar} "") + set (${_headerDepthVar} 0) + endif() + endif() +endmacro() + +function (cotire_parse_includes _language _scanOutput _ignoredIncudeDirs _honoredIncudeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) + if (WIN32) + # prevent CMake macro invocation errors due to backslash characters in Windows paths + string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") + endif() + string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") + string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") + list (LENGTH _scanOutput _len) + # remove duplicate lines to speed up parsing + list (REMOVE_DUPLICATES _scanOutput) + list (LENGTH _scanOutput _uniqueLen) + if (COTIRE_VERBOSE) + message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") + if (_ignoredExtensions) + message (STATUS "Ignored extensions: ${_ignoredExtensions}") + endif() + if (_ignoredIncudeDirs) + message (STATUS "Ignored paths: ${_ignoredIncudeDirs}") + endif() + if (_honoredIncudeDirs) + message (STATUS "Included paths: ${_honoredIncudeDirs}") + endif() + endif() + set (_sourceFiles ${ARGN}) + set (_selectedIncludes "") + set (_unparsedLines "") + # stack keeps track of inside/outside project status of processed header files + set (_headerIsInsideStack "") + foreach (_line IN LISTS _scanOutput) + if (_line) + cotire_parse_line("${_line}" _headerFile _headerDepth) + if (_headerFile) + cotire_check_header_file_location("${_headerFile}" "${_ignoredIncudeDirs}" "${_honoredIncudeDirs}" _headerIsInside) + if (COTIRE_DEBUG) + message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") + endif() + # update stack + list (LENGTH _headerIsInsideStack _stackLen) + if (_headerDepth GREATER _stackLen) + math (EXPR _stackLen "${_stackLen} + 1") + foreach (_index RANGE ${_stackLen} ${_headerDepth}) + list (APPEND _headerIsInsideStack ${_headerIsInside}) + endforeach() + else() + foreach (_index RANGE ${_headerDepth} ${_stackLen}) + list (REMOVE_AT _headerIsInsideStack -1) + endforeach() + list (APPEND _headerIsInsideStack ${_headerIsInside}) + endif() + if (COTIRE_DEBUG) + message (STATUS "${_headerIsInsideStack}") + endif() + # header is a candidate if it is outside project + if (NOT _headerIsInside) + # get parent header file's inside/outside status + if (_headerDepth GREATER 1) + math (EXPR _index "${_headerDepth} - 2") + list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) + else() + set (_parentHeaderIsInside TRUE) + endif() + # select header file if parent header file is inside project + # (e.g., a project header file that includes a standard header file) + if (_parentHeaderIsInside) + cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) + if (NOT _headerIsIgnored) + cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) + if (NOT _headerIsIgnored) + list (APPEND _selectedIncludes "${_headerFile}") + else() + # fix header's inside status on stack, it is ignored by extension now + list (REMOVE_AT _headerIsInsideStack -1) + list (APPEND _headerIsInsideStack TRUE) + endif() + endif() + if (COTIRE_DEBUG) + message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") + endif() + endif() + endif() + else() + if (MSVC) + # for cl.exe do not keep unparsed lines which solely consist of a source file name + string (FIND "${_sourceFiles}" "${_line}" _index) + if (_index LESS 0) + list (APPEND _unparsedLines "${_line}") + endif() + else() + list (APPEND _unparsedLines "${_line}") + endif() + endif() + endif() + endforeach() + list (REMOVE_DUPLICATES _selectedIncludes) + set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) + set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) +endfunction() + +function (cotire_scan_includes _includesVar) + set(_options "") + set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_VERSION LANGUAGE UNPARSED_LINES) + set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + if (NOT _option_LANGUAGE) + set (_option_LANGUAGE "CXX") + endif() + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + set (_cmd "${_option_COMPILER_EXECUTABLE}" ${_option_COMPILER_ARG1}) + cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") + cotire_add_definitions_to_cmd(_cmd ${_option_COMPILE_DEFINITIONS}) + cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) + cotire_add_includes_to_cmd(_cmd ${_option_INCLUDE_DIRECTORIES}) + cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) + # only consider existing source files for scanning + set (_existingSourceFiles "") + foreach (_sourceFile ${_sourceFiles}) + if (EXISTS "${_sourceFile}") + list (APPEND _existingSourceFiles "${_sourceFile}") + endif() + endforeach() + if (NOT _existingSourceFiles) + set (${_includesVar} "" PARENT_SCOPE) + return() + endif() + list (APPEND _cmd ${_existingSourceFiles}) + if (COTIRE_VERBOSE) + message (STATUS "execute_process: ${_cmd}") + endif() + if ("${_option_COMPILER_ID}" STREQUAL "MSVC") + if (COTIRE_DEBUG) + message (STATUS "clearing VS_UNICODE_OUTPUT") + endif() + # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared + unset (ENV{VS_UNICODE_OUTPUT}) + endif() + execute_process(COMMAND ${_cmd} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_QUIET ERROR_VARIABLE _output) + cotire_parse_includes( + "${_option_LANGUAGE}" "${_output}" + "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" + "${_option_IGNORE_EXTENSIONS}" + _includes _unparsedLines + ${_sourceFiles}) + set (${_includesVar} ${_includes} PARENT_SCOPE) + if (_option_UNPARSED_LINES) + set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) + endif() +endfunction() + +macro (cotire_append_undefs _contentsVar) + set (_undefs ${ARGN}) + if (_undefs) + list (REMOVE_DUPLICATES _undefs) + foreach (_definition ${_undefs}) + list (APPEND ${_contentsVar} "#undef ${_definition}") + endforeach() + endif() +endmacro() + +macro (cotire_comment_str _language _commentText _commentVar) + if ("${_language}" STREQUAL "CMAKE") + set (${_commentVar} "# ${_commentText}") + else() + set (${_commentVar} "/* ${_commentText} */") + endif() +endmacro() + +function (cotire_write_file _language _file _contents _force) + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) + cotire_comment_str("${_language}" "${_file}" _header2) + set (_contents "${_header1}\n${_header2}\n${_contents}") + if (COTIRE_DEBUG) + message (STATUS "${_contents}") + endif() + if (_force OR NOT EXISTS "${_file}") + file (WRITE "${_file}" "${_contents}") + else() + file (READ "${_file}" _oldContents) + if (NOT "${_oldContents}" STREQUAL "${_contents}") + file (WRITE "${_file}" "${_contents}") + else() + if (COTIRE_DEBUG) + message (STATUS "${_file} unchanged") + endif() + endif() + endif() +endfunction() + +function (cotire_generate_unity_source _unityFile) + set(_options "") + set(_oneValueArgs LANGUAGE) + set(_multiValueArgs + DEPENDS SOURCES_COMPILE_DEFINITIONS + PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (_option_DEPENDS) + cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) + if (_unityFileIsUpToDate) + return() + endif() + endif() + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + if (NOT _option_PRE_UNDEFS) + set (_option_PRE_UNDEFS "") + endif() + if (NOT _option_SOURCES_PRE_UNDEFS) + set (_option_SOURCES_PRE_UNDEFS "") + endif() + if (NOT _option_POST_UNDEFS) + set (_option_POST_UNDEFS "") + endif() + if (NOT _option_SOURCES_POST_UNDEFS) + set (_option_SOURCES_POST_UNDEFS "") + endif() + set (_contents "") + if (_option_LANGUAGE AND _sourceFiles) + if ("${_option_LANGUAGE}" STREQUAL "CXX") + list (APPEND _contents "#ifdef __cplusplus") + elseif ("${_option_LANGUAGE}" STREQUAL "C") + list (APPEND _contents "#ifndef __cplusplus") + endif() + endif() + set (_compileUndefinitions "") + foreach (_sourceFile ${_sourceFiles}) + cotire_get_source_compile_definitions( + "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions + ${_option_SOURCES_COMPILE_DEFINITIONS}) + cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) + cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) + if (_option_PRE_UNDEFS) + list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) + endif() + if (_sourcePreUndefs) + list (APPEND _compileUndefinitions ${_sourcePreUndefs}) + endif() + if (_compileUndefinitions) + cotire_append_undefs(_contents ${_compileUndefinitions}) + set (_compileUndefinitions "") + endif() + if (_sourcePostUndefs) + list (APPEND _compileUndefinitions ${_sourcePostUndefs}) + endif() + if (_option_POST_UNDEFS) + list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) + endif() + foreach (_definition ${_compileDefinitions}) + if ("${_definition}" MATCHES "^([a-zA-Z0-9_]+)=(.+)$") + list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") + list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") + else() + list (APPEND _contents "#define ${_definition}") + list (INSERT _compileUndefinitions 0 "${_definition}") + endif() + endforeach() + get_filename_component(_sourceFile "${_sourceFile}" ABSOLUTE) + if (WIN32) + file (TO_NATIVE_PATH "${_sourceFile}" _sourceFile) + endif() + list (APPEND _contents "#include \"${_sourceFile}\"") + endforeach() + if (_compileUndefinitions) + cotire_append_undefs(_contents ${_compileUndefinitions}) + set (_compileUndefinitions "") + endif() + if (_option_LANGUAGE AND _sourceFiles) + list (APPEND _contents "#endif") + endif() + list (APPEND _contents "") + string (REPLACE ";" "\n" _contents "${_contents}") + if (COTIRE_VERBOSE) + message ("${_contents}") + endif() + cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) +endfunction() + +function (cotire_generate_prefix_header _prefixFile) + set(_options "") + set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ID COMPILER_VERSION) + set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS + INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (_option_DEPENDS) + cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) + if (_prefixFileIsUpToDate) + return() + endif() + endif() + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + cotire_scan_includes(_selectedHeaders ${_sourceFiles} + LANGUAGE "${_option_LANGUAGE}" + COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" + COMPILER_ID "${_option_COMPILER_ID}" + COMPILER_VERSION "${_option_COMPILER_VERSION}" + COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} + COMPILE_FLAGS ${_option_COMPILE_FLAGS} + INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} + IGNORE_PATH ${_option_IGNORE_PATH} + INCLUDE_PATH ${_option_INCLUDE_PATH} + IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} + UNPARSED_LINES _unparsedLines) + cotire_generate_unity_source("${_prefixFile}" LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) + set (_unparsedLinesFile "${_prefixFile}.log") + if (_unparsedLines) + if (COTIRE_VERBOSE OR NOT _selectedHeaders) + list (LENGTH _unparsedLines _skippedLineCount) + file (RELATIVE_PATH _unparsedLinesFileRelPath "${CMAKE_BINARY_DIR}" "${_unparsedLinesFile}") + message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesFileRelPath}") + endif() + string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") + file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}\n") + else() + file (REMOVE "${_unparsedLinesFile}") + endif() +endfunction() + +function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) + set (_flags ${${_flagsVar}}) + if ("${_compilerID}" STREQUAL "MSVC") + # cl.exe options used + # /nologo suppresses display of sign-on banner + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + # /EP preprocess to stdout without #line directives + # /showIncludes list include files + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) + else() + # return as a flag string + set (_flags "${_sourceFileType${_language}} /EP /showIncludes") + endif() + elseif ("${_compilerID}" STREQUAL "GNU") + # GCC options used + # -H print the name of each header file used + # -E invoke preprocessor + # -fdirectives-only do not expand macros, requires GCC >= 4.3 + if (_flags) + # append to list + list (APPEND _flags -H -E) + if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") + list (APPEND _flags "-fdirectives-only") + endif() + else() + # return as a flag string + set (_flags "-H -E") + if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") + set (_flags "${_flags} -fdirectives-only") + endif() + endif() + elseif ("${_compilerID}" STREQUAL "Clang") + # Clang options used + # -H print the name of each header file used + # -E invoke preprocessor + if (_flags) + # append to list + list (APPEND _flags -H -E) + else() + # return as a flag string + set (_flags "-H -E") + endif() + else() + message (FATAL_ERROR "Unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) + set (_flags ${${_flagsVar}}) + if ("${_compilerID}" STREQUAL "MSVC") + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) + # cl.exe options used + # /Yc creates a precompiled header file + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + # /Zs syntax check only + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" + "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") + else() + # return as a flag string + set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + endif() + elseif ("${_compilerID}" MATCHES "GNU|Clang") + # GCC / Clang options used + # -x specify the source language + # -c compile but do not link + # -o place output in file + set (_xLanguage_C "c-header") + set (_xLanguage_CXX "c++-header") + if (_flags) + # append to list + list (APPEND _flags "-x" "${_xLanguage_${_language}}" "-c" "${_prefixFile}" -o "${_pchFile}") + else() + # return as a flag string + set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") + endif() + else() + message (FATAL_ERROR "Unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_add_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) + set (_flags ${${_flagsVar}}) + if ("${_compilerID}" STREQUAL "MSVC") + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + # cl.exe options used + # /Yu uses a precompiled header file during build + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + if (_flags) + # append to list + list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") + else() + # return as a flag string + set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + endif() + elseif ("${_compilerID}" STREQUAL "GNU") + # GCC options used + # -include process include file as the first line of the primary source file + # -Winvalid-pch warns if precompiled header is found but cannot be used + if (_flags) + # append to list + list (APPEND _flags "-include" "${_prefixFile}" "-Winvalid-pch") + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\" -Winvalid-pch") + endif() + elseif ("${_compilerID}" STREQUAL "Clang") + # Clang options used + # -include process include file as the first line of the primary source file + # -Qunused-arguments don't emit warning for unused driver arguments + if (_flags) + # append to list + list (APPEND _flags "-include" "${_prefixFile}" "-Qunused-arguments") + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\" -Qunused-arguments") + endif() + else() + message (FATAL_ERROR "Unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) + set(_options "") + set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ID COMPILER_VERSION LANGUAGE) + set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_LANGUAGE) + set (_option_LANGUAGE "CXX") + endif() + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") + cotire_add_definitions_to_cmd(_cmd ${_option_COMPILE_DEFINITIONS}) + cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) + cotire_add_includes_to_cmd(_cmd ${_option_INCLUDE_DIRECTORIES}) + cotire_add_pch_compilation_flags( + "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) + if (COTIRE_VERBOSE) + message (STATUS "execute_process: ${_cmd}") + endif() + if ("${_option_COMPILER_ID}" STREQUAL "MSVC") + if (COTIRE_DEBUG) + message (STATUS "clearing VS_UNICODE_OUTPUT") + endif() + # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared + unset (ENV{VS_UNICODE_OUTPUT}) + endif() + execute_process(COMMAND ${_cmd} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" RESULT_VARIABLE _result) + if (_result) + message (FATAL_ERROR "Error ${_result} precompiling ${_prefixFile}.") + endif() +endfunction() + +function (cotire_check_precompiled_header_support _language _target _msgVar) + if (MSVC) + # supported since Visual Studio C++ 6.0 + # and CMake does not support an earlier version + set (${_msgVar} "" PARENT_SCOPE) + elseif ("${CMAKE_${_language}_COMPILER_ID}" STREQUAL "GNU") + # GCC PCH support requires GCC >= 3.4 + cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) + if ("${COTIRE_${_language}_COMPILER_VERSION}" MATCHES ".+" AND + "${COTIRE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") + set (${_msgVar} + "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID} version ${COTIRE_${_language}_COMPILER_VERSION}." + PARENT_SCOPE) + else() + set (${_msgVar} "" PARENT_SCOPE) + endif() + elseif ("${CMAKE_${_language}_COMPILER_ID}" STREQUAL "Clang") + # Clang has PCH support + set (${_msgVar} "" PARENT_SCOPE) + else() + set (${_msgVar} "Unsupported ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}." PARENT_SCOPE) + endif() + if (APPLE) + # PCH compilation not supported by GCC / Clang when multiple build architectures (e.g., i386, x86_64) are selected + if (CMAKE_CONFIGURATION_TYPES) + set (_configs ${CMAKE_CONFIGURATION_TYPES}) + else() + set (_configs ${CMAKE_BUILD_TYPE}) + endif() + foreach (_config ${_configs}) + cotire_get_target_compile_flags("${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" _targetFlags) + cotire_filter_compile_flags("arch" _architectures _ignore ${_targetFlags}) + list (LENGTH _architectures _numberOfArchitectures) + if (_numberOfArchitectures GREATER 1) + string (REPLACE ";" ", " _architectureStr "${_architectures}") + set (${_msgVar} + "Precompiled headers not supported on Darwin for multiple architecture builds (${_architectureStr})." + PARENT_SCOPE) + break() + endif() + endforeach() + endif() +endfunction() + +macro (cotire_get_intermediate_dir _cotireDir) + get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) +endmacro() + +function (cotire_make_untiy_source_file_paths _language _target _maxIncludes _unityFilesVar) + set (_sourceFiles ${ARGN}) + list (LENGTH _sourceFiles _numberOfSources) + set (_unityFileExt_C ".c") + set (_unityFileExt_CXX ".cxx") + if (NOT DEFINED _unityFileExt_${_language}) + set (${_unityFileVar} "" PARENT_SCOPE) + return() + endif() + set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") + cotire_get_intermediate_dir(_baseDir) + set (_startIndex 0) + set (_index 0) + set (_unityFiles "") + foreach (_sourceFile ${_sourceFiles}) + get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) + math (EXPR _unityFileCount "${_index} - ${_startIndex}") + if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) + if (_index GREATER 0) + math (EXPR _endIndex "${_index} - 1") + set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") + list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") + endif() + set (_startIndex ${_index}) + endif() + math (EXPR _index "${_index} + 1") + endforeach() + if (_startIndex EQUAL 0) + set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") + list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") + elseif (_startIndex LESS _numberOfSources) + math (EXPR _endIndex "${_index} - 1") + set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") + list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") + endif() + set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) + if (COTIRE_DEBUG) + message(STATUS "${_unityFiles}") + endif() +endfunction() + +function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) + set (_prefixFileExt_C ".h") + set (_prefixFileExt_CXX ".hxx") + if (NOT _language) + set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") + elseif (DEFINED _prefixFileExt_${_language}) + set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") + else() + set (_prefixFileBaseName "") + set (_prefixFileName "") + endif() + set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) + set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) +endfunction() + +function (cotire_make_prefix_file_path _language _target _prefixFileVar) + cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) + set (${_prefixFileVar} "" PARENT_SCOPE) + if (_prefixFileName) + if (NOT _language) + set (_language "C") + endif() + if (MSVC OR "${CMAKE_${_language}_COMPILER_ID}" MATCHES "GNU|Clang") + cotire_get_intermediate_dir(_baseDir) + set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) + endif() + endif() +endfunction() + +function (cotire_make_pch_file_path _language _target _pchFileVar) + cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) + set (${_pchFileVar} "" PARENT_SCOPE) + if (_prefixFileBaseName AND _prefixFileName) + cotire_check_precompiled_header_support("${_language}" "${_target}" _msg) + if (NOT _msg) + if (XCODE) + # For Xcode, we completely hand off the compilation of the prefix header to the IDE + return() + endif() + cotire_get_intermediate_dir(_baseDir) + if (MSVC) + # MSVC uses the extension .pch added to the prefix header base name + set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) + elseif ("${CMAKE_${_language}_COMPILER_ID}" MATCHES "GNU|Clang") + # GCC / Clang look for a precompiled header corresponding to the prefix header with the extension .gch appended + set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) + endif() + endif() + endif() +endfunction() + +function (cotire_select_unity_source_files _unityFile _sourcesVar) + set (_sourceFiles ${ARGN}) + if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") + set (_startIndex ${CMAKE_MATCH_1}) + set (_endIndex ${CMAKE_MATCH_2}) + list (LENGTH _sourceFiles _numberOfSources) + if (NOT _startIndex LESS _numberOfSources) + math (EXPR _startIndex "${_numberOfSources} - 1") + endif() + if (NOT _endIndex LESS _numberOfSources) + math (EXPR _endIndex "${_numberOfSources} - 1") + endif() + set (_files "") + foreach (_index RANGE ${_startIndex} ${_endIndex}) + list (GET _sourceFiles ${_index} _file) + list (APPEND _files "${_file}") + endforeach() + else() + set (_files ${_sourceFiles}) + endif() + set (${_sourcesVar} ${_files} PARENT_SCOPE) +endfunction() + +function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) + get_target_property(_targetSourceFiles ${_target} SOURCES) + set (_dependencySources "") + # depend on target's generated source files + cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) + if (_generatedSources) + # but omit all generated source files that have the COTIRE_EXCLUDED property set to true + cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) + if (_excludedGeneratedSources) + list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) + endif() + # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly + cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) + if (_excludedNonDependencySources) + list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) + endif() + if (_generatedSources) + list (APPEND _dependencySources ${_generatedSources}) + endif() + endif() + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_language} ${_target} unity source depends on ${_dependencySources}") + endif() + set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) +endfunction() + +function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) + get_target_property(_targetSourceFiles ${_target} SOURCES) + # depend on target source files marked with custom COTIRE_DEPENDENCY property + set (_dependencySources "") + cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles}) + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_language} ${_target} prefix header DEPENDS ${_dependencySources}") + endif() + set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) +endfunction() + +function (cotire_generate_target_script _language _configurations _target _targetScriptVar) + set (COTIRE_TARGET_SOURCES ${ARGN}) + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") + cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS) + cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS) + # set up variables to be configured + set (COTIRE_TARGET_LANGUAGE "${_language}") + cotire_determine_compiler_version("${COTIRE_TARGET_LANGUAGE}" COTIRE_${_language}_COMPILER) + get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) + cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) + get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) + cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) + get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) + get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) + get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) + cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${COTIRE_TARGET_SOURCES}) + cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${COTIRE_TARGET_SOURCES}) + set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") + foreach (_config ${_configurations}) + string (TOUPPER "${_config}" _upperConfig) + cotire_get_target_include_directories( + "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}) + cotire_get_target_compile_definitions( + "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) + cotire_get_target_compiler_flags( + "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) + cotire_get_source_files_compile_definitions( + "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${COTIRE_TARGET_SOURCES}) + endforeach() + get_cmake_property(_vars VARIABLES) + string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") + # remove COTIRE_VERBOSE which is passed as a CMake define on command line + list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) + set (_contents "") + foreach (_var IN LISTS _matchVars ITEMS + MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES + CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 + CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) + if (DEFINED ${_var}) + string (REPLACE "\"" "\\\"" _value "${${_var}}") + set (_contents "${_contents}set (${_var} \"${_value}\")\n") + endif() + endforeach() + cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) + set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) +endfunction() + +function (cotire_setup_pch_file_compilation _language _targetScript _prefixFile _pchFile) + set (_sourceFiles ${ARGN}) + if (MSVC) + # for Visual Studio, we attach the precompiled header compilation to the first source file + # the remaining files include the precompiled header, see cotire_setup_prefix_file_inclusion + if (_sourceFiles) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + list (GET _sourceFiles 0 _hostFile) + set (_flags "") + cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) + cotire_add_pch_compilation_flags( + "${_language}" "MSVC" "${COTIRE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) + set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") + # make first source file depend on prefix header + set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") + endif() + elseif ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") + # for makefile based generator, we add a custom command to precompile the prefix header + if (_targetScript) + cotire_set_cmd_to_prologue(_cmds) + list (GET _sourceFiles 0 _hostFile) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") + file (RELATIVE_PATH _pchFileRelPath "${CMAKE_BINARY_DIR}" "${_pchFile}") + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") + endif() + set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) + add_custom_command(OUTPUT "${_pchFile}" + COMMAND ${_cmds} + DEPENDS "${_prefixFile}" + IMPLICIT_DEPENDS ${_language} "${_prefixFile}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Building ${_language} precompiled header ${_pchFileRelPath}" VERBATIM) + endif() + endif() +endfunction() + +function (cotire_setup_prefix_file_inclusion _language _target _wholeTarget _prefixFile _pchFile) + set (_sourceFiles ${ARGN}) + if (MSVC) + # for Visual Studio, we include the precompiled header in all but the first source file + # the first source file does the precompiled header compilation, see cotire_setup_pch_file_compilation + list (LENGTH _sourceFiles _numberOfSourceFiles) + if (_numberOfSourceFiles GREATER 1) + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + list (REMOVE_AT _sourceFiles 0) + set (_flags "") + cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) + cotire_add_pch_inclusion_flags( + "${_language}" "MSVC" "${COTIRE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + # make source files depend on precompiled header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") + endif() + elseif ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") + if (NOT _wholeTarget) + # for makefile based generator, we force the inclusion of the prefix header for a subset + # of the source files, if this is a multi-language target or has excluded files + set (_flags "") + cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) + cotire_add_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${COTIRE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + endif() + # make source files depend on precompiled header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") + endif() +endfunction() + +function (cotire_get_first_set_property_value _propertyValueVar _type _object) + set (_properties ${ARGN}) + foreach (_property ${_properties}) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (_propertyValue) + set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) + return() + endif() + endforeach() + set (${_propertyValueVar} "" PARENT_SCOPE) +endfunction() + +function (cotire_setup_target_pch_usage _languages _target _wholeTarget) + if (MSVC) + # for Visual Studio, precompiled header inclusion is always done on the source file level + # see cotire_setup_prefix_file_inclusion + elseif (XCODE) + # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers + # if necessary, we also generate a single prefix header which includes all language specific prefix headers + set (_prefixFiles "") + foreach (_language ${_languages}) + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + if (_prefixFile) + list (APPEND _prefixFiles "${_prefixFile}") + endif() + endforeach() + set (_cmds ${ARGN}) + list (LENGTH _prefixFiles _numberOfPrefixFiles) + if (_numberOfPrefixFiles GREATER 1) + cotire_make_prefix_file_path("" ${_target} _prefixHeader) + cotire_setup_combine_command(${_target} "${_prefixHeader}" "${_prefixFiles}" _cmds) + else() + set (_prefixHeader "${_prefixFiles}") + endif() + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") + endif() + add_custom_command(TARGET "${_target}" + PRE_BUILD ${_cmds} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Updating target ${_target} prefix headers" VERBATIM) + # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ + set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") + set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") + elseif ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") + if (_wholeTarget) + # for makefile based generator, we force inclusion of the prefix header for all target source files + # if this is a single-language target without any excluded files + set (_language "${_languages}") + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) + set (_flags "") + cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) + cotire_add_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${COTIRE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (TARGET ${_target} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + endif() + endif() +endfunction() + +function (cotire_setup_unity_generation_commands _language _target _targetScript _unityFiles _cmdsVar) + set (_dependencySources "") + cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) + foreach (_unityFile ${_unityFiles}) + file (RELATIVE_PATH _unityFileRelPath "${CMAKE_BINARY_DIR}" "${_unityFile}") + set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) + cotire_set_cmd_to_prologue(_unityCmd) + list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetScript}" "${_unityFile}") + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_targetScript} ${_dependencySources}") + endif() + add_custom_command( + OUTPUT "${_unityFile}" + COMMAND ${_unityCmd} + DEPENDS "${_targetScript}" ${_dependencySources} + COMMENT "Generating ${_language} unity source ${_unityFileRelPath}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) + endforeach() + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) + set (_sourceFiles ${ARGN}) + list (LENGTH _unityFiles _numberOfUnityFiles) + if (_numberOfUnityFiles GREATER 1) + # create a joint unity file from all unity file segments + cotire_make_untiy_source_file_paths(${_language} ${_target} 0 _unityFile ${_unityFiles}) + cotire_setup_combine_command(${_target} "${_unityFile}" "${_unityFiles}" ${_cmdsVar}) + else() + set (_unityFile "${_unityFiles}") + endif() + file (RELATIVE_PATH _prefixFileRelPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") + set (_dependencySources "") + cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) + cotire_set_cmd_to_prologue(_prefixCmd) + list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" "${_unityFile}") + set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_targetScript} ${_unityFile} ${_dependencySources}") + endif() + add_custom_command( + OUTPUT "${_prefixFile}" + COMMAND ${_prefixCmd} + DEPENDS "${_targetScript}" "${_unityFile}" ${_dependencySources} + COMMENT "Generating ${_language} prefix header ${_prefixFileRelPath}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_combine_command _target _joinedFile _files _cmdsVar) + file (RELATIVE_PATH _joinedFileRelPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") + set (_filesRelPaths "") + foreach (_file ${_files}) + file (RELATIVE_PATH _fileRelPath "${CMAKE_BINARY_DIR}" "${_file}") + list (APPEND _filesRelPaths "${_fileRelPath}") + endforeach() + cotire_set_cmd_to_prologue(_prefixCmd) + list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine" "${_joinedFile}" ${_filesRelPaths}) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") + endif() + set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) + add_custom_command( + OUTPUT "${_joinedFile}" + COMMAND ${_prefixCmd} + DEPENDS ${_files} + COMMENT "Generating ${_joinedFileRelPath}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_init_cotire_target_properties _target) + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") + cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") + if (NOT _isRelative) + set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") + endif() + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) + if (NOT _isSet) + if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") + else() + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") + endif() + endif() +endfunction() + +function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + string (REPLACE ";" " " _languagesStr "${_languages}") + string (REPLACE ";" ", " _excludedStr "${ARGN}") + set (_targetMsg "") + if (NOT _languages) + set (_targetMsg "Target ${_target} cannot be cotired.") + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetUsePCH AND NOT _targetAddSCU) + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetUsePCH) + if (_allExcludedSourceFiles) + set (_targetMsg "${_languagesStr} target ${_target} cotired excluding files ${_excludedStr} without precompiled header.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") + endif() + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetAddSCU) + if (_allExcludedSourceFiles) + set (_targetMsg "${_languagesStr} target ${_target} cotired excluding files ${_excludedStr} without unity build.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") + endif() + else() + if (_allExcludedSourceFiles) + set (_targetMsg "${_languagesStr} target ${_target} cotired excluding files ${_excludedStr}.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired.") + endif() + endif() + set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) +endfunction() + +function (cotire_choose_target_languages _target _targetLanguagesVar) + set (_languages ${ARGN}) + set (_allSourceFiles "") + set (_allExcludedSourceFiles "") + set (_allCotiredSourceFiles "") + set (_targetLanguages "") + get_target_property(_targetType ${_target} TYPE) + get_target_property(_targetSourceFiles ${_target} SOURCES) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + set (_disableMsg "") + foreach (_language ${_languages}) + get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) + get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) + if (_prefixHeader OR _unityBuildFile) + message (WARNING "Target ${_target} has already been cotired.") + set (${_targetLanguagesVar} "" PARENT_SCOPE) + return() + endif() + if (_targetUsePCH AND "${_language}" STREQUAL "C" OR "${_language}" STREQUAL "CXX") + cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg) + if (_disableMsg) + set (_targetUsePCH FALSE) + endif() + endif() + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (_sourceFiles OR _excludedSources OR _cotiredSources) + list (APPEND _targetLanguages ${_language}) + endif() + if (_sourceFiles) + list (APPEND _allSourceFiles ${_sourceFiles}) + endif() + if (_excludedSources) + list (APPEND _allExcludedSourceFiles ${_excludedSources}) + endif() + if (_cotiredSources) + list (APPEND _allCotiredSourceFiles ${_cotiredSources}) + endif() + endforeach() + set (_targetMsgLevel STATUS) + if (NOT _targetLanguages) + string (REPLACE ";" " or " _languagesStr "${_languages}") + set (_disableMsg "No ${_languagesStr} source files.") + set (_targetUsePCH FALSE) + set (_targetAddSCU FALSE) + endif() + if (_targetUsePCH) + list (LENGTH _allSourceFiles _numberOfSources) + if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) + set (_disableMsg "Too few applicable sources.") + set (_targetUsePCH FALSE) + elseif (_allCotiredSourceFiles) + cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) + list (REMOVE_DUPLICATES _cotireTargets) + string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") + set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") + set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") + set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") + set (_targetMsgLevel SEND_ERROR) + set (_targetUsePCH FALSE) + elseif (XCODE AND _allExcludedSourceFiles) + # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target + set (_disableMsg "Exclusion of source files not supported for generator Xcode.") + set (_targetUsePCH FALSE) + elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") + # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target + set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") + set (_targetUsePCH FALSE) + endif() + endif() + set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) + cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) + if (_targetMsg) + if (NOT DEFINED COTIREMSG_${_target}) + set (COTIREMSG_${_target} "") + endif() + if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR + NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") + # cache message to avoid redundant messages on re-configure + set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") + message (${_targetMsgLevel} "${_targetMsg}") + endif() + endif() + set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) +endfunction() + +function (cotire_process_target_language _language _configurations _target _wholeTargetVar _cmdsVar) + set (${_cmdsVar} "" PARENT_SCOPE) + get_target_property(_targetSourceFiles ${_target} SOURCES) + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (NOT _sourceFiles) + return() + endif() + get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) + if (NOT _maxIncludes) + set (_maxIncludes 0) + endif() + cotire_make_untiy_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_sourceFiles} ${_cotiredSources}) + if (NOT _unityFiles) + return() + endif() + set (_wholeTarget ${${_wholeTargetVar}}) + cotire_generate_target_script( + ${_language} "${_configurations}" ${_target} _targetScript ${_sourceFiles}) + set (_cmds "") + cotire_setup_unity_generation_commands( + ${_language} ${_target} "${_targetScript}" "${_unityFiles}" _cmds ${_sourceFiles} ${_cotiredSources}) + cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) + if (_prefixFile) + cotire_setup_prefix_generation_command( + ${_language} ${_target} "${_targetScript}" "${_prefixFile}" "${_unityFiles}" _cmds ${_sourceFiles} ${_cotiredSources}) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + if (_targetUsePCH) + cotire_make_pch_file_path(${_language} ${_target} _pchFile) + if (_pchFile) + cotire_setup_pch_file_compilation( + ${_language} "${_targetScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) + if (_excludedSources) + set (_wholeTarget FALSE) + endif() + cotire_setup_prefix_file_inclusion( + ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) + endif() + endif() + endif() + # mark target as cotired for language + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") + if (_prefixFile) + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") + if (_targetUsePCH AND _pchFile) + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") + endif() + endif() + set (${_wholeTargetVar} ${_wholeTarget} PARENT_SCOPE) + set (${_cmdsVar} ${_cmds} PARENT_SCOPE) +endfunction() + +function (cotire_setup_clean_target _target) + set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") + if (NOT TARGET "${_cleanTargetName}") + cotire_set_cmd_to_prologue(_cmds) + get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") + add_custom_target(${_cleanTargetName} COMMAND ${_cmds} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMENT "Cleaning up target ${_target} cotire generated files" VERBATIM) + cotire_init_target("${_cleanTargetName}") + endif() +endfunction() + +function (cotire_setup_pch_target _languages _configurations _target) + if ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") + # for makefile based generators, we add a custom target to trigger the generation of the cotire related files + set (_dependsFiles "") + foreach (_language ${_languages}) + set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) + if (NOT MSVC) + # Visual Studio only creates precompiled header as a side effect + list(INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) + endif() + cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) + if (_dependsFile) + list (APPEND _dependsFiles "${_dependsFile}") + endif() + endforeach() + if (_dependsFiles) + set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") + add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) + cotire_init_target("${_pchTargetName}") + cotire_add_to_pch_all_target(${_pchTargetName}) + endif() + endif() +endfunction() + +function (cotire_setup_unity_build_target _languages _configurations _target) + set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") + # determine unity target sub type + get_target_property(_targetType ${_target} TYPE) + if ("${_targetType}" STREQUAL "EXECUTABLE") + get_target_property(_isWin32 ${_target} WIN32_EXECUTABLE) + get_target_property(_isMacOSX_Bundle ${_target} MACOSX_BUNDLE) + if (_isWin32) + set (_unityTargetSubType WIN32) + elseif (_isMacOSX_Bundle) + set (_unityTargetSubType MACOSX_BUNDLE) + else() + set (_unityTargetSubType "") + endif() + elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") + set (_unityTargetSubType "${CMAKE_MATCH_1}") + else() + message (WARNING "Unknown target type ${_targetType}.") + return() + endif() + # determine unity target sources + get_target_property(_targetSourceFiles ${_target} SOURCES) + set (_unityTargetSources ${_targetSourceFiles}) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + foreach (_language ${_languages}) + get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) + if (_unityFiles) + # remove source files that are included in the unity source + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (_sourceFiles OR _cotiredSources) + list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) + endif() + # then add unity source file instead + list (APPEND _unityTargetSources ${_unityFiles}) + # make unity files use precompiled header if there are multiple unity files + list (LENGTH _unityFiles _numberOfUnityFiles) + if (_targetUsePCH AND _numberOfUnityFiles GREATER ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) + if (_prefixFile AND _pchFile) + cotire_setup_pch_file_compilation( + ${_language} "" "${_prefixFile}" "${_pchFile}" ${_unityFiles}) + cotire_setup_prefix_file_inclusion( + ${_language} ${_target} FALSE "${_prefixFile}" "${_pchFile}" ${_unityFiles}) + # add the prefix header to unity target sources + list (APPEND _unityTargetSources "${_prefixFile}") + endif() + endif() + endif() + endforeach() + if (COTIRE_DEBUG) + message (STATUS "add ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") + endif() + # generate unity target + if ("${_targetType}" STREQUAL "EXECUTABLE") + add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) + else() + add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) + endif() + set (_outputDirProperties + ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ + LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ + RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) + # copy output location properties + if (COTIRE_UNITY_OUTPUT_DIRECTORY) + set (_setDefaultOutputDir TRUE) + if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") + set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") + else() + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) + cotrie_resolve_config_properites("${_configurations}" _properties ${_outputDirProperties}) + foreach (_property ${_properties}) + get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) + if (_outputDir) + get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) + set_property(TARGET ${_target} PROPERTY ${_property} "${_outputDir}") + set (_setDefaultOutputDir FALSE) + endif() + endforeach() + if (_setDefaultOutputDir) + get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) + endif() + endif() + if (_setDefaultOutputDir) + set_target_properties(${_unityTargetName} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" + LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" + RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") + endif() + else() + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) + endif() + # copy output name + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ + LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ + OUTPUT_NAME OUTPUT_NAME_ + RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ + PREFIX _POSTFIX SUFFIX) + # copy compile stuff + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ + COMPILE_FLAGS Fortran_FORMAT + INCLUDE_DIRECTORIES + INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_) + # copy link stuff + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + BUILD_WITH_INSTALL_RPATH INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH + LINKER_LANGUAGE LINK_DEPENDS + LINK_FLAGS LINK_FLAGS_ + LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ + LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ + LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC + STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ + SOVERSION VERSION) + # copy Qt stuff + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + AUTOMOC AUTOMOC_MOC_OPTIONS) + # copy cmake stuff + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) + # copy platform stuff + if (APPLE) + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + BUNDLE BUNDLE_EXTENSION FRAMEWORK INSTALL_NAME_DIR MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST + OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE) + elseif (WIN32) + cotrie_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + GNUtoMS + VS_DOTNET_REFERENCES VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_KEYWORD + VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER + VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES) + endif() + # use output name from original target + get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) + if (NOT _targetOutputName) + set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") + endif() + # use export symbol from original target + cotire_get_target_export_symbol("${_target}" _defineSymbol) + if (_defineSymbol) + set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") + if ("${_targetType}" STREQUAL "EXECUTABLE") + set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) + endif() + endif() + cotire_init_target(${_unityTargetName}) + cotire_add_to_unity_all_target(${_unityTargetName}) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") +endfunction() + +function (cotire_target _target) + set(_options "") + set(_oneValueArgs "") + set(_multiValueArgs LANGUAGES CONFIGURATIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_LANGUAGES) + get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + endif() + if (NOT _option_CONFIGURATIONS) + if (CMAKE_CONFIGURATION_TYPES) + set (_option_CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES}) + elseif (CMAKE_BUILD_TYPE) + set (_option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}") + else() + set (_option_CONFIGURATIONS "None") + endif() + endif() + # trivial checks + get_target_property(_imported ${_target} IMPORTED) + if (_imported) + message (WARNING "Imported target ${_target} cannot be cotired") + return() + endif() + # check if target needs to be cotired for build type + # when using configuration types, the test is performed at build time + cotire_init_cotire_target_properties(${_target}) + if (NOT CMAKE_CONFIGURATION_TYPES) + if (CMAKE_BUILD_TYPE) + list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) + else() + list (FIND _option_CONFIGURATIONS "None" _index) + endif() + if (_index EQUAL -1) + if (COTIRE_DEBUG) + message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") + endif() + return() + endif() + endif() + # choose languages that apply to the target + cotire_choose_target_languages("${_target}" _targetLanguages ${_option_LANGUAGES}) + if (NOT _targetLanguages) + return() + endif() + list (LENGTH _targetLanguages _numberOfLanguages) + if (_numberOfLanguages GREATER 1) + set (_wholeTarget FALSE) + else() + set (_wholeTarget TRUE) + endif() + set (_cmds "") + foreach (_language ${_targetLanguages}) + cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} _wholeTarget _cmd) + if (_cmd) + list (APPEND _cmds ${_cmd}) + endif() + endforeach() + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + if (_targetAddSCU) + cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) + endif() + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + if (_targetUsePCH) + cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds}) + cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) + endif() + get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) + if (_targetAddCleanTarget) + cotire_setup_clean_target(${_target}) + endif() +endfunction() + +function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) + if (_targetName) + file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") + else() + file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") + endif() + # filter files in intermediate directory + set (_filesToRemove "") + foreach (_file ${_cotireFiles}) + get_filename_component(_dir "${_file}" PATH) + get_filename_component(_dirName "${_dir}" NAME) + if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") + list (APPEND _filesToRemove "${_file}") + endif() + endforeach() + if (_filesToRemove) + if (COTIRE_VERBOSE) + message (STATUS "removing ${_filesToRemove}") + endif() + file (REMOVE ${_filesToRemove}) + endif() +endfunction() + +function (cotire_init_target _targetName) + if (COTIRE_TARGETS_FOLDER) + set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") + endif() + if (MSVC_IDE) + set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) + endif() +endfunction() + +function (cotire_add_to_pch_all_target _pchTargetName) + set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + add_custom_target("${_targetName}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" VERBATIM) + cotire_init_target("${_targetName}") + endif() + cotire_setup_clean_all_target() + add_dependencies(${_targetName} ${_pchTargetName}) +endfunction() + +function (cotire_add_to_unity_all_target _unityTargetName) + set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + add_custom_target("${_targetName}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" VERBATIM) + cotire_init_target("${_targetName}") + endif() + cotire_setup_clean_all_target() + add_dependencies(${_targetName} ${_unityTargetName}) +endfunction() + +function (cotire_setup_clean_all_target) + set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + cotire_set_cmd_to_prologue(_cmds) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") + add_custom_target(${_targetName} COMMAND ${_cmds} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" COMMENT "Cleaning up all cotire generated files" VERBATIM) + cotire_init_target("${_targetName}") + endif() +endfunction() + +function (cotire) + set(_options "") + set(_oneValueArgs "") + set(_multiValueArgs LANGUAGES CONFIGURATIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + set (_targets ${_option_UNPARSED_ARGUMENTS}) + foreach (_target ${_targets}) + if (TARGET ${_target}) + cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS}) + else() + message (WARNING "${_target} is not a target") + endif() + endforeach() +endfunction() + +if (CMAKE_SCRIPT_MODE_FILE) + + # cotire is being run in script mode + # locate -P on command args + set (COTIRE_ARGC -1) + foreach (_index RANGE ${CMAKE_ARGC}) + if (COTIRE_ARGC GREATER -1) + set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") + math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") + elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") + set (COTIRE_ARGC 0) + endif() + endforeach() + + if (COTIRE_DEBUG) + message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") + endif() + + # include target script if available + if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") + include("${COTIRE_ARGV2}") + endif() + + if (WIN32) + # for MSVC, compiler IDs may not always be set correctly + if (MSVC) + set (CMAKE_C_COMPILER_ID "MSVC") + set (CMAKE_CXX_COMPILER_ID "MSVC") + endif() + endif() + + if (NOT COTIRE_BUILD_TYPE) + set (COTIRE_BUILD_TYPE "None") + endif() + string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) + set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) + set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) + set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) + # check if target has been cotired for actual build type COTIRE_BUILD_TYPE + list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) + if (_index GREATER -1) + set (_sources ${COTIRE_TARGET_SOURCES}) + set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) + else() + if (COTIRE_DEBUG) + message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") + endif() + set (_sources "") + set (_sourcesDefinitions "") + endif() + set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) + set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) + set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) + set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) + + if ("${COTIRE_ARGV1}" STREQUAL "unity") + + cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) + cotire_generate_unity_source( + "${COTIRE_ARGV3}" ${_sources} + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + DEPENDS "${COTIRE_ARGV0}" "${COTIRE_ARGV2}" ${COTIRE_TARGET_UNITY_DEPENDS} + SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} + PRE_UNDEFS ${_targetPreUndefs} + POST_UNDEFS ${_targetPostUndefs} + SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} + SOURCES_POST_UNDEFS ${_sourcesPostUndefs}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") + + set (_files "") + foreach (_index RANGE 4 ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + cotire_generate_prefix_header( + "${COTIRE_ARGV3}" ${_files} + COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" + COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} + COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" + COMPILER_VERSION "${COTIRE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + DEPENDS "${COTIRE_ARGV0}" "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS} + IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" + INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH} + IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" + INCLUDE_DIRECTORIES ${_includeDirs} + COMPILE_DEFINITIONS ${_compileDefinitions} + COMPILE_FLAGS ${_compileFlags}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") + + set (_files "") + foreach (_index RANGE 5 ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + cotire_precompile_prefix_header( + "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" + COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" + COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} + COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" + COMPILER_VERSION "${COTIRE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + INCLUDE_DIRECTORIES ${_includeDirs} + COMPILE_DEFINITIONS ${_compileDefinitions} + COMPILE_FLAGS ${_compileFlags}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "combine") + + set (_files "") + foreach (_index RANGE 2 ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + cotire_generate_unity_source(${_files}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") + + cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") + + else() + message (FATAL_ERROR "Unknown cotire command \"${COTIRE_ARGV1}\".") + endif() + +else() + + # cotire is being run in include mode + # set up all variable and property definitions + + unset (COTIRE_C_COMPILER_VERSION CACHE) + unset (COTIRE_CXX_COMPILER_VERSION CACHE) + + if (NOT DEFINED COTIRE_DEBUG_INIT) + if (DEFINED COTIRE_DEBUG) + set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) + else() + set (COTIRE_DEBUG_INIT FALSE) + endif() + endif() + option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) + + if (NOT DEFINED COTIRE_VERBOSE_INIT) + if (DEFINED COTIRE_VERBOSE) + set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) + else() + set (COTIRE_VERBOSE_INIT FALSE) + endif() + endif() + option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) + + set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING + "Ignore headers with the listed file extensions from the generated prefix header.") + + set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING + "Ignore headers from these directories when generating the prefix header.") + + set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "3" CACHE STRING + "Minimum number of sources in target required to enable use of precompiled header.") + + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "" CACHE STRING + "Maximum number of source files to include in a single unity source file.") + + if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) + set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") + endif() + if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) + set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") + endif() + if (NOT COTIRE_INTDIR) + set (COTIRE_INTDIR "cotire") + endif() + if (NOT COTIRE_PCH_ALL_TARGET_NAME) + set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") + endif() + if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) + set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") + endif() + if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) + set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") + endif() + if (NOT COTIRE_CLEAN_TARGET_SUFFIX) + set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") + endif() + if (NOT COTIRE_PCH_TARGET_SUFFIX) + set (COTIRE_PCH_TARGET_SUFFIX "_pch") + endif() + if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) + set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") + endif() + if (NOT DEFINED COTIRE_TARGETS_FOLDER) + set (COTIRE_TARGETS_FOLDER "cotire") + endif() + if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) + if ("${CMAKE_GENERATOR}" MATCHES "Ninja") + # generated Ninja build files do not work if the unity target produces the same output file as the cotired target + set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") + else() + set (COTIRE_UNITY_OUTPUT_DIRECTORY "") + endif() + endif() + + # define cotire cache variables + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "The variable can be set to a semicolon separated list of include directories." + "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." + "If not defined, defaults to empty list." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" + BRIEF_DOCS "Ignore includes with the listed file extensions from the prefix header when generating the prefix header." + FULL_DOCS + "The variable can be set to a semicolon separated list of file extensions." + "If a header file extension matches one in the list, it will be excluded from the generated prefix header." + "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." + "If not defined, defaults to inc;inl;ipp." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" + BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." + FULL_DOCS + "The variable can be set to an integer > 0." + "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." + "If not defined, defaults to 3." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "This may be set to an integer > 0." + "If a target contains more than that number of source files, cotire will create multiple unity source files for it." + "If not set, cotire will only create a single unity source file." + "Is use to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." + "Defaults to empty." + ) + + # define cotire directory properties + + define_property( + DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" + BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." + FULL_DOCS + "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" + BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." + FULL_DOCS + "See target property COTIRE_ADD_UNITY_BUILD." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" + BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." + FULL_DOCS + "See target property COTIRE_ADD_CLEAN." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" + BRIEF_DOCS "Honor headers from these directories when generating the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." + ) + + # define cotire target properties + + define_property( + TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED + BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." + FULL_DOCS + "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." + "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." + "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." + "The target name will be set to this target's name with the suffix _pch appended." + "Inherited from directory." + "Defaults to TRUE." + ) + + define_property( + TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED + BRIEF_DOCS "Add a new target that performs a unity build for this target." + FULL_DOCS + "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." + "Most of the relevant target properties will be copied from this target to the new unity build target." + "Target dependencies and linked libraries have to be manually set up for the new unity build target." + "The unity target name will be set to this target's name with the suffix _unity appended." + "Inherited from directory." + "Defaults to TRUE." + ) + + define_property( + TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED + BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." + FULL_DOCS + "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." + "The clean target name will be set to this target's name with the suffix _clean_cotire appended." + "Inherited from directory." + "Defaults to FALSE." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." + "Inherited from directory." + "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED + BRIEF_DOCS "Honor headers from these directories when generating the prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." + "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," + "the option which yields the closer relative path match wins." + "Inherited from directory." + "If not set, this property is initialized to the empty list." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file before each target source file." + "Inherited from directory." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file after each target source file." + "Inherited from directory." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "This may be set to an integer > 0." + "If a target contains more than that number of source files, cotire will create multiple unity build files for it." + "If not set, cotire will only create a single unity source file." + "Inherited from directory." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE__UNITY_SOURCE" + BRIEF_DOCS "Read-only property. The generated unity source file(s)." + FULL_DOCS + "cotire sets this property to the path of the generated single computation unit source file for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE__PREFIX_HEADER" + BRIEF_DOCS "Read-only property. The generated prefix header file." + FULL_DOCS + "cotire sets this property to the full path of the generated language prefix header for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" + BRIEF_DOCS "Read-only property. The generated precompiled header file." + FULL_DOCS + "cotire sets this property to the full path of the generated language precompiled header binary for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" + BRIEF_DOCS "Read-only property. The name of the generated unity build target corresponding to this target." + FULL_DOCS + "cotire sets this property to the name the generated unity build target for this target." + "Defaults to empty string." + ) + + # define cotire source properties + + define_property( + SOURCE PROPERTY "COTIRE_EXCLUDED" + BRIEF_DOCS "Do not modify source file's build command." + FULL_DOCS + "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." + "The source file will also be excluded from the generated unity source file." + "Source files that have their COMPILE_FLAGS property set will be excluded by default." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_DEPENDENCY" + BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." + FULL_DOCS + "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." + "If the file is modified, cotire will re-generate the prefix header source upon build." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file before this file is included." + "Defaults to empty string." + ) + + define_property( + SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file after this file is included." + "Defaults to empty string." + ) + + define_property( + SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" + BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." + FULL_DOCS + "If this property is set to TRUE, cotire will complete the current unity file and start a new one." + "The new unity source file will include this source file as the first one." + "This property essentially works as a separator for unity source files." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_TARGET" + BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." + FULL_DOCS + "cotire sets this property to the name of target, that the source file's build command has been altered for." + "Defaults to empty string." + ) + +endif() diff --git a/include/BasicBlock.h b/include/BasicBlock.h index 3b82bf3..653fe46 100644 --- a/include/BasicBlock.h +++ b/include/BasicBlock.h @@ -117,7 +117,7 @@ public: void findBBExps(LOCAL_ID &locals, Function *f); bool valid() {return 0==(flg & INVALID_BB); } bool wasTraversedAtLevel(int l) const {return traversed==l;} - ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond); + ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond); void addOutEdge(uint32_t ip) // TODO: fix this { edges.push_back(TYPEADR_TYPE(ip)); diff --git a/include/Enums.h b/include/Enums.h index d8a2ddc..d7def3a 100644 --- a/include/Enums.h +++ b/include/Enums.h @@ -177,7 +177,7 @@ enum llIcode iPOP, iPOPA, iPOPF, - iPUSH, + iPUSH, // 77 iPUSHA, iPUSHF, iRCL, /* 80 */ diff --git a/include/Procedure.h b/include/Procedure.h index 3d61d7d..ff361ea 100644 --- a/include/Procedure.h +++ b/include/Procedure.h @@ -13,6 +13,7 @@ struct Expr; struct Disassembler; struct Function; struct CALL_GRAPH; +struct PROG; typedef llvm::iplist FunctionListType; typedef FunctionListType lFunction; @@ -189,6 +190,7 @@ public: void preprocessReturnDU(LivenessSet &_liveOut); Expr * adjustActArgType(Expr *_exp, hlType forType); std::string writeCall(Function *tproc, STKFRAME &args, int *numLoc); + void processDosInt(STATE *pstate, PROG &prog, bool done); protected: void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table); bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate); diff --git a/include/ast.h b/include/ast.h index acd4e6a..d745105 100644 --- a/include/ast.h +++ b/include/ast.h @@ -29,6 +29,7 @@ struct STKFRAME; struct LOCAL_ID; struct ICODE; struct LLInst; +struct LLOperand; struct ID; typedef std::list::iterator iICODE; typedef boost::iterator_range rICODE; @@ -291,6 +292,7 @@ struct RegisterNode : public AstIdent regiType = reg_type; regiIdx = idx; } + RegisterNode(const LLOperand &, LOCAL_ID *locsym); RegisterNode(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym); virtual Expr *clone() const diff --git a/include/dcc.h b/include/dcc.h index 7eb1b43..7ffbff8 100644 --- a/include/dcc.h +++ b/include/dcc.h @@ -22,22 +22,6 @@ #include "BasicBlock.h" class Project; /* CALL GRAPH NODE */ -struct CALL_GRAPH -{ - ilFunction proc; /* Pointer to procedure in pProcList */ - std::vector outEdges; /* array of out edges */ -public: - void write(); - CALL_GRAPH() : outEdges(0) - { - } -public: - void writeNodeCallGraph(int indIdx); - bool insertCallGraph(ilFunction caller, ilFunction callee); - bool insertCallGraph(Function *caller, ilFunction callee); - void insertArc(ilFunction newProc); -}; -//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */ extern bundle cCode; /* Output C procedure's declaration and code */ /**** Global variables ****/ @@ -121,8 +105,8 @@ bool LibCheck(Function &p); /* chklib.c */ boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction); /* Exported functions from hlicode.c */ -char *writeJcond (const HLTYPE &, Function *, int *); -char *writeJcondInv (HLTYPE, Function *, int *); +const char *writeJcond(const HLTYPE &, Function *, int *); +const char *writeJcondInv (HLTYPE, Function *, int *); /* Exported funcions from locident.c */ diff --git a/include/icode.h b/include/icode.h index 0de9d69..6d5d761 100644 --- a/include/icode.h +++ b/include/icode.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include "libdis.h" #include "Enums.h" @@ -252,16 +252,26 @@ struct LLOperand eReg regi; /* 0 < regs < INDEXBASE <= index modes */ int16_t off; /* memory address offset */ uint32_t opz; /* idx of immed src op */ + bool immed; + bool is_offset; // set by jumps + bool is_compound; + size_t width; //union {/* Source operand if (flg & I) */ struct { /* Call & # actual arg bytes */ Function *proc; /* pointer to target proc (for CALL(F))*/ int cb; /* # actual arg bytes */ } proc; - LLOperand() : seg(rUNDEF),segOver(rUNDEF),segValue(0),regi(rUNDEF),off(0),opz(0) + LLOperand() : seg(rUNDEF),segOver(rUNDEF),segValue(0),regi(rUNDEF),off(0), + opz(0),immed(0),is_offset(false),is_compound(0),width(0) { proc.proc=0; proc.cb=0; } + LLOperand(eReg r,size_t w) : LLOperand() + { + regi=r; + width=w; + } bool operator==(const LLOperand &with) const { return (seg==with.seg) && @@ -279,12 +289,12 @@ struct LLOperand } eReg getReg2() const {return regi;} bool isReg() const; - static LLOperand CreateImm2(int64_t Val) + static LLOperand CreateImm2(int64_t Val,uint8_t wdth=2) { LLOperand Op; - //Op.Kind = kImmediate; - //Op.ImmVal = Val; + Op.immed=true; Op.opz = Val; + Op.width = wdth; return Op; } static LLOperand CreateReg2(unsigned Val) @@ -298,6 +308,10 @@ struct LLOperand return not (*this == LLOperand()); } void addProcInformation(int param_count,uint32_t call_conv); + bool isImmediate() const { return immed;} + void setImmediate(bool x) { immed=x;} + bool compound() const {return is_compound;} // dx:ax pair + size_t byteWidth() const { assert(width<=4); return width;} }; struct LLInst : public llvm::MCInst //: public llvm::ilist_node { diff --git a/include/project.h b/include/project.h index 9e0fff9..15a7b5b 100644 --- a/include/project.h +++ b/include/project.h @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include #include "symtab.h" #include "BinaryImage.h" #include "Procedure.h" diff --git a/include/state.h b/include/state.h index ff0f99a..254f267 100644 --- a/include/state.h +++ b/include/state.h @@ -33,7 +33,7 @@ struct STATE void setMemoryByte(uint32_t addr,uint8_t val) { //TODO: make this into a full scale value tracking class ! - }; + } }; diff --git a/src/BasicBlock.cpp b/src/BasicBlock.cpp index dff3fb8..6d86a61 100644 --- a/src/BasicBlock.cpp +++ b/src/BasicBlock.cpp @@ -66,7 +66,7 @@ void BB::display() for (size_t i = 0; i < edges.size(); i++) { - if(edges[i].BBptr==0) + if(edges[i].BBptr==nullptr) printf(" outEdge[%2zd] = Unlinked out edge to %d\n",i, edges[i].ip); else printf(" outEdge[%2zd] = %d\n",i, edges[i].BBptr->begin()->loc_ip); @@ -132,7 +132,7 @@ void BB::displayDfs() \param indLevel indentation level - used for formatting. \param numLoc: last # assigned to local variables */ -ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond) +ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond) { latch = pProc->m_dfsLast[this->latchNode]; std::ostringstream ostr; @@ -192,8 +192,8 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, int follow; /* ifFollow */ BB * succ, *latch; /* Successor and latching node */ ICODE * picode; /* Pointer to HLI_JCOND instruction */ - char *l; /* Pointer to HLI_JCOND expression */ - boolT emptyThen, /* THEN clause is empty */ + std::string l; /* Pointer to HLI_JCOND expression */ + bool emptyThen, /* THEN clause is empty */ repCond; /* Repeat condition for while() */ /* Check if this basic block should be analysed */ @@ -206,7 +206,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, /* Check for start of loop */ repCond = false; - latch = NULL; + latch = nullptr; if (loopType) { picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond); @@ -303,13 +303,13 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, if (succ->dfsLastNum != follow) /* THEN part */ { l = writeJcond ( *back().hl(), pProc, numLoc); - cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l); + cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l.c_str()); succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow); } else /* empty THEN part => negate ELSE part */ { l = writeJcondInv ( *back().hl(), pProc, numLoc); - cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l); + cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l.c_str()); edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow); emptyThen = true; } @@ -345,7 +345,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, else /* no follow => if..then..else */ { l = writeJcond ( *back().hl(), pProc, numLoc); - cCode.appendCode( "%s%s", indentStr(indLevel-1), l); + cCode.appendCode( "%s%s", indentStr(indLevel-1), l.c_str()); edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow); cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1)); edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow); diff --git a/src/RegisterNode.cpp b/src/RegisterNode.cpp new file mode 100644 index 0000000..2cf9700 --- /dev/null +++ b/src/RegisterNode.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +//#include +//#include + +#include "types.h" +#include "ast.h" +#include "bundle.h" + +#include "machine_x86.h" +#include "project.h" +using namespace std; +using namespace boost::adaptors; +RegisterNode::RegisterNode(const LLOperand &op,LOCAL_ID *locsym) +{ + ident.type(REGISTER); + hlType type_sel; + regType reg_type; + if (op.byteWidth()==1) + { + type_sel = TYPE_BYTE_SIGN; + reg_type = BYTE_REG; + } + else /* uint16_t */ + { + type_sel = TYPE_WORD_SIGN; + reg_type = WORD_REG; + } + regiIdx = locsym->newByteWordReg(type_sel, op.regi); + regiType = reg_type; +} + +//RegisterNode::RegisterNode(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym) +//{ +// ident.type(REGISTER); +// hlType type_sel; +// regType reg_type; +// if ((icodeFlg & B) || (icodeFlg & SRC_B)) +// { +// type_sel = TYPE_BYTE_SIGN; +// reg_type = BYTE_REG; +// } +// else /* uint16_t */ +// { +// type_sel = TYPE_WORD_SIGN; +// reg_type = WORD_REG; +// } +// regiIdx = locsym->newByteWordReg(type_sel, regi); +// regiType = reg_type; +//} + +string RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const +{ + std::ostringstream codeOut; + + std::ostringstream o; + ID *id = &pProc->localId.id_arr[regiIdx]; + if (id->name[0] == '\0') /* no name */ + { + id->setLocalName(++(*numLoc)); + codeOut <type)<< " "<name<<"; "; + codeOut <<"/* "<id.regi)<<" */\n"; + } + if (id->hasMacro) + o << id->macro << "("<name<<")"; + else + o << id->name; + + cCode.appendDecl(codeOut.str()); + return o.str(); +} + +int RegisterNode::hlTypeSize(Function *) const +{ + if (regiType == BYTE_REG) + return (1); + else + return (2); +} + + + +hlType RegisterNode::expType(Function *pproc) const +{ + if (regiType == BYTE_REG) + return (TYPE_BYTE_SIGN); + else + return (TYPE_WORD_SIGN); +} + +Expr *RegisterNode::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym) +{ + eReg treeReg = locsym->id_arr[regiIdx].id.regi; + if (treeReg == regi) /* uint16_t reg */ + { + return _expr; + } + else if(Machine_X86::isSubRegisterOf(treeReg,regi)) /* uint16_t/uint8_t reg */ + { + return _expr; + } +} +bool RegisterNode::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId) +{ + uint8_t regi = locId.id_arr[regiIdx].id.regi; + range_to_check.advance_begin(1); + auto all_valid_and_high_level_after_start = range_to_check | filtered(ICODE::select_valid_high_level); + for (ICODE &i : all_valid_and_high_level_after_start) + if (i.du.def.testRegAndSubregs(regi)) + return false; + if (all_valid_and_high_level_after_start.end().base() != lastBBinst) + return true; + return false; +} diff --git a/src/ast.cpp b/src/ast.cpp index 9b6abcc..90ad961 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -298,7 +298,7 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_ int idx; /* idx into pIcode->localId table */ - const LLOperand &pm((sd == SRC) ? ll_insn.src() : ll_insn.m_dst); + const LLOperand &pm(*ll_insn.get(sd)); if ( ((sd == DST) && ll_insn.testFlags(IM_DST)) or ((sd == SRC) && ll_insn.testFlags(IM_SRC)) or @@ -312,7 +312,7 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_ else if ((sd == DST) && ll_insn.testFlags(IM_TMP_DST)) { /* implicit tmp */ - newExp = new RegisterNode(rTMP, 0, &pProc->localId); + newExp = new RegisterNode(LLOperand(rTMP,2), &pProc->localId); duIcode.setRegDU(rTMP, (operDu)eUSE); } @@ -322,7 +322,8 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_ newExp = new GlobalVariable(pm.segValue, pm.off); else if ( pm.isReg() ) /* register */ { - newExp = new RegisterNode(pm.regi, (sd == SRC) ? ll_insn.getFlag() : ll_insn.getFlag() & NO_SRC_B, &pProc->localId); + //(sd == SRC) ? ll_insn.getFlag() : ll_insn.getFlag() & NO_SRC_B + newExp = new RegisterNode(pm, &pProc->localId); duIcode.setRegDU( pm.regi, du); } @@ -359,10 +360,11 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_ case INDEX_BP: selected = rBP; break; case INDEX_BX: selected = rBX; break; default: - newExp = 0; + newExp = nullptr; assert(false); } - newExp = new RegisterNode(selected, 0, &pProc->localId); + //NOTICE: was selected, 0 + newExp = new RegisterNode(LLOperand(selected, 0), &pProc->localId); duIcode.setRegDU( selected, du); newExp = UnaryOperator::Create(DEREFERENCE, newExp); } @@ -402,7 +404,7 @@ int hlSize[] = {2, 1, 1, 2, 2, 4, 4, 4, 2, 2, 1, 4, 4}; int Expr::hlTypeSize(Function * pproc) const { - if (this == NULL) + if (this == nullptr) return (2); /* for TYPE_UNKNOWN */ fprintf(stderr,"hlTypeSize queried for Unkown type %d \n",m_type); return 2; // CC: is this correct? @@ -710,7 +712,7 @@ bool Expr::insertSubTreeReg (AstIdent *&tree, Expr *_expr, eReg regi,const LOCAL bool Expr::insertSubTreeReg (Expr *&tree, Expr *_expr, eReg regi,const LOCAL_ID *locsym) { - if (tree == NULL) + if (tree == nullptr) return false; Expr *temp=tree->insertSubTreeReg(_expr,regi,locsym); if(nullptr!=temp) @@ -775,7 +777,7 @@ Expr *AstIdent::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym) * long register index longIdx*/ bool Expr::insertSubTreeLongReg(Expr *_expr, Expr *&tree, int longIdx) { - if (tree == NULL) + if (tree == nullptr) return false; Expr *temp=tree->insertSubTreeLongReg(_expr,longIdx); if(nullptr!=temp) diff --git a/src/backend.cpp b/src/backend.cpp index 315e409..03c5d52 100644 --- a/src/backend.cpp +++ b/src/backend.cpp @@ -10,14 +10,15 @@ #include #include -#include "dcc.h" -#include "disassem.h" #include #include #include #include #include +#include "dcc.h" +#include "disassem.h" #include "project.h" +#include "CallGraph.h" using namespace boost; using namespace boost::adaptors; bundle cCode; /* Procedure declaration and code */ @@ -318,9 +319,9 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios) pcallGraph->proc->flg |= PROC_OUTPUT; /* Dfs if this procedure has any successors */ - for (size_t i = 0; i < pcallGraph->outEdges.size(); i++) + for (auto & elem : pcallGraph->outEdges) { - backBackEnd (pcallGraph->outEdges[i], _ios); + backBackEnd (elem, _ios); } /* Generate code for this procedure */ diff --git a/src/chklib.cpp b/src/chklib.cpp index 361b409..766b266 100644 --- a/src/chklib.cpp +++ b/src/chklib.cpp @@ -56,7 +56,7 @@ static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */ static uint16_t *g; /* g[] */ static HT *ht; /* The hash table */ static PH_FUNC_STRUCT *pFunc; /* Points to the array of func names */ -static hlType *pArg=0; /* Points to the array of param types */ +static hlType *pArg=nullptr; /* Points to the array of param types */ static int numFunc; /* Number of func names actually stored */ static int numArg; /* Number of param names actually stored */ #define DCCLIBS "dcclibs.dat" /* Name of the prototypes data file */ @@ -302,7 +302,7 @@ void SetupLibCheck(void) uint16_t w, len; int i; - if ((g_file = fopen(sSigName, "rb")) == NULL) + if ((g_file = fopen(sSigName, "rb")) == nullptr) { printf("Warning: cannot open signature file %s\n", sSigName); return; @@ -392,7 +392,7 @@ void SetupLibCheck(void) /* This is now the hash table */ /* First allocate space for the table */ ht = new HT[numKeys]; - if ( 0 == ht) + if ( nullptr == ht) { printf("Could not allocate hash table\n"); exit(1); @@ -446,7 +446,7 @@ bool LibCheck(Function & pProc) if (prog.bSigs == false) { /* No signatures... can't rely on hash parameters to be initialised - so always return false */ + so always return false */ return false; } @@ -457,6 +457,8 @@ bool LibCheck(Function & pProc) pProc.name = "main"; return false; } + if(fileOffset + PATLEN > prog.cbImage) + return false; memcpy(pat, &prog.image()[fileOffset], PATLEN); //memmove(pat, &prog.image()[fileOffset], PATLEN); fixWildCards(pat); /* Fix wild cards in the copy */ @@ -888,7 +890,7 @@ void readProtoFile(void) } strcat(szProFName, DCCLIBS); - if ((fProto = fopen(szProFName, "rb")) == NULL) + if ((fProto = fopen(szProFName, "rb")) == nullptr) { printf("Warning: cannot open library prototype data file %s\n", szProFName); return; diff --git a/src/control.cpp b/src/control.cpp index 329bfba..749ff92 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -276,13 +276,13 @@ void Function::structLoops(derSeq *derivedG) /* Structure loops */ /* for all derived sequences Gi */ - for(derSeq::iterator iter=derivedG->begin(); iter!=derivedG->end(); ++iter) + for(auto & elem : *derivedG) { level++; - Ii = iter->Ii; + Ii = elem.Ii; while (Ii) /* for all intervals Ii of Gi */ { - latchNode = NULL; + latchNode = nullptr; intNodes.clear(); /* Find interval head (original BB node in G1) and create diff --git a/src/dataflow.cpp b/src/dataflow.cpp index 853e125..fa18f6f 100644 --- a/src/dataflow.cpp +++ b/src/dataflow.cpp @@ -93,11 +93,11 @@ size_t STKFRAME::getLocVar(int off) /* Returns a string with the source operand of Icode */ static Expr *srcIdent (const LLInst &ll_insn, Function * pProc, iICODE i, ICODE & duIcode, operDu du) { - if (ll_insn.testFlags(I)) /* immediate operand */ + const LLOperand * src_op = ll_insn.get(SRC); + if (src_op->isImmediate()) /* immediate operand ll_insn.testFlags(I)*/ { - if (ll_insn.testFlags(B)) - return new Constant(ll_insn.src().getImm2(), 1); - return new Constant(ll_insn.src().getImm2(), 2); + //if (ll_insn.testFlags(B)) + return new Constant(src_op->getImm2(), src_op->byteWidth()); } // otherwise return AstIdent::id (ll_insn, SRC, pProc, i, duIcode, du); @@ -148,6 +148,8 @@ void Function::elimCondCodes () if ((use & def) != use) continue; notSup = false; + LLOperand *dest_ll = defAt->ll()->get(DST); + LLOperand *src_ll = defAt->ll()->get(SRC); if ((useAtOp >= iJB) && (useAtOp <= iJNS)) { iICODE befDefAt = (++riICODE(defAt)).base(); @@ -161,29 +163,22 @@ void Function::elimCondCodes () case iOR: lhs = defAt->hl()->asgn.lhs()->clone(); useAt->copyDU(*defAt, eUSE, eDEF); - if (defAt->ll()->testFlags(B)) - rhs = new Constant(0, 1); - else - rhs = new Constant(0, 2); + //if (defAt->ll()->testFlags(B)) + rhs = new Constant(0, dest_ll->byteWidth()); break; case iTEST: rhs = srcIdent (*defAt->ll(),this, befDefAt,*useAt, eUSE); lhs = dstIdent (*defAt->ll(),this, befDefAt,*useAt, eUSE); lhs = BinaryOperator::And(lhs, rhs); - if (defAt->ll()->testFlags(B)) - rhs = new Constant(0, 1); - else - rhs = new Constant(0, 2); +// if (defAt->ll()->testFlags(B)) + rhs = new Constant(0, dest_ll->byteWidth()); break; case iINC: case iDEC: //WARNING: verbatim copy from iOR needs fixing ? lhs = defAt->hl()->asgn.lhs()->clone(); useAt->copyDU(*defAt, eUSE, eDEF); - if (defAt->ll()->testFlags(B)) - rhs = new Constant(0, 1); - else - rhs = new Constant(0, 2); + rhs = new Constant(0, dest_ll->byteWidth()); break; default: notSup = true; @@ -202,7 +197,8 @@ void Function::elimCondCodes () else if (useAtOp == iJCXZ) { - lhs = new RegisterNode(rCX, 0, &localId); + //NOTICE: was rCX, 0 + lhs = new RegisterNode(LLOperand(rCX, 0 ), &localId); useAt->setRegDU (rCX, eUSE); rhs = new Constant(0, 2); _expr = BinaryOperator::Create(EQUAL,lhs,rhs); @@ -514,7 +510,7 @@ void BB::genDU1() /* Process each register definition of a HIGH_LEVEL icode instruction. * Note that register variables should not be considered registers. */ - assert(0!=Parent); + assert(nullptr!=Parent); ICODE::TypeFilter select_high_level; auto all_high_levels = instructions | filtered(select_high_level); for (auto picode=all_high_levels.begin(); picode!=all_high_levels.end(); ++picode) @@ -568,7 +564,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode, } RegisterNode * lhs_reg=dynamic_cast(lhs_unary); assert(lhs_reg); - if (rhs == NULL) /* In case expression popped is NULL */ + if (rhs == nullptr) /* In case expression popped is NULL */ return; /* Insert on rhs of ticode, if possible */ @@ -607,7 +603,7 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico { bool res; - if (_exp == NULL) /* In case expression popped is NULL */ + if (_exp == nullptr) /* In case expression popped is NULL */ return; /* Insert on rhs of ticode, if possible */ @@ -634,18 +630,18 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico * instruction f up to instruction t. */ bool UnaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs) { - if(0==unaryExp) + if(nullptr==unaryExp) return false; return unaryExp->xClear ( range_to_check, lastBBinst, locs); } bool BinaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs) { - if(0==m_rhs) + if(nullptr==m_rhs) return false; if ( ! m_rhs->xClear (range_to_check, lastBBinst, locs) ) return false; - if(0==m_lhs) + if(nullptr==m_lhs) return false; return m_lhs->xClear (range_to_check, lastBBinst, locs); } @@ -689,7 +685,7 @@ static int processCArg (Function * pp, Function * pProc, ICODE * picode, size_t { if (pp->args.numArgs > 0) { - if(_exp==NULL) + if(_exp==nullptr) fprintf(stderr,"Would try to adjustForArgType with null _exp\n"); else pp->args.adjustForArgType (numArgs, _exp->expType (pProc)); @@ -794,7 +790,7 @@ void Function::processHliCall(Expr *_exp, iICODE picode) { if (pp->args.numArgs >0) { - if(_exp==NULL) + if(_exp==nullptr) { fprintf(stderr,"Would try to adjustForArgType with null _exp\n"); } @@ -840,7 +836,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc) Expr *_exp; // expression pointer - for HLI_POP and HLI_CALL */ //Expr *lhs; // exp ptr for return value of a HLI_CALL */ iICODE ticode; // Target icode */ - HLTYPE *ti_hl=0; + HLTYPE *ti_hl=nullptr; uint8_t regi; numHlIcodes = 0; // register(s) to be forward substituted */ @@ -1129,7 +1125,7 @@ void Function::preprocessReturnDU(LivenessSet &_liveOut) // int idx; bool isAx, isBx, isCx, isDx; eReg bad_regs[] = {rES,rCS,rDS,rSS}; - constexpr char * names[] ={"ES","CS","DS","SS"}; + constexpr const char * names[] ={"ES","CS","DS","SS"}; for(int i=0; i<4; ++i) if(_liveOut.testReg(bad_regs[i])) { diff --git a/src/dcc.cpp b/src/dcc.cpp index e5550a4..08fae64 100644 --- a/src/dcc.cpp +++ b/src/dcc.cpp @@ -8,6 +8,7 @@ #include "dcc.h" #include "project.h" +#include "CallGraph.h" /* Global variables - extern to other modules */ extern char *asm1_name, *asm2_name; /* Assembler output filenames */ extern SYMTAB symtab; /* Global symbol table */ @@ -34,54 +35,49 @@ static void displayTotalStats(void); #include #include -#include +#include #include /**************************************************************************** * main ***************************************************************************/ #include using namespace llvm; -class TVisitor : public TableGenAction { -public: - virtual bool operator()(raw_ostream &OS, RecordKeeper &Records) +bool TVisitor(raw_ostream &OS, RecordKeeper &Records) +{ + Record *rec = Records.getDef("ADD8i8"); + if(rec) { - Record *rec = Records.getDef("ADD8i8"); - if(rec) - { - if(not rec->getTemplateArgs().empty()) - std::cout << "Has template args\n"; - auto classes(rec->getSuperClasses()); - for(auto val : rec->getSuperClasses()) - std::cout << "Super "<getName()<<"\n"; + if(not rec->getTemplateArgs().empty()) + std::cout << "Has template args\n"; + auto classes(rec->getSuperClasses()); + for(auto val : rec->getSuperClasses()) + std::cout << "Super "<getName()<<"\n"; -// DagInit * in = rec->getValueAsDag(val.getName()); -// in->dump(); - for(const RecordVal &val : rec->getValues()) - { -// val.dump(); - } - rec->dump(); - - } - // rec = Records.getDef("CCR"); - // if(rec) - // rec->dump(); - for(auto val : Records.getDefs()) + // DagInit * in = rec->getValueAsDag(val.getName()); + // in->dump(); + for(const RecordVal &val : rec->getValues()) { - //std::cout<< "Def "<dump(); + } -}; + // rec = Records.getDef("CCR"); + // if(rec) + // rec->dump(); + for(auto val : Records.getDefs()) + { + //std::cout<< "Def "<ll()->label, 0)) + readVal(operands_s, lab->ll()->label, nullptr)) { break; /* Symbolic label. Done */ } @@ -483,7 +483,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass) /* Check for user supplied comment */ selectTable(Comment); ostringstream cbuf; - if (readVal(cbuf, inst.label, 0)) + if (readVal(cbuf, inst.label, nullptr)) { result_stream <<"; "<callGraph = 0; + Project::get()->callGraph = nullptr; Project::get()->create(m_fname); /* Load program into memory */ @@ -213,7 +213,7 @@ void DccFrontend::LoadImage(Project &proj) uint8_t buf[4]; /* Open the input file */ - if ((fp = fopen(proj.binary_path().c_str(), "rb")) == NULL) + if ((fp = fopen(proj.binary_path().c_str(), "rb")) == nullptr) { fatalError(CANNOT_OPEN, proj.binary_path().c_str()); } diff --git a/src/graph.cpp b/src/graph.cpp index a47791a..ea653bc 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -83,8 +83,8 @@ CondJumps: if (ll->testFlags(SWITCH)) { pBB = BB::Create(current_range, MULTI_BRANCH, this); - for (size_t i = 0; i < ll->caseTbl2.size(); i++) - pBB->addOutEdge(ll->caseTbl2[i]); + for (auto & elem : ll->caseTbl2) + pBB->addOutEdge(elem); hasCase = true; } else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT @@ -138,9 +138,9 @@ CondJumps: for (; iter!=heldBBs.end(); ++iter) { pBB = *iter; - for (size_t edeg_idx = 0; edeg_idx < pBB->edges.size(); edeg_idx++) + for (auto & elem : pBB->edges) { - int32_t ip = pBB->edges[edeg_idx].ip; + int32_t ip = elem.ip; if (ip >= SYNTHESIZED_MIN) { fatalError (INVALID_SYNTHETIC_BB); @@ -151,7 +151,7 @@ CondJumps: if(iter2==heldBBs.end()) fatalError(NO_BB, ip, name.c_str()); psBB = *iter2; - pBB->edges[edeg_idx].BBptr = psBB; + elem.BBptr = psBB; psBB->inEdges.push_back((BB *)nullptr); } } @@ -258,7 +258,7 @@ void Function::compressCFG() /* Allocate storage for dfsLast[] array */ numBBs = stats.numBBaft; - m_dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *)) + m_dfsLast.resize(numBBs,nullptr); // = (BB **)allocMem(numBBs * sizeof(BB *)) /* Now do a dfs numbering traversal and fill in the inEdges[] array */ last = numBBs - 1; @@ -360,10 +360,10 @@ void BB::mergeFallThrough( CIcodeRec &Icode) traversed = DFS_MERGE; /* Process all out edges recursively */ -for (size_t i = 0; i < edges.size(); i++) +for (auto & elem : edges) { - if (edges[i].BBptr->traversed != DFS_MERGE) - edges[i].BBptr->mergeFallThrough(Icode); + if (elem.BBptr->traversed != DFS_MERGE) + elem.BBptr->mergeFallThrough(Icode); } } diff --git a/src/hlicode.cpp b/src/hlicode.cpp index d179da8..4f85b9d 100644 --- a/src/hlicode.cpp +++ b/src/hlicode.cpp @@ -97,7 +97,7 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId) if(p and p->removeRegFromLong(regi,locId)) { du1.removeDef(regi); //du1.numRegsDef--; - //du.def &= maskDuReg[regi]; + //du.def &= maskDuReg[regi]; du.def.clrReg(regi); } return false; @@ -305,9 +305,9 @@ static bool needsLhs(unsigned opc) * refines the HIGH_LEVEL icodes. */ void Function::highLevelGen() { - size_t numIcode; /* number of icode instructions */ - iICODE pIcode; /* ptr to current icode node */ - Expr *rhs; /* left- and right-hand side of expression */ + size_t numIcode; /* number of icode instructions */ + iICODE pIcode; /* ptr to current icode node */ + Expr *rhs; /* left- and right-hand side of expression */ uint32_t _flg; /* icode flags */ numIcode = Icode.size(); for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i) @@ -316,6 +316,8 @@ void Function::highLevelGen() assert(numIcode==Icode.size()); pIcode = i; //Icode.GetIcode(i) LLInst *ll = pIcode->ll(); + LLOperand *dst_ll = ll->get(DST); + LLOperand *src_ll = ll->get(SRC); if ( ll->testFlags(NOT_HLL) ) pIcode->invalidate(); if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() ) @@ -327,8 +329,14 @@ void Function::highLevelGen() if ( not ll->testFlags(NO_SRC) ) /* if there is src op */ rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE); if(ll->m_dst.isSet() || (ll->getOpcode()==iMOD)) - lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE); + lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE); } + if(ll->getOpcode()==iPUSH) { + if(ll->testFlags(I)) { + lhs = new Constant(src_ll->opz,src_ll->byteWidth()); + } +// lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE); + } if(needsLhs(ll->getOpcode())) assert(lhs!=nullptr); switch (ll->getOpcode()) @@ -356,18 +364,13 @@ void Function::highLevelGen() case iDIV: case iIDIV:/* should be signed div */ + { + eReg v = ( dst_ll->byteWidth()==1) ? rAL:rAX; rhs = new BinaryOperator(DIV,lhs, rhs); - if ( ll->testFlags(B) ) - { - lhs = new RegisterNode(rAL, 0, &localId); - pIcode->setRegDU( rAL, eDEF); - } - else - { - lhs = new RegisterNode(rAX, 0, &localId); - pIcode->setRegDU( rAX, eDEF); - } + lhs = new RegisterNode(LLOperand(v, dst_ll->byteWidth()), &localId); + pIcode->setRegDU( v, eDEF); pIcode->setAsgn(lhs, rhs); + } break; case iIMUL: @@ -387,17 +390,13 @@ void Function::highLevelGen() break; case iMOD: + { rhs = new BinaryOperator(MOD,lhs, rhs); - eReg lhs_reg; - - if ( ll->testFlags(B) ) - lhs_reg = rAH; - else - lhs_reg = rDX; - - lhs = new RegisterNode(lhs_reg, 0, &localId); + eReg lhs_reg = (dst_ll->byteWidth()==1) ? rAH : rDX; + lhs = new RegisterNode(LLOperand(lhs_reg, dst_ll->byteWidth()), &localId); pIcode->setRegDU( lhs_reg, eDEF); pIcode->setAsgn(lhs, rhs); + } break; case iMOV: pIcode->setAsgn(lhs, rhs); @@ -415,7 +414,7 @@ void Function::highLevelGen() break; case iNOT: - rhs = new BinaryOperator(NOT,NULL, rhs); // TODO: change this to unary NOT ? + rhs = new BinaryOperator(NOT,nullptr, rhs); // TODO: change this to unary NOT ? pIcode->setAsgn(lhs, rhs); break; @@ -433,7 +432,7 @@ void Function::highLevelGen() break; case iRET: - case iRETF: pIcode->setUnary(HLI_RET, NULL); + case iRETF: pIcode->setUnary(HLI_RET, nullptr); break; case iSHL: @@ -498,7 +497,7 @@ std::string Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc) /* Displays the output of a HLI_JCOND icode. */ -char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc) +const char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc) { memset (buf, ' ', sizeof(buf)); buf[0] = '\0'; @@ -521,7 +520,7 @@ char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc) /* Displays the inverse output of a HLI_JCOND icode. This is used in the case * when the THEN clause of an if..then..else is empty. The clause is * negated and the ELSE clause is used instead. */ -char *writeJcondInv (HLTYPE h, Function * pProc, int *numLoc) +const char *writeJcondInv(HLTYPE h, Function * pProc, int *numLoc) { memset (buf, ' ', sizeof(buf)); buf[0] = '\0'; @@ -638,12 +637,12 @@ void ICODE::writeDU() { if (not du1.used(i)) continue; - printf ("%d: du1[%d][] = ", my_idx, i); - for(auto j : du1.idx[i].uses) - { - printf ("%d ", j->loc_ip); - } - printf ("\n"); + printf ("%d: du1[%d][] = ", my_idx, i); + for(auto j : du1.idx[i].uses) + { + printf ("%d ", j->loc_ip); + } + printf ("\n"); } /* For HLI_CALL, print # parameter bytes */ diff --git a/src/hltype.cpp b/src/hltype.cpp index 9bd5f67..8162487 100644 --- a/src/hltype.cpp +++ b/src/hltype.cpp @@ -20,6 +20,6 @@ HlTypeSupport *HLTYPE::get() case HLI_PUSH: return &exp; case HLI_CALL: return &call; default: - return 0; + return nullptr; } } diff --git a/src/idioms.cpp b/src/idioms.cpp index c7066b8..d39b2ef 100644 --- a/src/idioms.cpp +++ b/src/idioms.cpp @@ -3,6 +3,8 @@ * (C) Cristina Cifuentes ****************************************************************************/ +#include +#include #include #include #include "idiom.h" @@ -15,8 +17,6 @@ #include "shift_idioms.h" #include "arith_idioms.h" #include "dcc.h" -#include -#include /***************************************************************************** * JmpInst - Returns true if opcode is a conditional or unconditional jump ****************************************************************************/ @@ -116,7 +116,7 @@ void Function::findIdioms() case iCALL: case iCALLF: /* Check for library functions that return a long register. * Propagate this result */ - if (pIcode->ll()->src().proc.proc != 0) + if (pIcode->ll()->src().proc.proc != nullptr) if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) && (pIcode->ll()->src().proc.proc->flg & PROC_IS_FUNC)) { diff --git a/src/idioms/mov_idioms.cpp b/src/idioms/mov_idioms.cpp index 4ba07e8..c932a18 100644 --- a/src/idioms/mov_idioms.cpp +++ b/src/idioms/mov_idioms.cpp @@ -27,6 +27,7 @@ bool Idiom14::match(iICODE pIcode) return false; m_icodes[0]=pIcode++; m_icodes[1]=pIcode++; + LLInst * matched [] = {m_icodes[0]->ll(),m_icodes[1]->ll()}; /* Check for regL */ m_regL = m_icodes[0]->ll()->m_dst.regi; if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX))) @@ -105,7 +106,7 @@ int Idiom13::action() eReg regi = m_icodes[0]->ll()->m_dst.regi; m_icodes[0]->du1.removeDef(regi); //m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */ - lhs = new RegisterNode(m_loaded_reg, 0, &m_func->localId); + lhs = new RegisterNode(LLOperand(m_loaded_reg, 0), &m_func->localId); m_icodes[0]->setRegDU( m_loaded_reg, eDEF); rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE); m_icodes[0]->setAsgn(lhs, rhs); diff --git a/src/idioms/neg_idioms.cpp b/src/idioms/neg_idioms.cpp index a319d23..b10db1b 100644 --- a/src/idioms/neg_idioms.cpp +++ b/src/idioms/neg_idioms.cpp @@ -97,7 +97,7 @@ int Idiom16::action() { AstIdent *lhs; Expr *rhs; - lhs = new RegisterNode(m_icodes[0]->ll()->m_dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId); + lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST),&m_func->localId); rhs = UnaryOperator::Create(NEGATION, lhs->clone()); m_icodes[0]->setAsgn(lhs, rhs); m_icodes[1]->invalidate(); diff --git a/src/idioms/shift_idioms.cpp b/src/idioms/shift_idioms.cpp index 48d8552..161a240 100644 --- a/src/idioms/shift_idioms.cpp +++ b/src/idioms/shift_idioms.cpp @@ -81,9 +81,7 @@ int Idiom15::action() AstIdent *lhs; Expr *rhs,*_exp; - lhs = new RegisterNode(m_icodes[0]->ll()->m_dst.regi, - m_icodes[0]->ll()->getFlag() & NO_SRC_B, - &m_func->localId); + lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST), &m_func->localId); rhs = new Constant(m_icodes.size(), 2); _exp = new BinaryOperator(SHL,lhs, rhs); m_icodes[0]->setAsgn(lhs, _exp); @@ -159,7 +157,7 @@ int Idiom9::action() { int idx; AstIdent *lhs; - Expr *rhs,*expr; + Expr *expr; eReg regH,regL; regL=m_icodes[1]->ll()->m_dst.regi; regH=m_icodes[0]->ll()->m_dst.regi; diff --git a/src/liveness_set.cpp b/src/liveness_set.cpp new file mode 100644 index 0000000..984ee8a --- /dev/null +++ b/src/liveness_set.cpp @@ -0,0 +1,54 @@ +#include "BasicBlock.h" +#include "machine_x86.h" + +/* DU bit definitions for each reg value - including index registers */ +LivenessSet duReg[] = { {}, + //AH AL . . AX, BH + {rAH,rAL,rAX},{rCH,rCL,rCX},{rDH,rDL,rDX},{rBH,rBL,rBX}, + /* uint16_t regs */ + {rSP},{rBP},{rSI},{rDI}, + /* seg regs */ + {rES},{rCS},{rSS},{rDS}, + /* uint8_t regs */ + {rAL},{rCL},{rDL},{rBL}, + {rAH},{rCH},{rDH},{rBH}, + /* tmp reg */ + {rTMP},{rTMP2}, + /* index regs */ + {rBX,rSI},{rBX,rDI},{rBP,rSI},{rBP,rDI}, + {rSI},{rDI},{rBP},{rBX} + }; + +LivenessSet &LivenessSet::setReg(int r) +{ + this->reset(); + *this |= duReg[r]; + return *this; +} +LivenessSet &LivenessSet::clrReg(int r) +{ + return *this -= duReg[r]; +} + +LivenessSet &LivenessSet::addReg(int r) +{ + *this |= duReg[r]; +// postProcessCompositeRegs(); + return *this; +} + +bool LivenessSet::testRegAndSubregs(int r) const +{ + return (*this & duReg[r]).any(); +} +void LivenessSet::postProcessCompositeRegs() +{ + if(testReg(rAL) and testReg(rAH)) + registers.insert(rAX); + if(testReg(rCL) and testReg(rCH)) + registers.insert(rCX); + if(testReg(rDL) and testReg(rDH)) + registers.insert(rDX); + if(testReg(rBL) and testReg(rBH)) + registers.insert(rBX); +} diff --git a/src/parser.cpp b/src/parser.cpp index c92b265..678de4e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -12,6 +12,7 @@ #include "dcc.h" #include "project.h" +#include "CallGraph.h" using namespace std; //static void FollowCtrl (Function * pProc, CALL_GRAPH * pcallGraph, STATE * pstate); @@ -50,7 +51,7 @@ void DccFrontend::parse(Project &proj) /* We know where main() is. Start the flow of control from there */ start_proc.procEntry = prog.offMain; /* In medium and large models, the segment of main may (will?) not be - the same as the initial CS segment (of the startup code) */ + the same as the initial CS segment (of the startup code) */ state.setState(rCS, prog.segMain); start_proc.name = "main"; state.IP = prog.offMain; @@ -88,7 +89,7 @@ int strSize (const uint8_t *sym, char delim) const uint8_t *end_ptr=std::find(sym,sym+(prog.cbImage-(till_end)),delim); return end_ptr-sym+1; } -Function *fakeproc=Function::Create(0,0,"fake"); +Function *fakeproc=Function::Create(nullptr,0,"fake"); /* FollowCtrl - Given an initial procedure, state information and symbol table * builds a list of procedures reachable from the initial procedure @@ -597,7 +598,7 @@ boolT Function::process_CALL (ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *ps } /* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at - * previous offset into the program image */ + * previous offset into the program image */ uint32_t tgtAddr=0; if (pIcode.ll()->getOpcode() == iCALLF) tgtAddr= LH(&prog.image()[off]) + ((uint32_t)(LH(&prog.image()[off+2])) << 4); diff --git a/src/procs.cpp b/src/procs.cpp index 97141aa..0b85f6a 100644 --- a/src/procs.cpp +++ b/src/procs.cpp @@ -9,6 +9,7 @@ #include #include "dcc.h" #include "project.h" +#include "CallGraph.h" extern Project g_proj; /* Static indentation buffer */ @@ -123,7 +124,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const for(STKSYM &tgt_sym : *target_stackframe) { RegisterNode *tgt_sym_regs = dynamic_cast(tgt_sym.regs); - if( tgt_sym_regs == NULL ) // both REGISTER and LONG_VAR require this precondition + if( tgt_sym_regs == nullptr ) // both REGISTER and LONG_VAR require this precondition continue; if ( tgt_sym_regs->regiIdx == tidx ) { @@ -142,7 +143,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const /* Check if register argument already on the formal argument list */ for(STKSYM &tgt_sym : *target_stackframe) { - if( tgt_sym.regs == NULL ) // both REGISTER and LONG_VAR require this precondition + if( tgt_sym.regs == nullptr ) // both REGISTER and LONG_VAR require this precondition continue; if ( tgt_sym.regs->ident.idNode.longIdx == tidx ) { @@ -273,7 +274,7 @@ Expr *Function::adjustActArgType (Expr *_exp, hlType forType) hlType actType; int offset, offL; - if (expr == NULL) + if (expr == nullptr) return _exp; actType = expr-> expType (this); diff --git a/src/project.cpp b/src/project.cpp index c292741..7fc8364 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -9,7 +9,7 @@ SYMTAB symtab; /* Global symbol table */ STATS stats; /* cfg statistics */ //PROG prog; /* programs fields */ OPTION option; /* Command line options */ -Project *Project::s_instance = 0; +Project *Project::s_instance = nullptr; Project::Project() : callGraph(nullptr) { memset(&prog,0,sizeof(prog)); @@ -94,7 +94,7 @@ const std::string &Project::symbolName(size_t idx) Project *Project::get() { //WARNING: poor man's singleton, not thread safe - if(s_instance==0) + if(s_instance==nullptr) s_instance=new Project; return s_instance; } diff --git a/src/proplong.cpp b/src/proplong.cpp index 734bccd..1ff9dc1 100644 --- a/src/proplong.cpp +++ b/src/proplong.cpp @@ -352,7 +352,7 @@ int Function::findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE be icode.setRegDU( pmH->regi, eDEF); icode.setUnary(HLI_POP, asgn.lhs); next1->invalidate(); - asgn.lhs=0; + asgn.lhs=nullptr; forced_finish=true; /* to exit the loop */ } break; diff --git a/src/reducible.cpp b/src/reducible.cpp index 2e2454c..6d15260 100644 --- a/src/reducible.cpp +++ b/src/reducible.cpp @@ -54,7 +54,7 @@ BB *interval::firstOfInt () { auto pq = currNode; if (pq == nodes.end()) - return 0; + return nullptr; ++currNode; return *pq; } @@ -108,7 +108,7 @@ void derSeq_Entry::findIntervals (Function *c) appendQueue (H, Gi); /* H = {first node of G} */ Gi->beenOnH = true; - Gi->reachingInt = BB::Create(0,"",c); /* ^ empty BB */ + Gi->reachingInt = BB::Create(nullptr,"",c); /* ^ empty BB */ /* Process header nodes list H */ while (!H.empty()) @@ -124,15 +124,15 @@ void derSeq_Entry::findIntervals (Function *c) pI->appendNodeInt (H, header); /* pI(header) = {header} */ /* Process all nodes in the current interval list */ - while ((h = pI->firstOfInt()) != NULL) + while ((h = pI->firstOfInt()) != nullptr) { /* Check all immediate successors of h */ - for (size_t i = 0; i < h->edges.size(); i++) + for (auto & elem : h->edges) { - succ = h->edges[i].BBptr; + succ = elem.BBptr; succ->inEdgeCount--; - if (succ->reachingInt == NULL) /* first visit */ + if (succ->reachingInt == nullptr) /* first visit */ { succ->reachingInt = header; if (succ->inEdgeCount == 0) @@ -182,7 +182,7 @@ static void displayIntervals (interval *pI) printf (" Interval #: %d\t#OutEdges: %d\n", pI->numInt, pI->numOutEdges); for(BB *node : pI->nodes) { - if (node->correspInt == NULL) /* real BBs */ + if (node->correspInt == nullptr) /* real BBs */ printf (" Node: %d\n", node->begin()->loc_ip); else // BBs represent intervals printf (" Node (corresp int): %d\n", node->correspInt->numInt); @@ -248,7 +248,7 @@ bool Function::nextOrderGraph (derSeq &derivedGi) derSeq_Entry &new_entry(derivedGi.back()); sameGraph = true; - BBnode = 0; + BBnode = nullptr; std::vector bbs; for(Ii = prev_entry.Ii; Ii != nullptr; Ii = Ii->next) { diff --git a/src/scanner.cpp b/src/scanner.cpp index af9f1b7..1dd0478 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -64,7 +64,7 @@ static struct { { data1, axImp, B , iADD }, /* 04 */ { data2, axImp, 0 , iADD }, /* 05 */ { segop, none2, NO_SRC , iPUSH }, /* 06 */ - { segop, none2, NO_SRC , iPOP }, /* 07 */ + { segop, none2, NO_SRC , iPOP }, /* 07 */ { modrm, none2, B , iOR }, /* 08 */ { modrm, none2, NSP , iOR }, /* 09 */ { modrm, none2, TO_REG | B , iOR }, /* 0A */ @@ -96,7 +96,7 @@ static struct { { data1, axImp, B , iAND }, /* 24 */ { data2, axImp, 0 , iAND }, /* 25 */ { prefix, none2, 0 , (IC)rES}, /* 26 */ - { none1, axImp, NOT_HLL | B|NO_SRC , iDAA }, /* 27 */ + { none1, axImp, NOT_HLL | B|NO_SRC , iDAA }, /* 27 */ { modrm, none2, B , iSUB }, /* 28 */ { modrm, none2, 0 , iSUB }, /* 29 */ { modrm, none2, TO_REG | B , iSUB }, /* 2A */ @@ -133,7 +133,7 @@ static struct { { regop, none2, 0 , iDEC }, /* 49 */ { regop, none2, 0 , iDEC }, /* 4A */ { regop, none2, 0 , iDEC }, /* 4B */ - { regop, none2, NOT_HLL , iDEC }, /* 4C */ + { regop, none2, NOT_HLL , iDEC }, /* 4C */ { regop, none2, 0 , iDEC }, /* 4D */ { regop, none2, 0 , iDEC }, /* 4E */ { regop, none2, 0 , iDEC }, /* 4F */ @@ -450,7 +450,7 @@ LLOperand convertExpression(const x86_ea_t &from) { eReg base_reg = convertRegister(from.base); eReg index_reg = convertRegister(from.index); -// if(base_reg==rBX) + // if(base_reg==rBX) switch(base_reg) { case rDI: @@ -566,8 +566,8 @@ eErrorId scan(uint32_t ip, ICODE &p) if(p.insn.x86_get_branch_target()) decodeBranchTgt(p.insn); } -// LLOperand conv = convertOperand(*p.insn.get_dest()); -// assert(conv==p.ll()->dst); + // LLOperand conv = convertOperand(*p.insn.get_dest()); + // assert(conv==p.ll()->dst); if (p.ll()->getOpcode()) { /* Save bytes of image used */ @@ -626,14 +626,12 @@ static int signex(uint8_t b) ***************************************************************************/ static void setAddress(int i, bool fdst, uint16_t seg, int16_t reg, uint16_t off) { - LLOperand *pm; - /* If not to register (i.e. to r/m), and talking about r/m, then this is dest */ - pm = (!(stateTable[i].flg & TO_REG) == fdst) ? - &pIcode->ll()->m_dst : &pIcode->ll()->src(); + LLOperand *pm = (!(stateTable[i].flg & TO_REG) == fdst) ? &pIcode->ll()->m_dst : &pIcode->ll()->src(); /* Set segment. A later procedure (lookupAddr in proclist.c) will - * provide the value of this segment in the field segValue. */ + * provide the value of this segment in the field segValue. + */ if (seg) /* segment override */ { pm->seg = pm->segOver = (eReg)seg; @@ -733,7 +731,7 @@ static void segrm(int i) ***************************************************************************/ static void regop(int i) { - setAddress(i, false, 0, ((int16_t)i & 7) + rAX, 0); + setAddress(i, false, 0, ((int16_t)i & 0x7) + rAX, 0); pIcode->ll()->replaceDst(pIcode->ll()->src()); } @@ -743,6 +741,9 @@ static void regop(int i) *****************************************************************************/ static void segop(int i) { + if(i==0x1E) { + printf("es"); + } setAddress(i, true, 0, (((int16_t)i & 0x18) >> 3) + rES, 0); } @@ -837,11 +838,14 @@ static void trans(int i) { static llIcode transTable[8] = { - (llIcode)iINC, (llIcode)iDEC, (llIcode)iCALL, (llIcode)iCALLF, + (llIcode)iINC, iDEC, (llIcode)iCALL, (llIcode)iCALLF, (llIcode)iJMP, (llIcode)iJMPF,(llIcode)iPUSH, (llIcode)0 }; LLInst *ll = pIcode->ll(); - if ((uint8_t)REG(*pInst) < 2 || !(stateTable[i].flg & B)) { /* INC & DEC */ + if(transTable[REG(*pInst)]==iPUSH) { + printf("es"); + } + if ((uint8_t)REG(*pInst) < 2 || !(stateTable[i].flg & B)) { /* INC & DEC */ ll->setOpcode(transTable[REG(*pInst)]); /* valid on bytes */ rm(i); ll->replaceSrc( pIcode->ll()->m_dst ); @@ -895,7 +899,7 @@ static void arith(int i) *****************************************************************************/ static void data1(int i) { - pIcode->ll()->replaceSrc(LLOperand::CreateImm2((stateTable[i].flg & S_EXT)? signex(*pInst++): *pInst++)); + pIcode->ll()->replaceSrc(LLOperand::CreateImm2((stateTable[i].flg & S_EXT)? signex(*pInst++): *pInst++,1)); pIcode->ll()->setFlags(I); } @@ -937,6 +941,7 @@ static void dispM(int i) ****************************************************************************/ static void dispN(int ) { + //PROG &prog(Project::get()->prog); /*long off = (short)*/getWord(); /* Signed displacement */ @@ -961,10 +966,11 @@ static void dispS(int ) /**************************************************************************** dispF - 4 byte disp as immed 20-bit target address ***************************************************************************/ -static void dispF(int ) +static void dispF(int i) { - /*off = */(unsigned)getWord(); - /*seg = */(unsigned)getWord(); + uint16_t off = (unsigned)getWord(); + uint16_t seg = (unsigned)getWord(); + setAddress(i, true, seg, 0, off); // decodeBranchTgt(); } diff --git a/src/symtab.cpp b/src/symtab.cpp index 22018cf..2f05111 100644 --- a/src/symtab.cpp +++ b/src/symtab.cpp @@ -53,7 +53,7 @@ struct TABLEINFO_TYPE { TABLEINFO_TYPE() { - symTab=valTab=0; + symTab=valTab=nullptr; } //void deleteVal(uint32_t symOff, Function *symProc, boolT bSymToo); void create(tableType type); @@ -80,7 +80,7 @@ void TABLEINFO_TYPE::create(tableType type) numEntry = 0; tableSize = TABLESIZE; valTab = new SYMTABLE [TABLESIZE]; - symTab = 0; + symTab = nullptr; break; case Label: currentTabInfo.numEntry = 0; diff --git a/src/udm.cpp b/src/udm.cpp index c8f2e81..bf119d1 100644 --- a/src/udm.cpp +++ b/src/udm.cpp @@ -44,7 +44,7 @@ void Function::controlFlowAnalysis() { if (flg & PROC_ISLIB) return; /* Ignore library functions */ - derSeq *derivedG=0; + derSeq *derivedG=nullptr; /* Make cfg reducible and build derived sequences */ derivedG=checkReducibility();