commit 292c2829ab3d9b258acf187cc303b6632829f395 Author: Jeremy Rand Date: Fri Jul 4 22:48:00 2014 -0400 Initial commit with LLVM 3.4.1, cfe 3.4.1 and compiler-rt 3.4 diff --git a/.arcconfig b/.arcconfig new file mode 100644 index 00000000..4711195a --- /dev/null +++ b/.arcconfig @@ -0,0 +1,4 @@ +{ + "project_id" : "llvm", + "conduit_uri" : "http://llvm-reviews.chandlerc.com/" +} diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..9b3aa8b7 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: LLVM diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..24628309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +#==============================================================================# +# This file specifies intentionally untracked files that git should ignore. +# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html +# +# This file is intentionally different from the output of `git svn show-ignore`, +# as most of those are useless. +#==============================================================================# + +#==============================================================================# +# File extensions to be ignored anywhere in the tree. +#==============================================================================# +# Temp files created by most text editors. +*~ +# Merge files created by git. +*.orig +# Byte compiled python modules. +*.pyc +# vim swap files +.*.swp +.sw? + +#==============================================================================# +# Explicit files to ignore (only matches one). +#==============================================================================# +.gitusers +autom4te.cache +cscope.files +cscope.out +autoconf/aclocal.m4 +autoconf/autom4te.cache +compile_commands.json + +#==============================================================================# +# Directories to ignore (do not add trailing '/'s, they skip symlinks). +#==============================================================================# +# External projects that are tracked independently. +projects/* +!projects/sample +!projects/CMakeLists.txt +!projects/Makefile +# Clang, which is tracked independently. +tools/clang +# LLDB, which is tracked independently. +tools/lldb +# lld, which is tracked independently. +tools/lld +# Sphinx build tree, if building in-source dir. +docs/_build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..bd0f846f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,532 @@ +# See docs/CMake.html for instructions about how to build LLVM with CMake. + +project(LLVM) +cmake_minimum_required(VERSION 2.8) + +# Add path for custom modules +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" + ) + +set(LLVM_VERSION_MAJOR 3) +set(LLVM_VERSION_MINOR 4) +set(LLVM_VERSION_PATCH 1) + +if (NOT PACKAGE_VERSION) + set(PACKAGE_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") +endif() + +option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF) + +option(LLVM_USE_FOLDERS "Enable solution folders in Visual Studio. Disable for Express versions." ON) +if ( LLVM_USE_FOLDERS ) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif() + +include(VersionFromVCS) + +option(LLVM_APPEND_VC_REV + "Append the version control system revision id to LLVM version" OFF) + +if( LLVM_APPEND_VC_REV ) + add_version_info_from_vcs(PACKAGE_VERSION) +endif() + +set(PACKAGE_NAME LLVM) +set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") +set(PACKAGE_BUGREPORT "http://llvm.org/bugs/") + +# Configure CPack. +set(CPACK_PACKAGE_INSTALL_DIRECTORY "LLVM") +set(CPACK_PACKAGE_VENDOR "LLVM") +set(CPACK_PACKAGE_VERSION_MAJOR ${LLVM_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${LLVM_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${LLVM_VERSION_PATCH}) +set(CPACK_PACKAGE_VERSION ${PACKAGE_VERSION}) +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.TXT") +if(WIN32 AND NOT UNIX) + set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "LLVM") + set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\cmake\\\\nsis_logo.bmp") + set(CPACK_NSIS_MODIFY_PATH "ON") + set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") + set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS + "ExecWait '$INSTDIR/tools/msbuild/install.bat'") + set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS + "ExecWait '$INSTDIR/tools/msbuild/uninstall.bat'") +endif() +include(CPack) + +# Sanity check our source directory to make sure that we are not trying to +# generate an in-tree build (unless on MSVC_IDE, where it is ok), and to make +# sure that we don't have any stray generated files lying around in the tree +# (which would end up getting picked up by header search, instead of the correct +# versions). +if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE ) + message(FATAL_ERROR "In-source builds are not allowed. +CMake would overwrite the makefiles distributed with LLVM. +Please create a directory and run cmake from there, passing the path +to this source directory as the last argument. +This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. +Please delete them.") +endif() +if( NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) + file(GLOB_RECURSE + tablegenned_files_on_include_dir + "${CMAKE_CURRENT_SOURCE_DIR}/include/llvm/*.gen") + file(GLOB_RECURSE + tablegenned_files_on_lib_dir + "${CMAKE_CURRENT_SOURCE_DIR}/lib/Target/*.inc") + if( tablegenned_files_on_include_dir OR tablegenned_files_on_lib_dir) + message(FATAL_ERROR "Apparently there is a previous in-source build, +probably as the result of running `configure' and `make' on +${CMAKE_CURRENT_SOURCE_DIR}. +This may cause problems. The suspicious files are: +${tablegenned_files_on_lib_dir} +${tablegenned_files_on_include_dir} +Please clean the source directory.") + endif() +endif() + +string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) + +set(LLVM_MAIN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(LLVM_MAIN_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/include) +set(LLVM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(LLVM_TOOLS_BINARY_DIR ${LLVM_BINARY_DIR}/bin) +set(LLVM_EXAMPLES_BINARY_DIR ${LLVM_BINARY_DIR}/examples) +set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" ) + +set(LLVM_ALL_TARGETS + AArch64 + ARM + CppBackend + Hexagon + Mips + MSP430 + NVPTX + PowerPC + R600 + Sparc + SystemZ + X86 + XCore + ) + +# List of targets with JIT support: +set(LLVM_TARGETS_WITH_JIT X86 PowerPC AArch64 ARM Mips SystemZ) + +set(LLVM_TARGETS_TO_BUILD "all" + CACHE STRING "Semicolon-separated list of targets to build, or \"all\".") + +set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "" + CACHE STRING "Semicolon-separated list of experimental targets to build.") + +option(BUILD_SHARED_LIBS + "Build all libraries as shared libraries instead of static" OFF) + +option(LLVM_ENABLE_CBE_PRINTF_A "Set to ON if CBE is enabled for printf %a output" ON) +if(LLVM_ENABLE_CBE_PRINTF_A) + set(ENABLE_CBE_PRINTF_A 1) +endif() + +option(LLVM_ENABLE_TIMESTAMPS "Enable embedding timestamp information in build" ON) +if(LLVM_ENABLE_TIMESTAMPS) + set(ENABLE_TIMESTAMPS 1) +endif() + +option(LLVM_ENABLE_BACKTRACES "Enable embedding backtraces on crash." ON) +if(LLVM_ENABLE_BACKTRACES) + set(ENABLE_BACKTRACES 1) +endif() + +option(LLVM_ENABLE_CRASH_OVERRIDES "Enable crash overrides." ON) +if(LLVM_ENABLE_CRASH_OVERRIDES) + set(ENABLE_CRASH_OVERRIDES 1) +endif() + +option(LLVM_ENABLE_FFI "Use libffi to call external functions from the interpreter" OFF) +set(FFI_LIBRARY_DIR "" CACHE PATH "Additional directory, where CMake should search for libffi.so") +set(FFI_INCLUDE_DIR "" CACHE PATH "Additional directory, where CMake should search for ffi.h or ffi/ffi.h") + +set(LLVM_TARGET_ARCH "host" + CACHE STRING "Set target to use for LLVM JIT or use \"host\" for automatic detection.") + +option(LLVM_ENABLE_TERMINFO "Use terminfo database if available." ON) + +option(LLVM_ENABLE_THREADS "Use threads if available." ON) + +option(LLVM_ENABLE_ZLIB "Use zlib for compression/decompression if available." ON) + +if( LLVM_TARGETS_TO_BUILD STREQUAL "all" ) + set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} ) +endif() + +set(LLVM_TARGETS_TO_BUILD + ${LLVM_TARGETS_TO_BUILD} + ${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD}) +list(REMOVE_DUPLICATES LLVM_TARGETS_TO_BUILD) + +set(llvm_builded_incs_dir ${LLVM_BINARY_DIR}/include/llvm) + +include(AddLLVMDefinitions) + +option(LLVM_ENABLE_PIC "Build Position-Independent Code" ON) + +# MSVC has a gazillion warnings with this. +if( MSVC ) + option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." OFF) +else( MSVC ) + option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." ON) +endif() + +option(LLVM_ENABLE_PEDANTIC "Compile with pedantic enabled." ON) +option(LLVM_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) + +if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) + option(LLVM_ENABLE_ASSERTIONS "Enable assertions" OFF) +else() + option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON) +endif() + +option(LLVM_USE_INTEL_JITEVENTS + "Use Intel JIT API to inform Intel(R) VTune(TM) Amplifier XE 2011 about JIT code" + OFF) + +if( LLVM_USE_INTEL_JITEVENTS ) + # Verify we are on a supported platform + if( NOT CMAKE_SYSTEM_NAME MATCHES "Windows" AND NOT CMAKE_SYSTEM_NAME MATCHES "Linux" ) + message(FATAL_ERROR + "Intel JIT API support is available on Linux and Windows only.") + endif() +endif( LLVM_USE_INTEL_JITEVENTS ) + +option(LLVM_USE_OPROFILE + "Use opagent JIT interface to inform OProfile about JIT code" OFF) + +# If enabled, verify we are on a platform that supports oprofile. +if( LLVM_USE_OPROFILE ) + if( NOT CMAKE_SYSTEM_NAME MATCHES "Linux" ) + message(FATAL_ERROR "OProfile support is available on Linux only.") + endif( NOT CMAKE_SYSTEM_NAME MATCHES "Linux" ) +endif( LLVM_USE_OPROFILE ) + +set(LLVM_USE_SANITIZER "" CACHE STRING + "Define the sanitizer used to build binaries and tests.") + +option(LLVM_USE_SPLIT_DWARF + "Use -gsplit-dwarf when compiling llvm." OFF) + +# Define an option controlling whether we should build for 32-bit on 64-bit +# platforms, where supported. +if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) + # TODO: support other platforms and toolchains. + option(LLVM_BUILD_32_BITS "Build 32 bits executables and libraries." OFF) +endif() + +# Define the default arguments to use with 'lit', and an option for the user to +# override. +set(LIT_ARGS_DEFAULT "-sv") +if (MSVC OR XCODE) + set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") +endif() +set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") + +# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools. +if( WIN32 AND NOT CYGWIN ) + set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") +endif() + +# Define options to control the inclusion and default build behavior for +# components which may not strictly be necessary (tools, examples, and tests). +# +# This is primarily to support building smaller or faster project files. +option(LLVM_INCLUDE_TOOLS "Generate build targets for the LLVM tools." ON) +option(LLVM_BUILD_TOOLS + "Build the LLVM tools. If OFF, just generate build targets." ON) + +option(LLVM_BUILD_RUNTIME + "Build the LLVM runtime libraries." ON) +option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) +option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + +option(LLVM_BUILD_TESTS + "Build LLVM unit tests. If OFF, just generate build targets." OFF) +option(LLVM_INCLUDE_TESTS "Generate build targets for the LLVM unit tests." ON) + +option (LLVM_BUILD_DOCS "Build the llvm documentation." OFF) +option (LLVM_INCLUDE_DOCS "Generate build targets for llvm documentation." ON) +option (LLVM_ENABLE_DOXYGEN "Use doxygen to generate llvm documentation." OFF) + +# All options referred to from HandleLLVMOptions have to be specified +# BEFORE this include, otherwise options will not be correctly set on +# first cmake run +include(config-ix) + +# By default, we target the host, but this can be overridden at CMake +# invocation time. +set(LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_HOST_TRIPLE}" CACHE STRING + "Default target for which LLVM will generate code." ) +set(TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}") + +include(HandleLLVMOptions) + +# Verify that we can find a Python 2 interpreter. Python 3 is unsupported. +set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5) +include(FindPythonInterp) +if( NOT PYTHONINTERP_FOUND ) + message(FATAL_ERROR +"Unable to find Python interpreter, required for builds and testing. + +Please install Python or specify the PYTHON_EXECUTABLE CMake variable.") +endif() + +###### +# LLVMBuild Integration +# +# We use llvm-build to generate all the data required by the CMake based +# build system in one swoop: +# +# - We generate a file (a CMake fragment) in the object root which contains +# all the definitions that are required by CMake. +# +# - We generate the library table used by llvm-config. +# +# - We generate the dependencies for the CMake fragment, so that we will +# automatically reconfigure outselves. + +set(LLVMBUILDTOOL "${LLVM_MAIN_SRC_DIR}/utils/llvm-build/llvm-build") +set(LLVMCONFIGLIBRARYDEPENDENCIESINC + "${LLVM_BINARY_DIR}/tools/llvm-config/LibraryDependencies.inc") +set(LLVMBUILDCMAKEFRAG + "${LLVM_BINARY_DIR}/LLVMBuild.cmake") + +# Create the list of optional components that are enabled +if (LLVM_USE_INTEL_JITEVENTS) + set(LLVMOPTIONALCOMPONENTS IntelJITEvents) +endif (LLVM_USE_INTEL_JITEVENTS) +if (LLVM_USE_OPROFILE) + set(LLVMOPTIONALCOMPONENTS ${LLVMOPTIONALCOMPONENTS} OProfileJIT) +endif (LLVM_USE_OPROFILE) + +message(STATUS "Constructing LLVMBuild project information") +execute_process( + COMMAND ${PYTHON_EXECUTABLE} ${LLVMBUILDTOOL} + --native-target "${LLVM_NATIVE_ARCH}" + --enable-targets "${LLVM_TARGETS_TO_BUILD}" + --enable-optional-components "${LLVMOPTIONALCOMPONENTS}" + --write-library-table ${LLVMCONFIGLIBRARYDEPENDENCIESINC} + --write-cmake-fragment ${LLVMBUILDCMAKEFRAG} + OUTPUT_VARIABLE LLVMBUILDOUTPUT + ERROR_VARIABLE LLVMBUILDERRORS + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE LLVMBUILDRESULT) + +# On Win32, CMake doesn't properly handle piping the default output/error +# streams into the GUI console. So, we explicitly catch and report them. +if( NOT "${LLVMBUILDOUTPUT}" STREQUAL "") + message(STATUS "llvm-build output: ${LLVMBUILDOUTPUT}") +endif() +if( NOT "${LLVMBUILDRESULT}" STREQUAL "0" ) + message(FATAL_ERROR + "Unexpected failure executing llvm-build: ${LLVMBUILDERRORS}") +endif() + +# Include the generated CMake fragment. This will define properties from the +# LLVMBuild files in a format which is easy to consume from CMake, and will add +# the dependencies so that CMake will reconfigure properly when the LLVMBuild +# files change. +include(${LLVMBUILDCMAKEFRAG}) + +###### + +# Configure all of the various header file fragments LLVM uses which depend on +# configuration variables. +set(LLVM_ENUM_TARGETS "") +set(LLVM_ENUM_ASM_PRINTERS "") +set(LLVM_ENUM_ASM_PARSERS "") +set(LLVM_ENUM_DISASSEMBLERS "") +foreach(t ${LLVM_TARGETS_TO_BUILD}) + set( td ${LLVM_MAIN_SRC_DIR}/lib/Target/${t} ) + + list(FIND LLVM_ALL_TARGETS ${t} idx) + list(FIND LLVM_EXPERIMENTAL_TARGETS_TO_BUILD ${t} idy) + if( idx LESS 0 AND idy LESS 0 ) + message(FATAL_ERROR "The target `${t}' does not exist. + It should be one of\n${LLVM_ALL_TARGETS}") + else() + set(LLVM_ENUM_TARGETS "${LLVM_ENUM_TARGETS}LLVM_TARGET(${t})\n") + endif() + + file(GLOB asmp_file "${td}/*AsmPrinter.cpp") + if( asmp_file ) + set(LLVM_ENUM_ASM_PRINTERS + "${LLVM_ENUM_ASM_PRINTERS}LLVM_ASM_PRINTER(${t})\n") + endif() + if( EXISTS ${td}/AsmParser/CMakeLists.txt ) + set(LLVM_ENUM_ASM_PARSERS + "${LLVM_ENUM_ASM_PARSERS}LLVM_ASM_PARSER(${t})\n") + endif() + if( EXISTS ${td}/Disassembler/CMakeLists.txt ) + set(LLVM_ENUM_DISASSEMBLERS + "${LLVM_ENUM_DISASSEMBLERS}LLVM_DISASSEMBLER(${t})\n") + endif() +endforeach(t) + +# Produce the target definition files, which provide a way for clients to easily +# include various classes of targets. +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/AsmPrinters.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/AsmPrinters.def + ) +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/AsmParsers.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/AsmParsers.def + ) +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Disassemblers.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/Disassemblers.def + ) +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Targets.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/Targets.def + ) + +# Configure the three LLVM configuration header files. +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/config.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/Config/config.h) +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/llvm-config.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/Config/llvm-config.h) +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support/DataTypes.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/Support/DataTypes.h) + +set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR} ) +set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) +set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +include_directories( ${LLVM_BINARY_DIR}/include ${LLVM_MAIN_INCLUDE_DIR}) + +if( ${CMAKE_SYSTEM_NAME} MATCHES FreeBSD ) + # On FreeBSD, /usr/local/* is not used by default. In order to build LLVM + # with libxml2, iconv.h, etc., we must add /usr/local paths. + include_directories("/usr/local/include") + link_directories("/usr/local/lib") +endif( ${CMAKE_SYSTEM_NAME} MATCHES FreeBSD ) + +if( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include llvm/Support/Solaris.h") +endif( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) + +# Make sure we don't get -rdynamic in every binary. For those that need it, +# use set_target_properties(target PROPERTIES ENABLE_EXPORTS 1) +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +include(AddLLVM) +include(TableGen) + +if( MINGW ) + # People report that -O3 is unreliable on MinGW. The traditional + # build also uses -O2 for that reason: + llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELEASE "-O3" "-O2") +endif() + +# Put this before tblgen. Else we have a circular dependence. +add_subdirectory(lib/Support) +add_subdirectory(lib/TableGen) + +add_subdirectory(utils/TableGen) + +add_subdirectory(include/llvm) + +add_subdirectory(lib) + +add_subdirectory(utils/FileCheck) +add_subdirectory(utils/FileUpdate) +add_subdirectory(utils/count) +add_subdirectory(utils/not) +add_subdirectory(utils/llvm-lit) +add_subdirectory(utils/yaml-bench) + +add_subdirectory(projects) + +if( LLVM_INCLUDE_TOOLS ) + add_subdirectory(tools) +endif() + +if( LLVM_INCLUDE_EXAMPLES ) + add_subdirectory(examples) +endif() + +if( LLVM_INCLUDE_TESTS ) + add_subdirectory(test) + add_subdirectory(utils/unittest) + add_subdirectory(unittests) + if (MSVC) + # This utility is used to prevent crashing tests from calling Dr. Watson on + # Windows. + add_subdirectory(utils/KillTheDoctor) + endif() + + # Add a global check rule now that all subdirectories have been traversed + # and we know the total set of lit testsuites. + get_property(LLVM_LIT_TESTSUITES GLOBAL PROPERTY LLVM_LIT_TESTSUITES) + get_property(LLVM_LIT_PARAMS GLOBAL PROPERTY LLVM_LIT_PARAMS) + get_property(LLVM_LIT_DEPENDS GLOBAL PROPERTY LLVM_LIT_DEPENDS) + get_property(LLVM_LIT_EXTRA_ARGS GLOBAL PROPERTY LLVM_LIT_EXTRA_ARGS) + add_lit_target(check-all + "Running all regression tests" + ${LLVM_LIT_TESTSUITES} + PARAMS ${LLVM_LIT_PARAMS} + DEPENDS ${LLVM_LIT_DEPENDS} + ARGS ${LLVM_LIT_EXTRA_ARGS} + ) +endif() + +if (LLVM_INCLUDE_DOCS) + add_subdirectory(docs) +endif() + +add_subdirectory(cmake/modules) + +if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(DIRECTORY include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" + PATTERN "*.td" + PATTERN "*.inc" + PATTERN "LICENSE.TXT" + PATTERN ".svn" EXCLUDE + ) + + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" + PATTERN "*.gen" + PATTERN "*.inc" + # Exclude include/llvm/CMakeFiles/intrinsics_gen.dir, matched by "*.def" + PATTERN "CMakeFiles" EXCLUDE + PATTERN ".svn" EXCLUDE + ) +endif() + +# Workaround for MSVS10 to avoid the Dialog Hell +# FIXME: This could be removed with future version of CMake. +if(MSVC_VERSION EQUAL 1600) + set(LLVM_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/LLVM.sln") + if( EXISTS "${LLVM_SLN_FILENAME}" ) + file(APPEND "${LLVM_SLN_FILENAME}" "\n# This should be regenerated!\n") + endif() +endif() + diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT new file mode 100644 index 00000000..cffb91b6 --- /dev/null +++ b/CODE_OWNERS.TXT @@ -0,0 +1,151 @@ +This file is a list of the people responsible for ensuring that patches for a +particular part of LLVM are reviewed, either by themself or by someone else. +They are also the gatekeepers for their part of LLVM, with the final word on +what goes in or not. + +The list is sorted by surname and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), web-address +(W), PGP key ID and fingerprint (P), description (D), and snail-mail address +(S). + +N: Joe Abbey +E: jabbey@arxan.com +D: LLVM Bitcode (lib/Bitcode/* include/llvm/Bitcode/*) + +N: Owen Anderson +E: resistor@mac.com +D: SelectionDAG (lib/CodeGen/SelectionDAG/*) + +N: Rafael Avila de Espindola +E: rafael.espindola@gmail.com +D: Gold plugin (tools/gold/*) + +N: Chandler Carruth +E: chandlerc@gmail.com +E: chandlerc@google.com +D: Config, ADT, Support, inlining & related passes, SROA/mem2reg & related passes, CMake, library layering + +N: Evan Cheng +E: evan.cheng@apple.com +D: ARM target, parts of code generator not covered by someone else + +N: Eric Christopher +E: echristo@gmail.com +D: Debug Information, autotools/configure/make build, inline assembly + +N: Greg Clayton +D: LLDB + +N: Peter Collingbourne +D: libclc + +N: Anshuman Dasgupta +E: adasgupt@codeaurora.org +D: Hexagon Backend + +N: Hal Finkel +E: hfinkel@anl.gov +D: BBVectorize and the PowerPC target + +N: Venkatraman Govindaraju +E: venkatra@cs.wisc.edu +D: Sparc Backend (lib/Target/Sparc/*) + +N: Tobias Grosser +D: Polly + +N: James Grosbach +E: grosbach@apple.com +D: MC layer + +N: Howard Hinnant +D: libc++ + +N: Justin Holewinski +E: jholewinski@nvidia.com +D: NVPTX Target (lib/Target/NVPTX/*) + +N: Andy Kaylor +E: andrew.kaylor@intel.com +D: MCJIT, RuntimeDyld and JIT event listeners + +N: Galina Kistanova +E: gkistanova@gmail.com +D: LLVM Buildbot + +N: Anton Korobeynikov +E: anton@korobeynikov.info +D: Exception handling, Windows codegen, ARM EABI + +N: Benjamin Kramer +E: benny.kra@gmail.com +D: DWARF Parser + +N: Sergei Larin +E: slarin@codeaurora.org +D: VLIW Instruction Scheduling, Packetization + +N: Chris Lattner +E: sabre@nondot.org +W: http://nondot.org/~sabre/ +D: Everything not covered by someone else + +N: Tim Northover +E: Tim.Northover@arm.com +D: AArch64 backend + +N: Jakob Olesen +D: Register allocators and TableGen + +N: Richard Osborne +E: richard@xmos.com +D: XCore Backend + +N: Chad Rosier +E: mcrosier@codeaurora.org +D: Fast-Isel + +N: Nadav Rotem +E: nrotem@apple.com +D: X86 Backend, Loop Vectorizer + +N: Daniel Sanders +E: daniel.sanders@imgtec.com +D: MIPS Backend (lib/Target/Mips/*) + +N: Richard Sandiford +E: rsandifo@linux.vnet.ibm.com +D: SystemZ Backend + +N: Duncan Sands +E: baldrick@free.fr +D: DragonEgg + +N: Kostya Serebryany +E: kcc@google.com +D: AddressSanitizer, ThreadSanitizer (LLVM parts) + +N: Michael Spencer +E: bigcheesegs@gmail.com +D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size + +N: Tom Stellard +E: thomas.stellard@amd.com +E: mesa-dev@lists.freedesktop.org +D: R600 Backend + +N: Evgeniy Stepanov +E: eugenis@google.com +D: MemorySanitizer (LLVM part) + +N: Andrew Trick +E: atrick@apple.com +D: IndVar Simplify, Loop Strength Reduction, Instruction Scheduling + +N: Bill Wendling +E: isanbard@gmail.com +D: libLTO, IR Linker + +N: Peter Zotov +E: whitequark@whitequark.org +D: OCaml bindings diff --git a/CREDITS.TXT b/CREDITS.TXT new file mode 100644 index 00000000..3c1dcb07 --- /dev/null +++ b/CREDITS.TXT @@ -0,0 +1,445 @@ +This file is a partial list of people who have contributed to the LLVM +project. If you have contributed a patch or made some other contribution to +LLVM, please submit a patch to this file to add yourself, and it will be +done! + +The list is sorted by surname and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), web-address +(W), PGP key ID and fingerprint (P), description (D), snail-mail address +(S), and (I) IRC handle. + + +N: Vikram Adve +E: vadve@cs.uiuc.edu +W: http://www.cs.uiuc.edu/~vadve/ +D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM + +N: Owen Anderson +E: resistor@mac.com +D: LCSSA pass and related LoopUnswitch work +D: GVNPRE pass, DataLayout refactoring, random improvements + +N: Henrik Bach +D: MingW Win32 API portability layer + +N: Aaron Ballman +E: aaron@aaronballman.com +D: __declspec attributes, Windows support, general bug fixing + +N: Nate Begeman +E: natebegeman@mac.com +D: PowerPC backend developer +D: Target-independent code generator and analysis improvements + +N: Daniel Berlin +E: dberlin@dberlin.org +D: ET-Forest implementation. +D: Sparse bitmap + +N: David Blaikie +E: dblaikie@gmail.com +D: General bug fixing/fit & finish, mostly in Clang + +N: Neil Booth +E: neil@daikokuya.co.uk +D: APFloat implementation. + +N: Misha Brukman +E: brukman+llvm@uiuc.edu +W: http://misha.brukman.net +D: Portions of X86 and Sparc JIT compilers, PowerPC backend +D: Incremental bitcode loader + +N: Cameron Buschardt +E: buschard@uiuc.edu +D: The `mem2reg' pass - promotes values stored in memory to registers + +N: Brendon Cahoon +E: bcahoon@codeaurora.org +D: Loop unrolling with run-time trip counts. + +N: Chandler Carruth +E: chandlerc@gmail.com +E: chandlerc@google.com +D: Hashing algorithms and interfaces +D: Inline cost analysis +D: Machine block placement pass +D: SROA + +N: Casey Carter +E: ccarter@uiuc.edu +D: Fixes to the Reassociation pass, various improvement patches + +N: Evan Cheng +E: evan.cheng@apple.com +D: ARM and X86 backends +D: Instruction scheduler improvements +D: Register allocator improvements +D: Loop optimizer improvements +D: Target-independent code generator improvements + +N: Dan Villiom Podlaski Christiansen +E: danchr@gmail.com +E: danchr@cs.au.dk +W: http://villiom.dk +D: LLVM Makefile improvements +D: Clang diagnostic & driver tweaks +S: Aarhus, Denmark + +N: Jeff Cohen +E: jeffc@jolt-lang.org +W: http://jolt-lang.org +D: Native Win32 API portability layer + +N: John T. Criswell +E: criswell@uiuc.edu +D: Original Autoconf support, documentation improvements, bug fixes + +N: Anshuman Dasgupta +E: adasgupt@codeaurora.org +D: Deterministic finite automaton based infrastructure for VLIW packetization + +N: Stefanus Du Toit +E: stefanus.du.toit@intel.com +D: Bug fixes and minor improvements + +N: Rafael Avila de Espindola +E: rafael.espindola@gmail.com +D: The ARM backend + +N: Alkis Evlogimenos +E: alkis@evlogimenos.com +D: Linear scan register allocator, many codegen improvements, Java frontend + +N: Hal Finkel +E: hfinkel@anl.gov +D: Basic-block autovectorization, PowerPC backend improvements + +N: Ryan Flynn +E: pizza@parseerror.com +D: Miscellaneous bug fixes + +N: Brian Gaeke +E: gaeke@uiuc.edu +W: http://www.students.uiuc.edu/~gaeke/ +D: Portions of X86 static and JIT compilers; initial SparcV8 backend +D: Dynamic trace optimizer +D: FreeBSD/X86 compatibility fixes, the llvm-nm tool + +N: Nicolas Geoffray +E: nicolas.geoffray@lip6.fr +W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/ +D: PPC backend fixes for Linux + +N: Louis Gerbarg +D: Portions of the PowerPC backend + +N: Saem Ghani +E: saemghani@gmail.com +D: Callgraph class cleanups + +N: Mikhail Glushenkov +E: foldr@codedgers.com +D: Author of llvmc2 + +N: Dan Gohman +E: dan433584@gmail.com +D: Miscellaneous bug fixes + +N: David Goodwin +E: david@goodwinz.net +D: Thumb-2 code generator + +N: David Greene +E: greened@obbligato.org +D: Miscellaneous bug fixes +D: Register allocation refactoring + +N: Gabor Greif +E: ggreif@gmail.com +D: Improvements for space efficiency + +N: James Grosbach +E: grosbach@apple.com +D: SjLj exception handling support +D: General fixes and improvements for the ARM back-end +D: MCJIT +D: ARM integrated assembler and assembly parser + +N: Lang Hames +E: lhames@gmail.com +D: PBQP-based register allocator + +N: Gordon Henriksen +E: gordonhenriksen@mac.com +D: Pluggable GC support +D: C interface +D: Ocaml bindings + +N: Raul Fernandes Herbster +E: raul@dsc.ufcg.edu.br +D: JIT support for ARM + +N: Paolo Invernizzi +E: arathorn@fastwebnet.it +D: Visual C++ compatibility fixes + +N: Patrick Jenkins +E: patjenk@wam.umd.edu +D: Nightly Tester + +N: Dale Johannesen +E: dalej@apple.com +D: ARM constant islands improvements +D: Tail merging improvements +D: Rewrite X87 back end +D: Use APFloat for floating point constants widely throughout compiler +D: Implement X87 long double + +N: Brad Jones +E: kungfoomaster@nondot.org +D: Support for packed types + +N: Rod Kay +E: rkay@auroraux.org +D: Author of LLVM Ada bindings + +N: Eric Kidd +W: http://randomhacks.net/ +D: llvm-config script + +N: Anton Korobeynikov +E: asl@math.spbu.ru +D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv. +D: x86/linux PIC codegen, aliases, regparm/visibility attributes +D: Switch lowering refactoring + +N: Sumant Kowshik +E: kowshik@uiuc.edu +D: Author of the original C backend + +N: Benjamin Kramer +E: benny.kra@gmail.com +D: Miscellaneous bug fixes + +N: Sundeep Kushwaha +E: sundeepk@codeaurora.org +D: Implemented DFA-based target independent VLIW packetizer + +N: Christopher Lamb +E: christopher.lamb@gmail.com +D: aligned load/store support, parts of noalias and restrict support +D: vreg subreg infrastructure, X86 codegen improvements based on subregs +D: address spaces + +N: Jim Laskey +E: jlaskey@apple.com +D: Improvements to the PPC backend, instruction scheduling +D: Debug and Dwarf implementation +D: Auto upgrade mangler +D: llvm-gcc4 svn wrangler + +N: Chris Lattner +E: sabre@nondot.org +W: http://nondot.org/~sabre/ +D: Primary architect of LLVM + +N: Tanya Lattner (Tanya Brethour) +E: tonic@nondot.org +W: http://nondot.org/~tonic/ +D: The initial llvm-ar tool, converted regression testsuite to dejagnu +D: Modulo scheduling in the SparcV9 backend +D: Release manager (1.7+) + +N: Sylvestre Ledru +E: sylvestre@debian.org +W: http://sylvestre.ledru.info/ +W: http://llvm.org/apt/ +D: Debian and Ubuntu packaging +D: Continous integration with jenkins + +N: Andrew Lenharth +E: alenhar2@cs.uiuc.edu +W: http://www.lenharth.org/~andrewl/ +D: Alpha backend +D: Sampling based profiling + +N: Nick Lewycky +E: nicholas@mxc.ca +D: PredicateSimplifier pass + +N: Tony Linthicum, et. al. +E: tlinth@codeaurora.org +D: Backend for Qualcomm's Hexagon VLIW processor. + +N: Bruno Cardoso Lopes +E: bruno.cardoso@gmail.com +W: http://www.brunocardoso.org +D: The Mips backend + +N: Duraid Madina +E: duraid@octopus.com.au +W: http://kinoko.c.u-tokyo.ac.jp/~duraid/ +D: IA64 backend, BigBlock register allocator + +N: John McCall +E: rjmccall@apple.com +D: Clang semantic analysis and IR generation + +N: Michael McCracken +E: michael.mccracken@gmail.com +D: Line number support for llvmgcc + +N: Vladimir Merzliakov +E: wanderer@rsu.ru +D: Test suite fixes for FreeBSD + +N: Scott Michel +E: scottm@aero.org +D: Added STI Cell SPU backend. + +N: Kai Nacke +E: kai@redstar.de +D: Support for implicit TLS model used with MS VC runtime +D: Dumping of Win64 EH structures + +N: Takumi Nakamura +E: geek4civic@gmail.com +E: chapuni@hf.rim.or.jp +D: Cygwin and MinGW support. +D: Win32 tweaks. +S: Yokohama, Japan + +N: Edward O'Callaghan +E: eocallaghan@auroraux.org +W: http://www.auroraux.org +D: Add Clang support with various other improvements to utils/NewNightlyTest.pl +D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings +D: and error clean ups. + +N: Morten Ofstad +E: morten@hue.no +D: Visual C++ compatibility fixes + +N: Jakob Stoklund Olesen +E: stoklund@2pi.dk +D: Machine code verifier +D: Blackfin backend +D: Fast register allocator +D: Greedy register allocator + +N: Richard Osborne +E: richard@xmos.com +D: XCore backend + +N: Devang Patel +E: dpatel@apple.com +D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate +D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements +D: Optimizer improvements, Loop Index Split + +N: Wesley Peck +E: peckw@wesleypeck.com +W: http://wesleypeck.com/ +D: MicroBlaze backend + +N: Francois Pichet +E: pichet2000@gmail.com +D: MSVC support + +N: Vladimir Prus +W: http://vladimir_prus.blogspot.com +E: ghost@cs.msu.su +D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass + +N: Kalle Raiskila +E: kalle.rasikila@nokia.com +D: Some bugfixes to CellSPU + +N: Xerxes Ranby +E: xerxes@zafena.se +D: Cmake dependency chain and various bug fixes + +N: Alex Rosenberg +E: alexr@leftfield.org +I: arosenberg +D: ARM calling conventions rewrite, hard float support + +N: Chad Rosier +E: mcrosier@codeaurora.org +D: ARM fast-isel improvements +D: Performance monitoring + +N: Nadav Rotem +E: nrotem@apple.com +D: X86 code generation improvements, Loop Vectorizer. + +N: Roman Samoilov +E: roman@codedgers.com +D: MSIL backend + +N: Duncan Sands +E: baldrick@free.fr +I: baldrick +D: Ada support in llvm-gcc +D: Dragonegg plugin +D: Exception handling improvements +D: Type legalizer rewrite + +N: Ruchira Sasanka +E: sasanka@uiuc.edu +D: Graph coloring register allocator for the Sparc64 backend + +N: Arnold Schwaighofer +E: arnold.schwaighofer@gmail.com +D: Tail call optimization for the x86 backend + +N: Shantonu Sen +E: ssen@apple.com +D: Miscellaneous bug fixes + +N: Anand Shukla +E: ashukla@cs.uiuc.edu +D: The `paths' pass + +N: Michael J. Spencer +E: bigcheesegs@gmail.com +D: Shepherding Windows COFF support into MC. +D: Lots of Windows stuff. + +N: Reid Spencer +E: rspencer@reidspencer.com +W: http://reidspencer.com/ +D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid + +N: Alp Toker +E: alp@nuanti.com +W: http://atoker.com/ +D: C++ frontend next generation standards implementation + +N: Craig Topper +E: craig.topper@gmail.com +D: X86 codegen and disassembler improvements. AVX2 support. + +N: Edwin Torok +E: edwintorok@gmail.com +D: Miscellaneous bug fixes + +N: Adam Treat +E: manyoso@yahoo.com +D: C++ bugs filed, and C++ front-end bug fixes. + +N: Lauro Ramos Venancio +E: lauro.venancio@indt.org.br +D: ARM backend improvements +D: Thread Local Storage implementation + +N: Bill Wendling +I: wendling +E: isanbard@gmail.com +D: Release manager, IR Linker, LTO +D: Bunches of stuff + +N: Bob Wilson +E: bob.wilson@acm.org +D: Advanced SIMD (NEON) support in the ARM backend. diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 00000000..66d6647f --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,71 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +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: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +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 +CONTRIBUTORS 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 WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Autoconf llvm/autoconf + llvm/projects/ModuleMaker/autoconf + llvm/projects/sample/autoconf +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} +ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h diff --git a/LLVMBuild.txt b/LLVMBuild.txt new file mode 100644 index 00000000..9cee3030 --- /dev/null +++ b/LLVMBuild.txt @@ -0,0 +1,24 @@ +;===- ./LLVMBuild.txt ------------------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[common] +subdirectories = bindings docs examples lib projects tools utils + +[component_0] +type = Group +name = Miscellaneous +parent = $ROOT diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..e3672b76 --- /dev/null +++ b/Makefile @@ -0,0 +1,285 @@ +#===- ./Makefile -------------------------------------------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +LEVEL := . + +# Top-Level LLVM Build Stages: +# 1. Build lib/Support and lib/TableGen, which are used by utils (tblgen). +# 2. Build utils, which is used by IR. +# 3. Build IR, which builds the Intrinsics.inc file used by libs. +# 4. Build libs, which are needed by llvm-config. +# 5. Build llvm-config, which determines inter-lib dependencies for tools. +# 6. Build tools and docs. +# +# When cross-compiling, there are some things (tablegen) that need to +# be build for the build system first. + +# If "RC_ProjectName" exists in the environment, and its value is +# "llvmCore", then this is an "Apple-style" build; search for +# "Apple-style" in the comments for more info. Anything else is a +# normal build. +ifneq ($(findstring llvmCore, $(RC_ProjectName)),llvmCore) # Normal build (not "Apple-style"). + +ifeq ($(BUILD_DIRS_ONLY),1) + DIRS := lib/Support lib/TableGen utils tools/llvm-config + OPTIONAL_DIRS := tools/clang/utils/TableGen +else + DIRS := lib/Support lib/TableGen utils lib/IR lib tools/llvm-shlib \ + tools/llvm-config tools docs unittests + OPTIONAL_DIRS := projects bindings +endif + +ifeq ($(BUILD_EXAMPLES),1) + OPTIONAL_DIRS += examples +endif + +EXTRA_DIST := test unittests llvm.spec include win32 Xcode + +include $(LEVEL)/Makefile.config + +ifneq ($(ENABLE_SHARED),1) + DIRS := $(filter-out tools/llvm-shlib, $(DIRS)) +endif + +ifneq ($(ENABLE_DOCS),1) + DIRS := $(filter-out docs, $(DIRS)) +endif + +ifeq ($(MAKECMDGOALS),libs-only) + DIRS := $(filter-out tools docs, $(DIRS)) + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),install-libs) + DIRS := $(filter-out tools docs, $(DIRS)) + OPTIONAL_DIRS := $(filter bindings, $(OPTIONAL_DIRS)) +endif + +ifeq ($(MAKECMDGOALS),tools-only) + DIRS := $(filter-out docs, $(DIRS)) + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),install-clang) + DIRS := tools/clang/tools/driver tools/clang/lib/Headers \ + tools/clang/tools/libclang \ + tools/clang/tools/c-index-test \ + tools/clang/include/clang-c \ + tools/clang/runtime tools/clang/docs \ + tools/lto + OPTIONAL_DIRS := + NO_INSTALL = 1 +endif + +ifeq ($(MAKECMDGOALS),clang-only) + DIRS := $(filter-out tools docs unittests, $(DIRS)) \ + tools/clang tools/lto + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),unittests) + DIRS := $(filter-out tools docs, $(DIRS)) utils unittests + OPTIONAL_DIRS := +endif + +# Use NO_INSTALL define of the Makefile of each directory for deciding +# if the directory is installed or not +ifeq ($(MAKECMDGOALS),install) + OPTIONAL_DIRS := $(filter bindings, $(OPTIONAL_DIRS)) +endif + +# Don't build unittests when ONLY_TOOLS is set. +ifneq ($(ONLY_TOOLS),) + DIRS := $(filter-out unittests, $(DIRS)) +endif + +# If we're cross-compiling, build the build-hosted tools first +ifeq ($(LLVM_CROSS_COMPILING),1) +all:: cross-compile-build-tools + +clean:: + $(Verb) rm -rf BuildTools + +cross-compile-build-tools: + $(Verb) if [ ! -f BuildTools/Makefile ]; then \ + $(MKDIR) BuildTools; \ + cd BuildTools ; \ + unset CFLAGS ; \ + unset CXXFLAGS ; \ + unset SDKROOT ; \ + unset UNIVERSAL_SDK_PATH ; \ + $(PROJ_SRC_DIR)/configure --build=$(BUILD_TRIPLE) \ + --host=$(BUILD_TRIPLE) --target=$(BUILD_TRIPLE) \ + --disable-polly ; \ + cd .. ; \ + fi; \ + ($(MAKE) -C BuildTools \ + BUILD_DIRS_ONLY=1 \ + UNIVERSAL= \ + UNIVERSAL_SDK_PATH= \ + SDKROOT= \ + TARGET_NATIVE_ARCH="$(TARGET_NATIVE_ARCH)" \ + TARGETS_TO_BUILD="$(TARGETS_TO_BUILD)" \ + ENABLE_OPTIMIZED=$(ENABLE_OPTIMIZED) \ + ENABLE_PROFILING=$(ENABLE_PROFILING) \ + ENABLE_COVERAGE=$(ENABLE_COVERAGE) \ + DISABLE_ASSERTIONS=$(DISABLE_ASSERTIONS) \ + ENABLE_EXPENSIVE_CHECKS=$(ENABLE_EXPENSIVE_CHECKS) \ + ENABLE_LIBCPP=$(ENABLE_LIBCPP) \ + CFLAGS= \ + CXXFLAGS= \ + ) || exit 1; +endif + +# Include the main makefile machinery. +include $(LLVM_SRC_ROOT)/Makefile.rules + +# Specify options to pass to configure script when we're +# running the dist-check target +DIST_CHECK_CONFIG_OPTIONS = --with-llvmgccdir=$(LLVMGCCDIR) + +.PHONY: debug-opt-prof +debug-opt-prof: + $(Echo) Building Debug Version + $(Verb) $(MAKE) + $(Echo) + $(Echo) Building Optimized Version + $(Echo) + $(Verb) $(MAKE) ENABLE_OPTIMIZED=1 + $(Echo) + $(Echo) Building Profiling Version + $(Echo) + $(Verb) $(MAKE) ENABLE_PROFILING=1 + +dist-hook:: + $(Echo) Eliminating files constructed by configure + $(Verb) $(RM) -f \ + $(TopDistDir)/include/llvm/Config/config.h \ + $(TopDistDir)/include/llvm/Support/DataTypes.h + +clang-only: all +tools-only: all +libs-only: all +install-clang: install +install-libs: install + +# If SHOW_DIAGNOSTICS is enabled, clear the diagnostics file first. +ifeq ($(SHOW_DIAGNOSTICS),1) +clean-diagnostics: + $(Verb) rm -f $(LLVM_OBJ_ROOT)/$(BuildMode)/diags +.PHONY: clean-diagnostics + +all-local:: clean-diagnostics +endif + +#------------------------------------------------------------------------ +# Make sure the generated files are up-to-date. This must be kept in +# sync with the AC_CONFIG_HEADER and AC_CONFIG_FILE invocations in +# autoconf/configure.ac. +# Note that Makefile.config is covered by its own separate rule +# in Makefile.rules where it can be reused by sub-projects. +#------------------------------------------------------------------------ +FilesToConfig := \ + bindings/ocaml/llvm/META.llvm \ + docs/doxygen.cfg \ + llvm.spec \ + include/llvm/Config/config.h \ + include/llvm/Config/llvm-config.h \ + include/llvm/Config/Targets.def \ + include/llvm/Config/AsmPrinters.def \ + include/llvm/Config/AsmParsers.def \ + include/llvm/Config/Disassemblers.def \ + include/llvm/Support/DataTypes.h +FilesToConfigPATH := $(addprefix $(LLVM_OBJ_ROOT)/,$(FilesToConfig)) + +all-local:: $(FilesToConfigPATH) +$(FilesToConfigPATH) : $(LLVM_OBJ_ROOT)/% : $(LLVM_SRC_ROOT)/%.in + $(Echo) Regenerating $* + $(Verb) cd $(LLVM_OBJ_ROOT) && $(ConfigStatusScript) $* +.PRECIOUS: $(FilesToConfigPATH) + +# NOTE: This needs to remain as the last target definition in this file so +# that it gets executed last. +ifneq ($(BUILD_DIRS_ONLY),1) +all:: + $(Echo) '*****' Completed $(BuildMode) Build +ifneq ($(ENABLE_OPTIMIZED),1) + $(Echo) '*****' Note: Debug build can be 10 times slower than an + $(Echo) '*****' optimized build. Use 'make ENABLE_OPTIMIZED=1' to + $(Echo) '*****' make an optimized build. Alternatively you can + $(Echo) '*****' configure with --enable-optimized. +ifeq ($(SHOW_DIAGNOSTICS),1) + $(Verb) if test -s $(LLVM_OBJ_ROOT)/$(BuildMode)/diags; then \ + $(LLVM_SRC_ROOT)/utils/clang-parse-diagnostics-file -a \ + $(LLVM_OBJ_ROOT)/$(BuildMode)/diags; \ + fi +endif +endif +endif + +check-llvm2cpp: + $(Verb)$(MAKE) check TESTSUITE=Feature RUNLLVM2CPP=1 + +srpm: $(LLVM_OBJ_ROOT)/llvm.spec + rpmbuild -bs $(LLVM_OBJ_ROOT)/llvm.spec + +rpm: $(LLVM_OBJ_ROOT)/llvm.spec + rpmbuild -bb --target $(TARGET_TRIPLE) $(LLVM_OBJ_ROOT)/llvm.spec + +show-footprint: + $(Verb) du -sk $(LibDir) + $(Verb) du -sk $(ToolDir) + $(Verb) du -sk $(ExmplDir) + $(Verb) du -sk $(ObjDir) + +build-for-llvm-top: + $(Verb) if test ! -f ./config.status ; then \ + ./configure --prefix="$(LLVM_TOP)/install" \ + --with-llvm-gcc="$(LLVM_TOP)/llvm-gcc" ; \ + fi + $(Verb) $(MAKE) tools-only + +SVN = svn +SVN-UPDATE-OPTIONS = +AWK = awk + +# Multiline variable defining a recursive function for finding svn repos rooted at +# a given path. svnup() requires one argument: the root to search from. +define SUB_SVN_DIRS +svnup() { + dirs=`svn status --no-ignore $$1 | awk '/^(I|\?) / {print $$2}' | LC_ALL=C xargs svn info 2>/dev/null | awk '/^Path:\ / {print $$2}'`; + if [ "$$dirs" = "" ]; then + return; + fi; + for f in $$dirs; do + echo $$f; + svnup $$f; + done +} +endef +export SUB_SVN_DIRS + +update: + $(SVN) $(SVN-UPDATE-OPTIONS) update $(LLVM_SRC_ROOT) + @eval $$SUB_SVN_DIRS; $(SVN) status --no-ignore $(LLVM_SRC_ROOT) | svnup $(LLVM_SRC_ROOT) | xargs $(SVN) $(SVN-UPDATE-OPTIONS) update + +happiness: update all check-all + +.PHONY: srpm rpm update happiness + +# declare all targets at this level to be serial: + +.NOTPARALLEL: + +else # Building "Apple-style." +# In an Apple-style build, once configuration is done, lines marked +# "Apple-style" are removed with sed! Please don't remove these! +# Look for the string "Apple-style" in utils/buildit/build_llvm. +include $(shell find . -name GNUmakefile) # Building "Apple-style." +endif # Building "Apple-style." diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 00000000..a157abae --- /dev/null +++ b/Makefile.common @@ -0,0 +1,69 @@ +#===-- Makefile.common - Common make rules for LLVM --------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by all of the LLVM makefiles. This file defines common +# rules to do things like compile a .cpp file or generate dependency info. +# These are platform dependent, so this is the file used to specify these +# system dependent operations. +# +# The following functionality can be set by setting incoming variables. +# The variable $(LEVEL) *must* be set: +# +# 1. LEVEL - The level of the current subdirectory from the top of the +# source directory. This level should be expressed as a path, for +# example, ../.. for two levels deep. +# +# 2. DIRS - A list of subdirectories to be built. Fake targets are set up +# so that each of the targets "all", "install", and "clean" each build +# the subdirectories before the local target. DIRS are guaranteed to be +# built in order. +# +# 3. PARALLEL_DIRS - A list of subdirectories to be built, but that may be +# built in any order. All DIRS are built in order before PARALLEL_DIRS are +# built, which are then built in any order. +# +# 4. SOURCES - If specified, this sets the source code filenames. If this +# is not set, it defaults to be all of the .cpp, .c, .y, and .l files +# in the current directory. +# +# 5. SourceDir - If specified, this specifies a directory that the source files +# are in, if they are not in the current directory. This should include a +# trailing / character. +# +# 6. LLVM_SRC_ROOT - If specified, points to the top of the LLVM source tree. +# +# 8. PROJ_SRC_DIR - The directory which contains the current set of Makefiles +# and usually the source code too (unless SourceDir is set). +# +# 9. PROJ_SRC_ROOT - The root directory of the source code being compiled. +# +# 10. PROJ_OBJ_DIR - The directory where object code should be placed. +# +# 11. PROJ_OBJ_ROOT - The root directory for where object code should be +# placed. +# +# For building, +# LLVM, LLVM_SRC_ROOT = PROJ_SRC_ROOT +# +#===-----------------------------------------------------------------------==== + +# +# Configuration file to set paths specific to local installation of LLVM +# +ifndef LLVM_OBJ_ROOT +include $(LEVEL)/Makefile.config +else +include $(LLVM_OBJ_ROOT)/Makefile.config +endif + +# +# Include all of the build rules used for making LLVM +# +include $(LLVM_SRC_ROOT)/Makefile.rules + diff --git a/Makefile.config.in b/Makefile.config.in new file mode 100644 index 00000000..00c6d965 --- /dev/null +++ b/Makefile.config.in @@ -0,0 +1,412 @@ +#===-- Makefile.config - Local configuration for LLVM ------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by Makefile.common. It defines paths and other +# values specific to a particular installation of LLVM. +# +#===------------------------------------------------------------------------===# + +# Define LLVM specific info and directories based on the autoconf variables +LLVMPackageName := @PACKAGE_TARNAME@ +LLVMVersion := @PACKAGE_VERSION@ +LLVM_VERSION_MAJOR := @LLVM_VERSION_MAJOR@ +LLVM_VERSION_MINOR := @LLVM_VERSION_MINOR@ +LLVM_VERSION_PATCH := @LLVM_VERSION_PATCH@ +LLVM_VERSION_SUFFIX := @LLVM_VERSION_SUFFIX@ +LLVM_CONFIGTIME := @LLVM_CONFIGTIME@ + +########################################################################### +# Directory Configuration +# This section of the Makefile determines what is where. To be +# specific, there are several locations that need to be defined: +# +# o LLVM_SRC_ROOT : The root directory of the LLVM source code. +# o LLVM_OBJ_ROOT : The root directory containing the built LLVM code. +# +# o PROJ_SRC_DIR : The directory containing the code to build. +# o PROJ_SRC_ROOT : The root directory of the code to build. +# +# o PROJ_OBJ_DIR : The directory in which compiled code will be placed. +# o PROJ_OBJ_ROOT : The root directory in which compiled code is placed. +# +########################################################################### + +PWD := @BINPWD@ +# Set the project name to LLVM if its not defined +ifndef PROJECT_NAME +PROJECT_NAME := $(LLVMPackageName) +endif + +# The macro below is expanded when 'realpath' is not built-in. +# Built-in 'realpath' is available on GNU Make 3.81. +realpath = $(shell cd $(1); $(PWD)) + +PROJ_OBJ_DIR := $(call realpath, .) +PROJ_OBJ_ROOT := $(call realpath, $(PROJ_OBJ_DIR)/$(LEVEL)) + +CLANG_SRC_ROOT := @CLANG_SRC_ROOT@ + +ifeq ($(PROJECT_NAME),$(LLVMPackageName)) +LLVM_SRC_ROOT := $(call realpath, @abs_top_srcdir@) +LLVM_OBJ_ROOT := $(call realpath, @abs_top_builddir@) +PROJ_SRC_ROOT := $(LLVM_SRC_ROOT) +PROJ_SRC_DIR := $(LLVM_SRC_ROOT)$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR)) + +ifneq ($(CLANG_SRC_ROOT),) + CLANG_SRC_ROOT:= $(call realpath, $(CLANG_SRC_ROOT)) + PROJ_SRC_DIR := $(patsubst $(LLVM_SRC_ROOT)/tools/clang%,$(CLANG_SRC_ROOT)%,$(PROJ_SRC_DIR)) +endif + +prefix := @prefix@ +PROJ_prefix := $(prefix) +program_prefix := @program_prefix@ +PROJ_VERSION := $(LLVMVersion) +else +ifndef PROJ_SRC_ROOT +$(error Projects must define PROJ_SRC_ROOT) +endif +ifndef PROJ_OBJ_ROOT +$(error Projects must define PROJ_OBJ_ROOT) +endif +ifndef PROJ_INSTALL_ROOT +$(error Projects must define PROJ_INSTALL_ROOT) +endif +ifndef LLVM_SRC_ROOT +$(error Projects must define LLVM_SRC_ROOT) +endif +ifndef LLVM_OBJ_ROOT +$(error Projects must define LLVM_OBJ_ROOT) +endif +PROJ_SRC_DIR := $(call realpath, $(PROJ_SRC_ROOT)/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR))) +prefix := $(PROJ_INSTALL_ROOT) +PROJ_prefix := $(prefix) +ifndef PROJ_VERSION +PROJ_VERSION := 1.0 +endif +endif + +INTERNAL_PREFIX := @INTERNAL_PREFIX@ +ifneq ($(INTERNAL_PREFIX),) +PROJ_internal_prefix := $(INTERNAL_PREFIX) +else +PROJ_internal_prefix := $(prefix) +endif + +PROJ_bindir := $(PROJ_prefix)/bin +PROJ_libdir := $(PROJ_prefix)/lib +PROJ_datadir := $(PROJ_prefix)/share +PROJ_docsdir := $(PROJ_prefix)/docs/llvm +PROJ_etcdir := $(PROJ_prefix)/etc/llvm +PROJ_includedir := $(PROJ_prefix)/include +PROJ_infodir := $(PROJ_prefix)/info +PROJ_mandir := $(PROJ_prefix)/share/man + +# Determine if we're on a unix type operating system +LLVM_ON_UNIX:=@LLVM_ON_UNIX@ +LLVM_ON_WIN32:=@LLVM_ON_WIN32@ + +# Host operating system for which LLVM will be run. +OS=@OS@ +HOST_OS=@HOST_OS@ +# Target operating system for which LLVM will compile for. +TARGET_OS=@TARGET_OS@ + +# Host hardware architecture +HOST_ARCH=@HOST_ARCH@ +# Target hardware architecture +ARCH=@ARCH@ +TARGET_NATIVE_ARCH := $(ARCH) + +# Indicates, whether we're cross-compiling LLVM or not +LLVM_CROSS_COMPILING=@LLVM_CROSS_COMPILING@ + +# Executable file extension for build platform (mainly for +# tablegen call if we're cross-compiling). +BUILD_EXEEXT=@BUILD_EXEEXT@ + +# Compilers for the build platflorm (mainly for tablegen +# call if we're cross-compiling). +BUILD_CC=@BUILD_CC@ +BUILD_CXX=@BUILD_CXX@ + +# Triple for configuring build tools when cross-compiling +BUILD_TRIPLE=@build@ + +# Target triple (cpu-vendor-os) which LLVM is compiled for +HOST_TRIPLE=@host@ + +# Target triple (cpu-vendor-os) for which we should generate code +TARGET_TRIPLE=@target@ + +# Extra options to compile LLVM with +EXTRA_OPTIONS=@EXTRA_OPTIONS@ + +# Extra options to link LLVM with +EXTRA_LD_OPTIONS=@EXTRA_LD_OPTIONS@ + +# Endian-ness of the target +ENDIAN=@ENDIAN@ + +# Path to the C++ compiler to use. This is an optional setting, which defaults +# to whatever your gmake defaults to. +CXX = @CXX@ + +# Path to the CC binary, which use used by testcases for native builds. +CC := @CC@ + +# C/C++ preprocessor flags. +CPPFLAGS += @CPPFLAGS@ + +# C compiler flags. +CFLAGS += @CFLAGS@ + +# C++ compiler flags. +CXXFLAGS += @CXXFLAGS@ + +# Linker flags. +LDFLAGS += @LDFLAGS@ + +# Path to the library archiver program. +AR_PATH = @AR@ +AR = @AR@ + +# Path to the nm program +NM_PATH = @NM@ + +# The pathnames of the programs we require to build +CMP := @CMP@ +CP := @CP@ +DATE := @DATE@ +FIND := @FIND@ +GREP := @GREP@ +INSTALL := @INSTALL@ +MKDIR := $(LLVM_SRC_ROOT)/autoconf/mkinstalldirs +MV := @MV@ +RANLIB := @RANLIB@ +RM := @RM@ +SED := @SED@ +TAR := @TAR@ +PYTHON := @PYTHON@ + +# Paths to miscellaneous programs we hope are present but might not be +BZIP2 := @BZIP2@ +CAT := @CAT@ +DOT := @DOT@ +DOXYGEN := @DOXYGEN@ +GROFF := @GROFF@ +GZIPBIN := @GZIPBIN@ +OCAMLC := @OCAMLC@ +OCAMLOPT := @OCAMLOPT@ +OCAMLDEP := @OCAMLDEP@ +OCAMLDOC := @OCAMLDOC@ +GAS := @GAS@ +POD2HTML := @POD2HTML@ +POD2MAN := @POD2MAN@ +PDFROFF := @PDFROFF@ +ZIP := @ZIP@ + +HAVE_PTHREAD := @HAVE_PTHREAD@ + +LIBS := @LIBS@ + +# Targets that we should build +TARGETS_TO_BUILD=@TARGETS_TO_BUILD@ + +# Path to directory where object files should be stored during a build. +# Set OBJ_ROOT to "." if you do not want to use a separate place for +# object files. +OBJ_ROOT := . + +# What to pass as rpath flag to g++ +RPATH := @RPATH@ + +# What to pass as -rdynamic flag to g++ +RDYNAMIC := @RDYNAMIC@ + +# These are options that can either be enabled here, or can be enabled on the +# make command line (ie, make ENABLE_PROFILING=1): + +# When ENABLE_LIBCPP is enabled, LLVM uses libc++ by default to build. +#ENABLE_LIBCPP = 0 +ENABLE_LIBCPP = @ENABLE_LIBCPP@ + +# When ENABLE_CXX11 is enabled, LLVM uses c++11 mode by default to build. +ENABLE_CXX11 = @ENABLE_CXX11@ + +# When ENABLE_SPLIT_DWARF is enabled, LLVM uses -gfission to build in debug mode. +ENABLE_SPLIT_DWARF = @ENABLE_SPLIT_DWARF@ + +# When ENABLE_CLANG_ARCMT is enabled, clang will have ARCMigrationTool. +ENABLE_CLANG_ARCMT = @ENABLE_CLANG_ARCMT@ + +# When ENABLE_CLANG_REWRITER is enabled, clang will have Rewriter. +ENABLE_CLANG_REWRITER = @ENABLE_CLANG_REWRITER@ + +# When ENABLE_CLANG_STATIC_ANALYZER is enabled, clang will have StaticAnalyzer. +ENABLE_CLANG_STATIC_ANALYZER = @ENABLE_CLANG_STATIC_ANALYZER@ + +# When ENABLE_WERROR is enabled, we'll pass -Werror on the command line +ENABLE_WERROR = @ENABLE_WERROR@ + +# When ENABLE_OPTIMIZED is enabled, LLVM code is optimized and output is put +# into the "Release" directories. Otherwise, LLVM code is not optimized and +# output is put in the "Debug" directories. +#ENABLE_OPTIMIZED = 1 +@ENABLE_OPTIMIZED@ + +# When ENABLE_PROFILING is enabled, profile instrumentation is done +# and output is put into the "+Profile" directories, where +# is either Debug or Release depending on how other build +# flags are set. Otherwise, output is put in the +# directories. +#ENABLE_PROFILING = 1 +@ENABLE_PROFILING@ + +# When DISABLE_ASSERTIONS is enabled, builds of all of the LLVM code will +# exclude assertion checks, otherwise they are included. +#DISABLE_ASSERTIONS = 1 +@DISABLE_ASSERTIONS@ + +# When ENABLE_EXPENSIVE_CHECKS is enabled, builds of all of the LLVM +# code will include expensive checks, otherwise they are excluded. +#ENABLE_EXPENSIVE_CHECKS = 0 +@ENABLE_EXPENSIVE_CHECKS@ + +# When DEBUG_RUNTIME is enabled, the runtime libraries will retain debug +# symbols. +#DEBUG_RUNTIME = 1 +@DEBUG_RUNTIME@ + +# When DEBUG_SYMBOLS is enabled, the compiler libraries will retain debug +# symbols. +#DEBUG_SYMBOLS = 1 +@DEBUG_SYMBOLS@ + +# When KEEP_SYMBOLS is enabled, installed executables will never have their +# symbols stripped. +#KEEP_SYMBOLS = 1 +@KEEP_SYMBOLS@ + +# The compiler flags to use for optimized builds. +OPTIMIZE_OPTION := @OPTIMIZE_OPTION@ + +# When ENABLE_PROFILING is enabled, the llvm source base is built with profile +# information to allow gprof to be used to get execution frequencies. +#ENABLE_PROFILING = 1 + +# When ENABLE_DOCS is disabled, docs/ will not be built. +ENABLE_DOCS = @ENABLE_DOCS@ + +# When ENABLE_DOXYGEN is enabled, the doxygen documentation will be built +ENABLE_DOXYGEN = @ENABLE_DOXYGEN@ + +# Do we want to enable threads? +ENABLE_THREADS := @LLVM_ENABLE_THREADS@ + +# Do we want to enable zlib? +ENABLE_ZLIB := @LLVM_ENABLE_ZLIB@ + +# Do we want to build with position independent code? +ENABLE_PIC := @ENABLE_PIC@ + +# Do we want to build a shared library and link the tools with it? +ENABLE_SHARED := @ENABLE_SHARED@ + +# Do we want to link the stdc++ into a shared library? (Cygming) +ENABLE_EMBED_STDCXX := @ENABLE_EMBED_STDCXX@ + +# Use -fvisibility-inlines-hidden? +ENABLE_VISIBILITY_INLINES_HIDDEN := @ENABLE_VISIBILITY_INLINES_HIDDEN@ + +# Do we want to allow timestamping information into builds? +ENABLE_TIMESTAMPS := @ENABLE_TIMESTAMPS@ + +# This option tells the Makefiles to produce verbose output. +# It essentially prints the commands that make is executing +#VERBOSE = 1 + +# Enable JIT for this platform +TARGET_HAS_JIT = @TARGET_HAS_JIT@ + +# Environment variable to set to change the runtime shared library search path. +SHLIBPATH_VAR = @SHLIBPATH_VAR@ + +# Shared library extension for host platform. +SHLIBEXT = @SHLIBEXT@ + +# Executable file extension for host platform. +EXEEXT = @EXEEXT@ + +# Things we just assume are "there" +ECHO := echo + +# Get the options for causing archives to link all their content instead of +# just missing symbols, and the inverse of that. This is used for certain LLVM +# tools that permit loadable modules. It ensures that the LLVM symbols will be +# available to those loadable modules. +LINKALL := @LINKALL@ +NOLINKALL := @NOLINKALL@ + +# Get the value of HUGE_VAL_SANITY which will be either "yes" or "no" depending +# on the check. +HUGE_VAL_SANITY = @HUGE_VAL_SANITY@ + +# Bindings that we should build +BINDINGS_TO_BUILD := @BINDINGS_TO_BUILD@ +ALL_BINDINGS := @ALL_BINDINGS@ +OCAML_LIBDIR := @OCAML_LIBDIR@ + +# When compiling under Mingw/Cygwin, executables such as tblgen +# expect Windows paths, whereas the build system uses Unix paths. +# The function SYSPATH transforms Unix paths into Windows paths. +ifneq (,$(findstring -mno-cygwin, $(CXX))) + SYSPATH = $(shell echo $(1) | cygpath -m -f -) +else + SYSPATH = $(1) +endif + +# Location of the plugin header file for gold. +BINUTILS_INCDIR := @BINUTILS_INCDIR@ + +# Optional flags supported by the compiler +# -Wno-missing-field-initializers +NO_MISSING_FIELD_INITIALIZERS = @NO_MISSING_FIELD_INITIALIZERS@ +# -Wno-variadic-macros +NO_VARIADIC_MACROS = @NO_VARIADIC_MACROS@ +# -Wcovered-switch-default +COVERED_SWITCH_DEFAULT = @COVERED_SWITCH_DEFAULT@ +# -Wno-uninitialized +NO_UNINITIALIZED = @NO_UNINITIALIZED@ +# -Wno-maybe-uninitialized +NO_MAYBE_UNINITIALIZED = @NO_MAYBE_UNINITIALIZED@ + +# Was polly found in tools/polly? +LLVM_HAS_POLLY = @LLVM_HAS_POLLY@ +# Flags supported by the linker. +# bfd ld / gold --version-script=file +HAVE_LINK_VERSION_SCRIPT = @HAVE_LINK_VERSION_SCRIPT@ + +# Flags to control using libxml2 +LIBXML2_LIBS := @LIBXML2_LIBS@ +LIBXML2_INC := @LIBXML2_INC@ + +# Flags to control building support for Intel JIT Events API +USE_INTEL_JITEVENTS := @USE_INTEL_JITEVENTS@ +INTEL_JITEVENTS_INCDIR := @INTEL_JITEVENTS_INCDIR@ +INTEL_JITEVENTS_LIBDIR := @INTEL_JITEVENTS_LIBDIR@ + +# Flags to control building support for OProfile JIT API +USE_OPROFILE := @USE_OPROFILE@ + +ifeq ($(USE_INTEL_JITEVENTS), 1) + OPTIONAL_COMPONENTS += IntelJITEvents +endif +ifeq ($(USE_OPROFILE), 1) + OPTIONAL_COMPONENTS += OProfileJIT +endif diff --git a/Makefile.rules b/Makefile.rules new file mode 100644 index 00000000..210abdaf --- /dev/null +++ b/Makefile.rules @@ -0,0 +1,2122 @@ +#===-- Makefile.rules - Common make rules for LLVM ---------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by all of the LLVM makefiles. For details on how to use +# it properly, please see the document MakefileGuide.html in the docs directory. +# +#===-----------------------------------------------------------------------====# + +################################################################################ +# TARGETS: Define standard targets that can be invoked +################################################################################ + +#-------------------------------------------------------------------- +# Define the various target sets +#-------------------------------------------------------------------- +RecursiveTargets := all clean clean-all install uninstall install-bytecode \ + unitcheck +LocalTargets := all-local clean-local clean-all-local check-local \ + install-local printvars uninstall-local \ + install-bytecode-local +TopLevelTargets := check dist dist-check dist-clean dist-gzip dist-bzip2 \ + dist-zip unittests +UserTargets := $(RecursiveTargets) $(LocalTargets) $(TopLevelTargets) +InternalTargets := preconditions distdir dist-hook + +################################################################################ +# INITIALIZATION: Basic things the makefile needs +################################################################################ + +#-------------------------------------------------------------------- +# Set the VPATH so that we can find source files. +#-------------------------------------------------------------------- +VPATH=$(PROJ_SRC_DIR) + +#-------------------------------------------------------------------- +# Reset the list of suffixes we know how to build. +#-------------------------------------------------------------------- +.SUFFIXES: +.SUFFIXES: .c .cpp .cc .h .hpp .o .a .td .ps .dot .m .mm +.SUFFIXES: $(SHLIBEXT) $(SUFFIXES) + +#-------------------------------------------------------------------- +# Mark all of these targets as phony to avoid implicit rule search +#-------------------------------------------------------------------- +.PHONY: $(UserTargets) $(InternalTargets) + +#-------------------------------------------------------------------- +# Make sure all the user-target rules are double colon rules and +# they are defined first. +#-------------------------------------------------------------------- + +$(UserTargets):: + +#------------------------------------------------------------------------ +# LLVMBuild Integration +#------------------------------------------------------------------------ +# +# We use llvm-build to generate all the data required by the Makefile based +# build system in one swoop: +# +# - We generate a file (a Makefile fragment) in the object root which contains +# all the definitions that are required by Makefiles across the entire +# project. +# +# - We generate the library table used by llvm-config. +# +# - We generate the dependencies for the Makefile fragment, so that we will +# automatically reconfigure outselves. + +# The path to the llvm-build tool itself. +LLVMBuildTool := $(PROJ_SRC_ROOT)/utils/llvm-build/llvm-build + +# The files we are going to generate using llvm-build. +LLVMBuildMakeFrag := $(PROJ_OBJ_ROOT)/Makefile.llvmbuild +LLVMConfigLibraryDependenciesInc := \ + $(PROJ_OBJ_ROOT)/tools/llvm-config/LibraryDependencies.inc + +# This is for temporary backwards compatibility. +ifndef TARGET_NATIVE_ARCH +TARGET_NATIVE_ARCH := $(ARCH) +endif + +# The rule to create the LLVMBuild Makefile fragment as well as the llvm-config +# library table. +# +# Note that this target gets its real dependencies generated for us by +# llvm-build. +# +# We include a dependency on this Makefile to ensure that changes to the +# generation command get picked up. +$(LLVMBuildMakeFrag): $(PROJ_SRC_ROOT)/Makefile.rules \ + $(PROJ_OBJ_ROOT)/Makefile.config + $(Echo) Constructing LLVMBuild project information. + $(Verb)$(PYTHON) $(LLVMBuildTool) \ + --native-target "$(TARGET_NATIVE_ARCH)" \ + --enable-targets "$(TARGETS_TO_BUILD)" \ + --enable-optional-components "$(OPTIONAL_COMPONENTS)" \ + --write-library-table $(LLVMConfigLibraryDependenciesInc) \ + --write-make-fragment $(LLVMBuildMakeFrag) + +# For completeness, let Make know how the extra files are generated. +$(LLVMConfigLibraryDependenciesInc): $(LLVMBuildMakeFrag) + +# Include the generated Makefile fragment. +# +# We currently only include the dependencies for the fragment itself if we are +# at the top-level. Otherwise, recursive invocations would ends up doing +# substantially more redundant stat'ing. +# +# This means that we won't properly regenerate things for developers used to +# building from a subdirectory, but that is always somewhat unreliable. +ifeq ($(LEVEL),.) +LLVMBUILD_INCLUDE_DEPENDENCIES := 1 + +# Clean the generated makefile fragment at the top-level. +clean-local:: + -$(Verb) $(RM) -f $(LLVMBuildMakeFrag) +endif +-include $(LLVMBuildMakeFrag) + +################################################################################ +# PRECONDITIONS: that which must be built/checked first +################################################################################ + +SrcMakefiles := $(filter %Makefile %Makefile.tests,\ + $(wildcard $(PROJ_SRC_DIR)/Makefile*)) +ObjMakefiles := $(subst $(PROJ_SRC_DIR),$(PROJ_OBJ_DIR),$(SrcMakefiles)) +ConfigureScript := $(PROJ_SRC_ROOT)/configure +ConfigStatusScript := $(PROJ_OBJ_ROOT)/config.status +MakefileConfigIn := $(strip $(wildcard $(PROJ_SRC_ROOT)/Makefile.config.in)) +MakefileCommonIn := $(strip $(wildcard $(PROJ_SRC_ROOT)/Makefile.common.in)) +MakefileConfig := $(PROJ_OBJ_ROOT)/Makefile.config +MakefileCommon := $(PROJ_OBJ_ROOT)/Makefile.common +PreConditions := $(ConfigStatusScript) $(ObjMakefiles) +ifneq ($(MakefileCommonIn),) +PreConditions += $(MakefileCommon) +endif + +ifneq ($(MakefileConfigIn),) +PreConditions += $(MakefileConfig) +endif + +preconditions: $(PreConditions) + +#------------------------------------------------------------------------ +# Make sure the BUILT_SOURCES are built first +#------------------------------------------------------------------------ +$(filter-out clean clean-local,$(UserTargets)):: $(BUILT_SOURCES) + +clean-all-local:: +ifneq ($(strip $(BUILT_SOURCES)),) + -$(Verb) $(RM) -f $(BUILT_SOURCES) +endif + +ifneq ($(PROJ_OBJ_ROOT),$(PROJ_SRC_ROOT)) +spotless: + $(Verb) if test -x config.status ; then \ + $(EchoCmd) Wiping out $(PROJ_OBJ_ROOT) ; \ + $(MKDIR) .spotless.save ; \ + $(MV) config.status .spotless.save ; \ + $(MV) mklib .spotless.save ; \ + $(MV) projects .spotless.save ; \ + $(RM) -rf * ; \ + $(MV) .spotless.save/config.status . ; \ + $(MV) .spotless.save/mklib . ; \ + $(MV) .spotless.save/projects . ; \ + $(RM) -rf .spotless.save ; \ + $(EchoCmd) Rebuilding configuration of $(PROJ_OBJ_ROOT) ; \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) ; \ + else \ + $(EchoCmd) "make spotless" can only be run from $(PROJ_OBJ_ROOT); \ + fi +else +spotless: + $(EchoCmd) "spotless target not supported for objdir == srcdir" +endif + +$(BUILT_SOURCES) : $(ObjMakefiles) + +#------------------------------------------------------------------------ +# Make sure we're not using a stale configuration +#------------------------------------------------------------------------ +reconfigure: + $(Echo) Reconfiguring $(PROJ_OBJ_ROOT) + $(Verb) cd $(PROJ_OBJ_ROOT) && \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) + +.PRECIOUS: $(ConfigStatusScript) +$(ConfigStatusScript): $(ConfigureScript) + $(Echo) Reconfiguring with $< + $(Verb) cd $(PROJ_OBJ_ROOT) && \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) + +#------------------------------------------------------------------------ +# Make sure the configuration makefile is up to date +#------------------------------------------------------------------------ +ifneq ($(MakefileConfigIn),) +$(MakefileConfig): $(MakefileConfigIn) $(ConfigStatusScript) + $(Echo) Regenerating $@ + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ConfigStatusScript) Makefile.config +endif + +ifneq ($(MakefileCommonIn),) +$(MakefileCommon): $(MakefileCommonIn) $(ConfigStatusScript) + $(Echo) Regenerating $@ + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ConfigStatusScript) Makefile.common +endif + +#------------------------------------------------------------------------ +# If the Makefile in the source tree has been updated, copy it over into the +# build tree. But, only do this if the source and object makefiles differ +#------------------------------------------------------------------------ +ifndef PROJ_MAKEFILE +PROJ_MAKEFILE := $(PROJ_SRC_DIR)/Makefile +endif + +ifneq ($(PROJ_OBJ_DIR),$(PROJ_SRC_DIR)) + +Makefile: $(PROJ_MAKEFILE) $(ExtraMakefiles) + $(Echo) "Updating Makefile" + $(Verb) $(MKDIR) $(@D) + $(Verb) $(CP) -f $< $@ + +# Copy the Makefile.* files unless we're in the root directory which avoids +# the copying of Makefile.config.in or other things that should be explicitly +# taken care of. +$(PROJ_OBJ_DIR)/Makefile% : $(PROJ_MAKEFILE)% + @case '$?' in \ + *Makefile.rules) ;; \ + *.in) ;; \ + *) $(EchoCmd) "Updating $(@F)" ; \ + $(MKDIR) $(@D) ; \ + $(CP) -f $< $@ ;; \ + esac + +endif + +#------------------------------------------------------------------------ +# Set up the basic dependencies +#------------------------------------------------------------------------ +$(UserTargets):: $(PreConditions) + +all:: all-local +clean:: clean-local +clean-all:: clean-local clean-all-local +install:: install-local +uninstall:: uninstall-local +install-local:: all-local +install-bytecode:: install-bytecode-local + +############################################################################### +# VARIABLES: Set up various variables based on configuration data +############################################################################### + +# Variable for if this make is for a "cleaning" target +ifneq ($(strip $(filter clean clean-local dist-clean,$(MAKECMDGOALS))),) + IS_CLEANING_TARGET=1 +endif + +#-------------------------------------------------------------------- +# Variables derived from configuration we are building +#-------------------------------------------------------------------- + +CPP.Defines := +ifeq ($(ENABLE_OPTIMIZED),1) + BuildMode := Release + # Don't use -fomit-frame-pointer on Darwin or FreeBSD. + ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin Darwin DragonFly FreeBSD GNU/kFreeBSD)) + OmitFramePointer := -fomit-frame-pointer + endif + + CXX.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + C.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + LD.Flags += $(OPTIMIZE_OPTION) + ifdef DEBUG_SYMBOLS + BuildMode := $(BuildMode)+Debug + CXX.Flags += -g + C.Flags += -g + KEEP_SYMBOLS := 1 + endif +else + ifdef NO_DEBUG_SYMBOLS + BuildMode := Unoptimized + CXX.Flags += + C.Flags += + KEEP_SYMBOLS := 1 + else + BuildMode := Debug + ifeq ($(ENABLE_SPLIT_DWARF), 1) + CXX.Flags += -gsplit-dwarf + C.Flags += -gsplit-dwarf + else + CXX.Flags += -g + C.Flags += -g + endif + KEEP_SYMBOLS := 1 + endif +endif + +ifeq ($(ENABLE_LIBCPP),1) + CXX.Flags += -stdlib=libc++ + LD.Flags += -stdlib=libc++ +endif + +ifeq ($(ENABLE_CXX11),1) + CXX.Flags += -std=c++11 +endif + +ifeq ($(ENABLE_WERROR),1) + CXX.Flags += -Werror + C.Flags += -Werror +endif + +ifeq ($(ENABLE_PROFILING),1) + BuildMode := $(BuildMode)+Profile + CXX.Flags := $(filter-out -fomit-frame-pointer,$(CXX.Flags)) -pg -g + C.Flags := $(filter-out -fomit-frame-pointer,$(C.Flags)) -pg -g + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) -pg + KEEP_SYMBOLS := 1 +endif + +ifeq ($(ENABLE_VISIBILITY_INLINES_HIDDEN),1) + CXX.Flags += -fvisibility-inlines-hidden +endif + +ifdef ENABLE_EXPENSIVE_CHECKS + # GNU libstdc++ uses RTTI if you define _GLIBCXX_DEBUG, which we did above. + # See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40160 + REQUIRES_RTTI := 1 +endif + +# IF REQUIRES_EH=1 is specified then don't disable exceptions +ifndef REQUIRES_EH + CXX.Flags += -fno-exceptions +else + # If the library requires EH, it also requires RTTI. + REQUIRES_RTTI := 1 +endif + +ifdef REQUIRES_FRAME_POINTER + CXX.Flags := $(filter-out -fomit-frame-pointer,$(CXX.Flags)) + C.Flags := $(filter-out -fomit-frame-pointer,$(C.Flags)) + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) +endif + +# If REQUIRES_RTTI=1 is specified then don't disable run-time type id. +ifneq ($(REQUIRES_RTTI), 1) + CXX.Flags += -fno-rtti +endif + +ifeq ($(ENABLE_COVERAGE),1) + BuildMode := $(BuildMode)+Coverage + CXX.Flags += -ftest-coverage -fprofile-arcs + C.Flags += -ftest-coverage -fprofile-arcs +endif + +# If DISABLE_ASSERTIONS=1 is specified (make command line or configured), +# then disable assertions by defining the appropriate preprocessor symbols. +ifeq ($(DISABLE_ASSERTIONS),1) + CPP.Defines += -DNDEBUG +else + BuildMode := $(BuildMode)+Asserts + CPP.Defines += -D_DEBUG +endif + +# If ENABLE_EXPENSIVE_CHECKS=1 is specified (make command line or +# configured), then enable expensive checks by defining the +# appropriate preprocessor symbols. +ifeq ($(ENABLE_EXPENSIVE_CHECKS),1) + BuildMode := $(BuildMode)+Checks + CPP.Defines += -D_GLIBCXX_DEBUG -DXDEBUG +endif + +# LOADABLE_MODULE implies several other things so we force them to be +# defined/on. +ifdef LOADABLE_MODULE + SHARED_LIBRARY := 1 + LINK_LIBS_IN_SHARED := 1 +endif + +ifdef SHARED_LIBRARY + ENABLE_PIC := 1 + PIC_FLAG = "(PIC)" +endif + +ifeq ($(ENABLE_PIC),1) + ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + # Nothing. Win32 defaults to PIC and warns when given -fPIC + else + ifeq ($(HOST_OS),Darwin) + # Common symbols not allowed in dylib files + CXX.Flags += -fno-common + C.Flags += -fno-common + else + # Linux and others; pass -fPIC + CXX.Flags += -fPIC + C.Flags += -fPIC + endif + endif +else + ifeq ($(HOST_OS),Darwin) + CXX.Flags += -mdynamic-no-pic + C.Flags += -mdynamic-no-pic + endif +endif + +# Support makefile variable to disable any kind of timestamp/non-deterministic +# info from being used in the build. +ifeq ($(ENABLE_TIMESTAMPS),1) + DOTDIR_TIMESTAMP_COMMAND := $(DATE) +else + DOTDIR_TIMESTAMP_COMMAND := echo 'Created.' +endif + +ifeq ($(HOST_OS),MingW) + # Work around PR4957 + CPP.Defines += -D__NO_CTYPE_INLINE + ifeq ($(LLVM_CROSS_COMPILING),1) + # Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=525016 + ifdef TOOLNAME + LD.Flags += -Wl,--allow-multiple-definition + endif + endif +endif + +CXX.Flags += -Woverloaded-virtual +CPP.BaseFlags += $(CPP.Defines) +AR.Flags := cru + +# Make Floating point IEEE compliant on Alpha. +ifeq ($(ARCH),Alpha) + CXX.Flags += -mieee + CPP.BaseFlags += -mieee +ifeq ($(ENABLE_PIC),0) + CXX.Flags += -fPIC + CPP.BaseFlags += -fPIC +endif + + LD.Flags += -Wl,--no-relax +endif + +# GNU ld/PECOFF accepts but ignores them below; +# --version-script +# --export-dynamic +# --rpath +# FIXME: autoconf should be aware of them. +ifneq (,$(filter $(HOST_OS),Cygwin MingW)) + HAVE_LINK_VERSION_SCRIPT := 0 + RPATH := + RDYNAMIC := -Wl,--export-all-symbols +endif + +#-------------------------------------------------------------------- +# Directory locations +#-------------------------------------------------------------------- +TargetMode := +ifeq ($(LLVM_CROSS_COMPILING),1) + BuildLLVMToolDir := $(LLVM_OBJ_ROOT)/BuildTools/$(BuildMode)/bin +endif + +ObjRootDir := $(PROJ_OBJ_DIR)/$(BuildMode) +ObjDir := $(ObjRootDir) +LibDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/lib +ToolDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/bin +ExmplDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/examples +LLVMLibDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/lib +LLVMToolDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/bin +LLVMExmplDir:= $(LLVM_OBJ_ROOT)/$(BuildMode)/examples + +#-------------------------------------------------------------------- +# Locations of shared libraries +#-------------------------------------------------------------------- + +SharedPrefix := lib +SharedLibDir := $(LibDir) +LLVMSharedLibDir := $(LLVMLibDir) + +# Win32.DLL prefers to be located on the "PATH" of binaries. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + SharedLibDir := $(ToolDir) + LLVMSharedLibDir := $(LLVMToolDir) + + ifeq ($(HOST_OS),Cygwin) + SharedPrefix := cyg + else + SharedPrefix := + endif +endif + +#-------------------------------------------------------------------- +# Full Paths To Compiled Tools and Utilities +#-------------------------------------------------------------------- +EchoCmd := $(ECHO) llvm[$(MAKELEVEL)]: +ifdef BUILD_DIRS_ONLY +EchoCmd := $(EchoCmd) "(build tools)": +endif + +Echo := @$(EchoCmd) +ifndef LLVMAS +LLVMAS := $(LLVMToolDir)/llvm-as$(EXEEXT) +endif +ifndef LLVM_TBLGEN + ifeq ($(LLVM_CROSS_COMPILING),1) + LLVM_TBLGEN := $(BuildLLVMToolDir)/llvm-tblgen$(BUILD_EXEEXT) + else + LLVM_TBLGEN := $(LLVMToolDir)/llvm-tblgen$(EXEEXT) + endif +endif +ifeq ($(LLVM_CROSS_COMPILING),1) + LLVM_CONFIG := $(BuildLLVMToolDir)/llvm-config$(BUILD_EXEEXT) +else + LLVM_CONFIG := $(LLVMToolDir)/llvm-config$(EXEEXT) +endif +ifndef LLVMDIS +LLVMDIS := $(LLVMToolDir)/llvm-dis$(EXEEXT) +endif +ifndef LLI +LLI := $(LLVMToolDir)/lli$(EXEEXT) +endif +ifndef LLC +LLC := $(LLVMToolDir)/llc$(EXEEXT) +endif +ifndef LOPT +LOPT := $(LLVMToolDir)/opt$(EXEEXT) +endif +ifndef LBUGPOINT +LBUGPOINT := $(LLVMToolDir)/bugpoint$(EXEEXT) +endif +ifndef LLVMLINK +LLVMLINK := $(LLVMToolDir)/llvm-link$(EXEEXT) +endif + +#-------------------------------------------------------------------- +# Adjust to user's request +#-------------------------------------------------------------------- + +ifeq ($(HOST_OS),Darwin) + ifdef MACOSX_DEPLOYMENT_TARGET + DARWIN_VERSION := $(MACOSX_DEPLOYMENT_TARGET) + else + DARWIN_VERSION := `sw_vers -productVersion` + endif + # Strip a number like 10.4.7 to 10.4 + DARWIN_VERSION := $(shell echo $(DARWIN_VERSION)| sed -E 's/(10.[0-9]+).*/\1/') + # Get "4" out of 10.4 for later pieces in the makefile. + DARWIN_MAJVERS := $(shell echo $(DARWIN_VERSION)| sed -E 's/10.([0-9]+).*/\1/') + + LoadableModuleOptions := -Wl,-flat_namespace -Wl,-undefined,suppress + SharedLinkOptions := -dynamiclib + ifdef DEPLOYMENT_TARGET + SharedLinkOptions += $(DEPLOYMENT_TARGET) + else + ifneq ($(ARCH),ARM) + SharedLinkOptions += -mmacosx-version-min=$(DARWIN_VERSION) + endif + endif +else + SharedLinkOptions=-shared +endif + +ifeq ($(TARGET_OS),Darwin) + ifdef DEPLOYMENT_TARGET + TargetCommonOpts += $(DEPLOYMENT_TARGET) + else + ifneq ($(ARCH),ARM) + TargetCommonOpts += -mmacosx-version-min=$(DARWIN_VERSION) + endif + endif +endif + +ifdef SHARED_LIBRARY +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS),Darwin) + LD.Flags += $(RPATH) -Wl,'$$ORIGIN' +endif +endif +endif + +ifdef TOOL_VERBOSE + C.Flags += -v + CXX.Flags += -v + LD.Flags += -v + VERBOSE := 1 +endif + +# Adjust settings for verbose mode +ifndef VERBOSE + Verb := @ + AR.Flags += >/dev/null 2>/dev/null + ConfigureScriptFLAGS += >$(PROJ_OBJ_DIR)/configure.out 2>&1 +else + ConfigureScriptFLAGS := +endif + +# By default, strip symbol information from executable +ifndef KEEP_SYMBOLS + Strip := $(PLATFORMSTRIPOPTS) + StripWarnMsg := "(without symbols)" + Install.StripFlag += -s +endif + +# Adjust linker flags for building an executable +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + ifndef TOOL_NO_EXPORTS + LD.Flags += $(RDYNAMIC) + endif + ifneq ($(HOST_OS), Darwin) + ifdef TOOLNAME + LD.Flags += $(RPATH) -Wl,'$$ORIGIN/../lib' + endif + else + ifneq ($(DARWIN_MAJVERS),4) + LD.Flags += $(RPATH) -Wl,@executable_path/../lib + endif + ifeq ($(RC_XBS),YES) + TempFile := $(shell mkdir -p ${OBJROOT}/dSYMs ; mktemp ${OBJROOT}/dSYMs/llvm-lto.XXXXXX) + LD.Flags += -Wl,-object_path_lto -Wl,$(TempFile) + endif + endif +endif + + +#---------------------------------------------------------- +# Options To Invoke Tools +#---------------------------------------------------------- + +ifdef EXTRA_LD_OPTIONS +LD.Flags += $(EXTRA_LD_OPTIONS) +endif + +ifndef NO_PEDANTIC +CompileCommonOpts += -pedantic -Wno-long-long +endif +CompileCommonOpts += -Wall -W -Wno-unused-parameter -Wwrite-strings \ + $(EXTRA_OPTIONS) $(COVERED_SWITCH_DEFAULT) \ + $(NO_UNINITIALIZED) $(NO_MAYBE_UNINITIALIZED) \ + $(NO_MISSING_FIELD_INITIALIZERS) +# Enable cast-qual for C++; the workaround is to use const_cast. +CXX.Flags += -Wcast-qual + +ifeq ($(HOST_OS),HP-UX) + CompileCommonOpts := -D_REENTRANT -D_HPUX_SOURCE +endif + +# If we are building a universal binary on Mac OS/X, pass extra options. This +# is useful to people that want to link the LLVM libraries into their universal +# apps. +# +# The following can be optionally specified: +# UNIVERSAL_SDK_PATH variable can be specified as a path to the SDK to use. +# For Mac OS/X 10.4 Intel machines, the traditional one is: +# UNIVERSAL_SDK_PATH=/Developer/SDKs/MacOSX10.4u.sdk/ +# UNIVERSAL_ARCH can be optionally specified to be a list of architectures +# to build for, e.g. UNIVERSAL_ARCH="i386 ppc ppc64". This defaults to +# i386/ppc only. +ifdef UNIVERSAL + ifndef UNIVERSAL_ARCH + UNIVERSAL_ARCH := i386 ppc + endif + UNIVERSAL_ARCH_OPTIONS := $(UNIVERSAL_ARCH:%=-arch %) + TargetCommonOpts += $(UNIVERSAL_ARCH_OPTIONS) + ifdef UNIVERSAL_SDK_PATH + TargetCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH) + endif + + # Building universal cannot compute dependencies automatically. + DISABLE_AUTO_DEPENDENCIES=1 +else + ifeq ($(TARGET_OS),Darwin) + ifeq ($(ARCH),x86_64) + TargetCommonOpts = -m64 + else + ifeq ($(ARCH),x86) + TargetCommonOpts = -m32 + endif + endif + endif +endif + +ifeq ($(HOST_OS),SunOS) +CPP.BaseFlags += -include llvm/Support/Solaris.h +endif + +ifeq ($(HOST_OS),AuroraUX) +CPP.BaseFlags += -include llvm/Support/Solaris.h +endif # !HOST_OS - AuroraUX. + +# On Windows, SharedLibDir != LibDir. The order is important. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + LD.Flags += -L$(SharedLibDir) -L$(LibDir) -L$(LLVMToolDir) -L$(LLVMLibDir) +else + LD.Flags += -L$(LibDir) -L$(LLVMLibDir) +endif + +CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS +# All -I flags should go here, so that they don't confuse llvm-config. +CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \ + $(patsubst %,-I%/include,\ + $(PROJ_OBJ_ROOT) $(PROJ_SRC_ROOT) \ + $(LLVM_OBJ_ROOT) $(LLVM_SRC_ROOT))) \ + $(CPP.BaseFlags) + +ifeq ($(INCLUDE_BUILD_DIR),1) + CPP.Flags += -I$(ObjDir) +endif + +# SHOW_DIAGNOSTICS support. +ifeq ($(SHOW_DIAGNOSTICS),1) + Compile.Wrapper := env CC_LOG_DIAGNOSTICS=1 \ + CC_LOG_DIAGNOSTICS_FILE="$(LLVM_OBJ_ROOT)/$(BuildMode)/diags" +else + Compile.Wrapper := +endif + +Compile.C = $(Compile.Wrapper) \ + $(CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c +Compile.CXX = $(Compile.Wrapper) \ + $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c +Preprocess.CXX= $(Compile.Wrapper) \ + $(CXX) $(CPP.Flags) $(TargetCommonOpts) $(CPPFLAGS) \ + $(CompileCommonOpts) $(CXX.Flags) -E +Link = $(Compile.Wrapper) \ + $(CXX) $(CXXFLAGS) $(LD.Flags) $(LDFLAGS) \ + $(TargetCommonOpts) $(Strip) + +Preprocess.C = $(CC) $(CPP.Flags) $(C.Flags) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -E + +ProgInstall = $(INSTALL) $(Install.StripFlag) -m 0755 +ScriptInstall = $(INSTALL) -m 0755 +DataInstall = $(INSTALL) -m 0644 + +# When compiling under Mingw/Cygwin, the tblgen tool expects Windows +# paths. In this case, the SYSPATH function (defined in +# Makefile.config) transforms Unix paths into Windows paths. +TableGen.Flags= -I $(call SYSPATH, $(PROJ_SRC_DIR)) \ + -I $(call SYSPATH, $(LLVM_SRC_ROOT)/include) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/include) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/lib/Target) +LLVMTableGen = $(LLVM_TBLGEN) $(TableGen.Flags) + +Archive = $(AR) $(AR.Flags) +ifdef RANLIB +Ranlib = $(RANLIB) +else +Ranlib = ranlib +endif + +AliasTool = ln -sf + +#---------------------------------------------------------- +# Get the list of source files and compute object file +# names from them. +#---------------------------------------------------------- + +ifndef SOURCES + Sources := $(notdir $(wildcard $(PROJ_SRC_DIR)/*.cpp \ + $(PROJ_SRC_DIR)/*.cc $(PROJ_SRC_DIR)/*.c)) +else + Sources := $(SOURCES) +endif + +ifdef BUILT_SOURCES +Sources += $(filter %.cpp %.c %.cc,$(BUILT_SOURCES)) +endif + +BaseNameSources := $(sort $(basename $(Sources))) +SourceDirs := $(sort $(dir $(Sources))) + +ObjectsO := $(BaseNameSources:%=$(ObjDir)/%.o) +ObjectDirs := $(SourceDirs:%=$(ObjDir)/%) + +#---------------------------------------------------------- +# For Mingw MSYS bash and Python/w32: +# +# $(ECHOPATH) prints DOSish pathstring. +# ex) $(ECHOPATH) /include/sys/types.h +# --> C:/mingw/include/sys/types.h +# built-in "echo" does not transform path to DOSish path. +# +# FIXME: It would not be needed when MSYS's python +# were provided. +#---------------------------------------------------------- + +ifeq (-mingw32,$(findstring -mingw32,$(BUILD_TRIPLE))) + ECHOPATH := $(Verb)$(PYTHON) -u -c "import sys;print ' '.join(sys.argv[1:])" +else + ECHOPATH := $(Verb)$(ECHO) +endif + +############################################################################### +# DIRECTORIES: Handle recursive descent of directory structure +############################################################################### + +#--------------------------------------------------------- +# Provide rules to make install dirs. This must be early +# in the file so they get built before dependencies +#--------------------------------------------------------- + +$(DESTDIR)$(PROJ_bindir) $(DESTDIR)$(PROJ_libdir) $(DESTDIR)$(PROJ_includedir) $(DESTDIR)$(PROJ_etcdir):: + $(Verb) $(MKDIR) $@ + +# To create other directories, as needed, and timestamp their creation +%/.dir: + $(Verb) $(MKDIR) $* > /dev/null + $(Verb) $(DOTDIR_TIMESTAMP_COMMAND) > $@ + +.PRECIOUS: $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir +.PRECIOUS: $(LLVMLibDir)/.dir $(LLVMToolDir)/.dir $(LLVMExmplDir)/.dir + +#--------------------------------------------------------- +# Collect the object directories (as there may be more +# than one if the source code is spread across +# subdirectories). +#--------------------------------------------------------- + +OBJECT_DIRS := $(ObjDir)/.dir $(ObjectDirs:%=%/.dir) +.PRECIOUS: $(OBJECT_DIRS) + +#--------------------------------------------------------- +# Handle the DIRS options for sequential construction +#--------------------------------------------------------- + +SubDirs := +ifdef DIRS +SubDirs += $(DIRS) + +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + if ([ ! -f $$dir/Makefile ] || \ + command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +else +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +endif + +endif + +#--------------------------------------------------------- +# Handle the EXPERIMENTAL_DIRS options ensuring success +# after each directory is built. +#--------------------------------------------------------- +ifdef EXPERIMENTAL_DIRS +$(RecursiveTargets):: + $(Verb) for dir in $(EXPERIMENTAL_DIRS); do \ + if ([ ! -f $$dir/Makefile ] || \ + command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ ) || exit 0; \ + done +endif + +#----------------------------------------------------------- +# Handle the OPTIONAL_PARALLEL_DIRS options for optional parallel construction +#----------------------------------------------------------- +ifdef OPTIONAL_PARALLEL_DIRS + PARALLEL_DIRS += $(foreach T,$(OPTIONAL_PARALLEL_DIRS),$(shell test -d $(PROJ_SRC_DIR)/$(T) -o -f $(T)/Makefile && echo "$(T)")) +endif + +#----------------------------------------------------------- +# Handle the PARALLEL_DIRS options for parallel construction +#----------------------------------------------------------- +ifdef PARALLEL_DIRS + +SubDirs += $(PARALLEL_DIRS) + +# Unfortunately, this list must be maintained if new recursive targets are added +all :: $(addsuffix /.makeall ,$(PARALLEL_DIRS)) +clean :: $(addsuffix /.makeclean ,$(PARALLEL_DIRS)) +clean-all:: $(addsuffix /.makeclean-all,$(PARALLEL_DIRS)) +install :: $(addsuffix /.makeinstall ,$(PARALLEL_DIRS)) +uninstall:: $(addsuffix /.makeuninstall,$(PARALLEL_DIRS)) +install-bytecode :: $(addsuffix /.makeinstall-bytecode,$(PARALLEL_DIRS)) +unitcheck:: $(addsuffix /.makeunitcheck,$(PARALLEL_DIRS)) + +ParallelTargets := $(foreach T,$(RecursiveTargets),%/.make$(T)) + +$(ParallelTargets) : + $(Verb) \ + SD=$(PROJ_SRC_DIR)/$(@D); \ + DD=$(@D); \ + if [ ! -f $$SD/Makefile ]; then \ + SD=$(@D); \ + DD=$(notdir $(@D)); \ + fi; \ + if ([ ! -f $$DD/Makefile ] || \ + command test $$DD/Makefile -ot \ + $$SD/Makefile ); then \ + $(MKDIR) $$DD; \ + $(CP) $$SD/Makefile $$DD/Makefile; \ + fi; \ + $(MAKE) -C $$DD $(subst $(@D)/.make,,$@) +endif + +#--------------------------------------------------------- +# Handle the OPTIONAL_DIRS options for directores that may +# or may not exist. +#--------------------------------------------------------- +ifdef OPTIONAL_DIRS + +SubDirs += $(OPTIONAL_DIRS) + +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) +$(RecursiveTargets):: + $(Verb) for dir in $(OPTIONAL_DIRS); do \ + if [ -d $(PROJ_SRC_DIR)/$$dir ]; then\ + if ([ ! -f $$dir/Makefile ] || \ + command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C$$dir $@ ) || exit 1; \ + fi \ + done +else +$(RecursiveTargets):: + $(Verb) for dir in $(OPTIONAL_DIRS); do \ + if [ -d $(PROJ_SRC_DIR)/$$dir ]; then\ + ($(MAKE) -C$$dir $@ ) || exit 1; \ + fi \ + done +endif +endif + +#--------------------------------------------------------- +# Handle the CONFIG_FILES options +#--------------------------------------------------------- +ifdef CONFIG_FILES + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) UnInstall circumvented with NO_INSTALL +else +install-local:: $(DESTDIR)$(PROJ_etcdir) $(CONFIG_FILES) + $(Echo) Installing Configuration Files To $(DESTDIR)$(PROJ_etcdir) + $(Verb)for file in $(CONFIG_FILES); do \ + if test -f $(PROJ_OBJ_DIR)/$${file} ; then \ + $(DataInstall) $(PROJ_OBJ_DIR)/$${file} $(DESTDIR)$(PROJ_etcdir) ; \ + elif test -f $(PROJ_SRC_DIR)/$${file} ; then \ + $(DataInstall) $(PROJ_SRC_DIR)/$${file} $(DESTDIR)$(PROJ_etcdir) ; \ + else \ + $(ECHO) Error: cannot find config file $${file}. ; \ + fi \ + done + +uninstall-local:: + $(Echo) Uninstalling Configuration Files From $(DESTDIR)$(PROJ_etcdir) + $(Verb)for file in $(CONFIG_FILES); do \ + $(RM) -f $(DESTDIR)$(PROJ_etcdir)/$${file} ; \ + done +endif + +endif + +############################################################################### +# Set up variables for building libraries +############################################################################### + +#--------------------------------------------------------- +# Define various command line options pertaining to the +# libraries needed when linking. There are "Proj" libs +# (defined by the user's project) and "LLVM" libs (defined +# by the LLVM project). +#--------------------------------------------------------- + +ifdef USEDLIBS +ProjLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(USEDLIBS))) +ProjLibsOptions := $(patsubst %.o, $(LibDir)/%.o, $(ProjLibsOptions)) +ProjUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(USEDLIBS))) +ProjLibsPaths := $(addprefix $(LibDir)/,$(ProjUsedLibs)) +endif + +ifdef LLVMLIBS +LLVMLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsOptions := $(patsubst %.o, $(LLVMLibDir)/%.o, $(LLVMLibsOptions)) +LLVMUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsPaths := $(addprefix $(LLVMLibDir)/,$(LLVMUsedLibs)) +endif + +# Loadable module for Win32 requires all symbols resolved for linking. +# Then all symbols in LLVM.dll will be available. +ifeq ($(ENABLE_SHARED),1) + ifdef LOADABLE_MODULE + ifneq (,$(filter $(HOST_OS),Cygwin MingW)) + LINK_COMPONENTS += all + endif + endif +endif + +ifndef IS_CLEANING_TARGET +ifdef LINK_COMPONENTS + +# If LLVM_CONFIG doesn't exist, build it. This can happen if you do a make +# clean in tools, then do a make in tools (instead of at the top level). +$(LLVM_CONFIG): + @echo "*** llvm-config doesn't exist - rebuilding it." + @$(MAKE) -C $(PROJ_OBJ_ROOT)/tools/llvm-config + +$(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT): $(LLVM_CONFIG) + +ifeq ($(ENABLE_SHARED), 1) +# We can take the "auto-import" feature to get rid of using dllimport. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +LLVMLibsOptions += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc \ + -L $(SharedLibDir) +endif +LLVMLibsOptions += -lLLVM-$(LLVMVersion) +LLVMLibsPaths += $(SharedLibDir)/$(SharedPrefix)LLVM-$(LLVMVersion)$(SHLIBEXT) +else + +ifndef NO_LLVM_CONFIG +LLVMConfigLibs := $(shell $(LLVM_CONFIG) --libs $(LINK_COMPONENTS) || echo Error) +ifeq ($(LLVMConfigLibs),Error) +$(error llvm-config --libs failed) +endif +LLVMLibsOptions += $(LLVMConfigLibs) +LLVMConfigLibfiles := $(shell $(LLVM_CONFIG) --libfiles $(LINK_COMPONENTS) || echo Error) +ifeq ($(LLVMConfigLibfiles),Error) +$(error llvm-config --libfiles failed) +endif +LLVMLibsPaths += $(LLVM_CONFIG) $(LLVMConfigLibfiles) +endif + +endif +endif +endif + +# Set up the library exports file. +ifdef EXPORTED_SYMBOL_FILE + +# First, set up the native export file, which may differ from the source +# export file. + +ifeq ($(HOST_OS),Darwin) +# Darwin convention prefixes symbols with underscores. +NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE)).sed +$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir + $(Verb) sed -e 's/^/_/' < $< > $@ +clean-local:: + -$(Verb) $(RM) -f $(NativeExportsFile) +else +ifeq ($(HAVE_LINK_VERSION_SCRIPT),1) +# Gold and BFD ld require a version script rather than a plain list. +NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE)).map +$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir + $(Verb) echo "{" > $@ + $(Verb) grep -q '[[:alnum:]_]' $< && echo " global:" >> $@ || : + $(Verb) sed -e 's/$$/;/' -e 's/^/ /' < $< >> $@ +ifneq ($(HOST_OS),OpenBSD) + $(Verb) echo " local: *;" >> $@ +endif + $(Verb) echo "};" >> $@ +clean-local:: + -$(Verb) $(RM) -f $(NativeExportsFile) +else +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +# GNU ld Win32 accepts .DEF files that contain "DATA" entries. +NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE:.exports=.def)) +$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir + $(Echo) Generating $(notdir $@) + $(Verb) $(ECHO) "EXPORTS" > $@ + $(Verb) $(CAT) $< >> $@ +clean-local:: + -$(Verb) $(RM) -f $(NativeExportsFile) +else +# Default behavior: just use the exports file verbatim. +NativeExportsFile := $(EXPORTED_SYMBOL_FILE) +endif +endif +endif + +# Now add the linker command-line options to use the native export file. + +# Darwin +ifeq ($(HOST_OS),Darwin) +LLVMLibsOptions += -Wl,-exported_symbols_list,$(NativeExportsFile) +endif + +# gold, bfd ld, etc. +ifeq ($(HAVE_LINK_VERSION_SCRIPT),1) +LLVMLibsOptions += -Wl,--version-script,$(NativeExportsFile) +endif + +# Windows +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +# LLVMLibsOptions is invalidated at processing tools/llvm-shlib. +SharedLinkOptions += $(NativeExportsFile) +endif + +endif + +############################################################################### +# Library Build Rules: Four ways to build a library +############################################################################### + +# if we're building a library ... +ifdef LIBRARYNAME + +# Make sure there isn't any extraneous whitespace on the LIBRARYNAME option +LIBRARYNAME := $(strip $(LIBRARYNAME)) +LIBRARYALIASNAME := $(strip $(LIBRARYALIASNAME)) +ifdef LOADABLE_MODULE +BaseLibName.A := $(LIBRARYNAME).a +BaseLibName.SO := $(LIBRARYNAME)$(SHLIBEXT) +BaseAliasName.SO := $(LIBRARYALIASNAME)$(SHLIBEXT) +else +BaseLibName.A := lib$(LIBRARYNAME).a +BaseLibName.SO := $(SharedPrefix)$(LIBRARYNAME)$(SHLIBEXT) +BaseAliasName.SO := $(SharedPrefix)$(LIBRARYALIASNAME)$(SHLIBEXT) +endif +LibName.A := $(LibDir)/$(BaseLibName.A) +LibName.SO := $(SharedLibDir)/$(BaseLibName.SO) +AliasName.SO := $(SharedLibDir)/$(BaseAliasName.SO) +LibName.O := $(LibDir)/$(LIBRARYNAME).o + +#--------------------------------------------------------- +# Shared Library Targets: +# If the user asked for a shared library to be built +# with the SHARED_LIBRARY variable, then we provide +# targets for building them. +#--------------------------------------------------------- +ifdef SHARED_LIBRARY + +all-local:: $(LibName.SO) + +ifdef EXPORTED_SYMBOL_FILE +$(LibName.SO): $(NativeExportsFile) +endif + +ifdef LINK_LIBS_IN_SHARED +ifdef LOADABLE_MODULE +SharedLibKindMessage := "Loadable Module" +SharedLinkOptions := $(LoadableModuleOptions) $(SharedLinkOptions) +else +SharedLibKindMessage := "Shared Library" +endif +$(LibName.SO): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) $(SharedLibDir)/.dir + $(Echo) Linking $(BuildMode) $(SharedLibKindMessage) \ + $(notdir $@) + $(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO) \ + $(ProjLibsOptions) $(LLVMLibsOptions) $(LIBS) +else +$(LibName.SO): $(ObjectsO) $(SharedLibDir)/.dir + $(Echo) Linking $(BuildMode) Shared Library $(notdir $@) + $(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO) +endif + +clean-local:: +ifneq ($(strip $(LibName.SO)),) + -$(Verb) $(RM) -f $(LibName.SO) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else + +# Win32.DLL prefers to be located on the "PATH" of binaries. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +DestSharedLibDir := $(DESTDIR)$(PROJ_bindir) +else +DestSharedLibDir := $(DESTDIR)$(PROJ_libdir) +endif +DestSharedLib := $(DestSharedLibDir)/$(BaseLibName.SO) +DestSharedAlias := $(DestSharedLibDir)/$(BaseAliasName.SO) + +install-local:: $(DestSharedLib) + +$(DestSharedLib): $(LibName.SO) $(DestSharedLibDir) + $(Echo) Installing $(BuildMode) Shared Library $(DestSharedLib) + $(Verb) $(INSTALL) $(LibName.SO) $(DestSharedLib) +ifdef SHARED_ALIAS + $(Echo) Creating alias from $(DestSharedLib) to $(DestSharedAlias) + $(Verb) $(AliasTool) $(DestSharedLib) $(DestSharedAlias) +endif + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Shared Library $(DestSharedLib) + -$(Verb) $(RM) -f $(DestSharedLib) +endif +endif + +#--------------------------------------------------------- +# Library Targets: +# If neither BUILD_ARCHIVE or LOADABLE_MODULE are specified, default to +# building an archive. +#--------------------------------------------------------- +ifndef NO_BUILD_ARCHIVE +ifndef BUILD_ARCHIVE +ifndef LOADABLE_MODULE +BUILD_ARCHIVE = 1 +endif +endif +endif + +#--------------------------------------------------------- +# Archive Library Targets: +# If the user wanted a regular archive library built, +# then we provide targets for building them. +#--------------------------------------------------------- +ifdef BUILD_ARCHIVE + +all-local:: $(LibName.A) + +$(LibName.A): $(ObjectsO) $(LibDir)/.dir + $(Echo) Building $(BuildMode) Archive Library $(notdir $@) + -$(Verb) $(RM) -f $@ + $(Verb) $(Archive) $@ $(ObjectsO) + $(Verb) $(Ranlib) $@ + +clean-local:: +ifneq ($(strip $(LibName.A)),) + -$(Verb) $(RM) -f $(LibName.A) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +ifdef NO_INSTALL_ARCHIVES +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestArchiveLib := $(DESTDIR)$(PROJ_libdir)/lib$(LIBRARYNAME).a + +install-local:: $(DestArchiveLib) + +$(DestArchiveLib): $(LibName.A) $(DESTDIR)$(PROJ_libdir) + $(Echo) Installing $(BuildMode) Archive Library $(DestArchiveLib) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_libdir) + $(Verb) $(INSTALL) $(LibName.A) $(DestArchiveLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Archive Library $(DestArchiveLib) + -$(Verb) $(RM) -f $(DestArchiveLib) +endif +endif +endif + +# endif LIBRARYNAME +endif + +############################################################################### +# Tool Build Rules: Build executable tool based on TOOLNAME option +############################################################################### + +ifdef TOOLNAME + +#--------------------------------------------------------- +# Set up variables for building a tool. +#--------------------------------------------------------- +TOOLEXENAME := $(strip $(TOOLNAME))$(EXEEXT) +ifdef EXAMPLE_TOOL +ToolBuildPath := $(ExmplDir)/$(TOOLEXENAME) +else +ToolBuildPath := $(ToolDir)/$(TOOLEXENAME) +endif + +# TOOLALIAS is a name to symlink (or copy) the tool to. +ifdef TOOLALIAS +ifdef EXAMPLE_TOOL +ToolAliasBuildPath := $(ExmplDir)/$(strip $(TOOLALIAS))$(EXEEXT) +else +ToolAliasBuildPath := $(ToolDir)/$(strip $(TOOLALIAS))$(EXEEXT) +endif +endif + +#--------------------------------------------------------- +# Prune Exports +#--------------------------------------------------------- + +# If the tool opts in with TOOL_NO_EXPORTS, optimize startup time of the app by +# not exporting all of the weak symbols from the binary. This reduces dyld +# startup time by 4x on darwin in some cases. +ifdef TOOL_NO_EXPORTS +ifeq ($(HOST_OS),Darwin) + +# Tiger tools don't support this. +ifneq ($(DARWIN_MAJVERS),4) +LD.Flags += -Wl,-exported_symbol,_main +endif +endif + +ifeq ($(HOST_OS), $(filter $(HOST_OS), DragonFly Linux NetBSD FreeBSD GNU/kFreeBSD GNU)) +ifneq ($(ARCH), Mips) + LD.Flags += -Wl,--version-script=$(LLVM_SRC_ROOT)/autoconf/ExportMap.map +endif +endif +endif + +#--------------------------------------------------------- +# Tool Order File Support +#--------------------------------------------------------- + +ifeq ($(HOST_OS),Darwin) +ifdef TOOL_ORDER_FILE + +LD.Flags += -Wl,-order_file,$(TOOL_ORDER_FILE) + +endif +endif + +#--------------------------------------------------------- +# Tool Version Info Support +#--------------------------------------------------------- + +ifeq ($(HOST_OS),Darwin) +ifdef TOOL_INFO_PLIST + +LD.Flags += -Wl,-sectcreate,__TEXT,__info_plist,$(ObjDir)/$(TOOL_INFO_PLIST) + +$(ToolBuildPath): $(ObjDir)/$(TOOL_INFO_PLIST) + +$(ObjDir)/$(TOOL_INFO_PLIST): $(PROJ_SRC_DIR)/$(TOOL_INFO_PLIST).in $(ObjDir)/.dir + $(Echo) "Creating $(TOOLNAME) '$(TOOL_INFO_PLIST)' file..." + $(Verb)sed -e "s#@TOOL_INFO_UTI@#$(TOOL_INFO_UTI)#g" \ + -e "s#@TOOL_INFO_NAME@#$(TOOL_INFO_NAME)#g" \ + -e "s#@TOOL_INFO_VERSION@#$(TOOL_INFO_VERSION)#g" \ + -e "s#@TOOL_INFO_BUILD_VERSION@#$(TOOL_INFO_BUILD_VERSION)#g" \ + $< > $@ + +endif +endif + +#--------------------------------------------------------- +# Provide targets for building the tools +#--------------------------------------------------------- +all-local:: $(ToolBuildPath) $(ToolAliasBuildPath) + +clean-local:: +ifneq ($(strip $(ToolBuildPath)),) + -$(Verb) $(RM) -f $(ToolBuildPath) +endif +ifneq ($(strip $(ToolAliasBuildPath)),) + -$(Verb) $(RM) -f $(ToolAliasBuildPath) +endif + +ifdef EXAMPLE_TOOL +$(ToolBuildPath): $(ExmplDir)/.dir +else +$(ToolBuildPath): $(ToolDir)/.dir +endif + +ifdef CODESIGN_TOOLS +TOOL_CODESIGN_IDENTITY ?= - + +$(ToolBuildPath): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) + $(Echo) Linking $(BuildMode) executable $(TOOLNAME) $(StripWarnMsg) + $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ + $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) + $(Echo) ======= Finished Linking $(BuildMode) Executable $(TOOLNAME) \ + $(StripWarnMsg) + $(Echo) ======= Code-Signing $(BuildMode) Executable $(TOOLNAME) + $(Verb) codesign -s $(TOOL_CODESIGN_IDENTITY) $@ +else +$(ToolBuildPath): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) + $(Echo) Linking $(BuildMode) executable $(TOOLNAME) $(StripWarnMsg) + $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ + $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) + $(Echo) ======= Finished Linking $(BuildMode) Executable $(TOOLNAME) \ + $(StripWarnMsg) +endif + +ifneq ($(strip $(ToolAliasBuildPath)),) +$(ToolAliasBuildPath): $(ToolBuildPath) + $(Echo) Creating $(BuildMode) Alias $(TOOLALIAS) $(StripWarnMsg) + $(Verb) $(RM) -f $(ToolAliasBuildPath) + $(Verb) $(AliasTool) $(notdir $(ToolBuildPath)) $(ToolAliasBuildPath) + $(Echo) ======= Finished Creating $(BuildMode) Alias $(TOOLALIAS) \ + $(StripWarnMsg) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else + +ifdef INTERNAL_TOOL +ToolBinDir = $(DESTDIR)$(PROJ_internal_prefix)/bin +else +ToolBinDir = $(DESTDIR)$(PROJ_bindir) +endif +DestTool = $(ToolBinDir)/$(program_prefix)$(TOOLEXENAME) + +install-local:: $(DestTool) + +$(DestTool): $(ToolBuildPath) + $(Echo) Installing $(BuildMode) $(DestTool) + $(Verb) $(MKDIR) $(ToolBinDir) + $(Verb) $(ProgInstall) $(ToolBuildPath) $(DestTool) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) $(DestTool) + -$(Verb) $(RM) -f $(DestTool) + +# TOOLALIAS install. +ifdef TOOLALIAS +DestToolAlias = $(ToolBinDir)/$(program_prefix)$(TOOLALIAS)$(EXEEXT) + +install-local:: $(DestToolAlias) + +$(DestToolAlias): $(DestTool) + $(Echo) Installing $(BuildMode) $(DestToolAlias) + $(Verb) $(RM) -f $(DestToolAlias) + $(Verb) $(AliasTool) $(notdir $(DestTool)) $(DestToolAlias) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) $(DestToolAlias) + -$(Verb) $(RM) -f $(DestToolAlias) +endif + +endif +endif + +############################################################################### +# Object Build Rules: Build object files based on sources +############################################################################### + +# FIXME: This should be checking for "if not GCC or ICC", not for "if HP-UX" +ifeq ($(HOST_OS),HP-UX) + DISABLE_AUTO_DEPENDENCIES=1 +endif + +COMPILE_DEPS = $(OBJECT_DIRS) $(BUILT_SOURCES) $(PROJ_MAKEFILE) + +# Provide rule sets for when dependency generation is enabled +ifndef DISABLE_AUTO_DEPENDENCIES + +#--------------------------------------------------------- +# Create .o files in the ObjDir directory from the .cpp and .c files... +#--------------------------------------------------------- + +DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.d.tmp" \ + -MT "$(ObjDir)/$*.o" -MT "$(ObjDir)/$*.d" + +# If the build succeeded, move the dependency file over, otherwise +# remove it. +DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.d.tmp" "$(ObjDir)/$*.d"; \ + else $(RM) "$(ObjDir)/$*.d.tmp"; exit 1; fi + +$(ObjDir)/%.o: %.cpp $(COMPILE_DEPS) + $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.mm $(COMPILE_DEPS) + $(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.cc $(COMPILE_DEPS) + $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.c $(COMPILE_DEPS) + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.m $(COMPILE_DEPS) + $(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +# Provide alternate rule sets if dependencies are disabled +else + +$(ObjDir)/%.o: %.cpp $(COMPILE_DEPS) + $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.mm $(COMPILE_DEPS) + $(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.cc $(COMPILE_DEPS) + $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.c $(COMPILE_DEPS) + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ + +$(ObjDir)/%.o: %.m $(COMPILE_DEPS) + $(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ +endif + + +## Rules for building preprocessed (.i/.ii) outputs. +$(BuildMode)/%.ii: %.cpp $(COMPILE_DEPS) + $(Echo) "Compiling $*.cpp for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.ii: %.mm $(COMPILE_DEPS) + $(Echo) "Compiling $*.mm for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.ii: %.cc $(COMPILE_DEPS) + $(Echo) "Compiling $*.cc for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.i: %.c $(COMPILE_DEPS) + $(Echo) "Compiling $*.c for $(BuildMode) build to .i file" + $(Verb) $(Preprocess.C) $< -o $@ + +$(BuildMode)/%.i: %.m $(COMPILE_DEPS) + $(Echo) "Compiling $*.m for $(BuildMode) build to .i file" + $(Verb) $(Preprocess.C) $< -o $@ + + +$(ObjDir)/%.s: %.cpp $(COMPILE_DEPS) + $(Echo) "Compiling $*.cpp to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.mm $(COMPILE_DEPS) + $(Echo) "Compiling $*.mm to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.cc $(COMPILE_DEPS) + $(Echo) "Compiling $*.cc to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.c $(COMPILE_DEPS) + $(Echo) "Compiling $*.c to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ -S + +$(ObjDir)/%.s: %.m $(COMPILE_DEPS) + $(Echo) "Compiling $*.m to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ -S + +############################################################################### +# TABLEGEN: Provide rules for running tblgen to produce *.inc files +############################################################################### + +ifdef TARGET +TABLEGEN_INC_FILES_COMMON = 1 +endif + +ifdef TABLEGEN_INC_FILES_COMMON + +INCFiles := $(filter %.inc,$(BUILT_SOURCES)) +INCTMPFiles := $(INCFiles:%=$(ObjDir)/%.tmp) +.PRECIOUS: $(INCTMPFiles) $(INCFiles) + +# INCFiles rule: All of the tblgen generated files are emitted to +# $(ObjDir)/%.inc.tmp, instead of emitting them directly to %.inc. This allows +# us to only "touch" the real file if the contents of it change. IOW, if +# tblgen is modified, all of the .inc.tmp files are regenerated, but no +# dependencies of the .inc files are, unless the contents of the .inc file +# changes. +$(INCFiles) : %.inc : $(ObjDir)/%.inc.tmp + $(Verb) $(CMP) -s $@ $< || $(CP) $< $@ + +endif # TABLEGEN_INC_FILES_COMMON + +ifdef TARGET + +TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \ + $(LLVM_SRC_ROOT)/include/llvm/Target/Target.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetCallingConv.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSchedule.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSelectionDAG.td \ + $(LLVM_SRC_ROOT)/include/llvm/CodeGen/ValueTypes.td) \ + $(wildcard $(LLVM_SRC_ROOT)/include/llvm/IR/Intrinsics*.td) + +# All .inc.tmp files depend on the .td files. +$(INCTMPFiles) : $(TDFiles) + +$(TARGET:%=$(ObjDir)/%GenRegisterInfo.inc.tmp): \ +$(ObjDir)/%GenRegisterInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN) + $(Echo) "Building $( $@ +else +%.ps: %.dot + $(Echo) "Cannot build $@: The program dot is not installed" +endif + +# This rules ensures that header files that are removed still have a rule for +# which they can be "generated." This allows make to ignore them and +# reproduce the dependency lists. +%.h:: ; +%.hpp:: ; + +# Define clean-local to clean the current directory. Note that this uses a +# very conservative approach ensuring that empty variables do not cause +# errors or disastrous removal. +clean-local:: +ifneq ($(strip $(ObjRootDir)),) + -$(Verb) $(RM) -rf $(ObjRootDir) +endif +ifneq ($(strip $(SHLIBEXT)),) # Extra paranoia - make real sure SHLIBEXT is set + -$(Verb) $(RM) -f *$(SHLIBEXT) +endif + +clean-all-local:: + -$(Verb) $(RM) -rf Debug Release Profile + + +############################################################################### +# DEPENDENCIES: Include the dependency files if we should +############################################################################### +ifndef DISABLE_AUTO_DEPENDENCIES + +# If its not one of the cleaning targets +ifndef IS_CLEANING_TARGET + +# Get the list of dependency files +DependSourceFiles := $(basename $(filter %.cpp %.c %.cc %.m %.mm, $(Sources))) +DependFiles := $(DependSourceFiles:%=$(PROJ_OBJ_DIR)/$(BuildMode)/%.d) + +-include $(DependFiles) "" + +endif + +endif + +############################################################################### +# CHECK: Running the test suite +############################################################################### + +check:: all + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local \ + TESTSUITE=$(TESTSUITE) ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +# An alias dating from when both lit and DejaGNU test runners were used. +check-lit:: check + +check-all:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local-all ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +############################################################################### +# UNITTESTS: Running the unittests test suite +############################################################################### + +unittests:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/unittests" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/unittests/Makefile" ; then \ + $(EchoCmd) Running unittests test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/unittests unitcheck; \ + else \ + $(EchoCmd) No Makefile in unittests directory ; \ + fi ; \ + else \ + $(EchoCmd) No unittests directory ; \ + fi + +############################################################################### +# DISTRIBUTION: Handle construction of a distribution tarball +############################################################################### + +#------------------------------------------------------------------------ +# Define distribution related variables +#------------------------------------------------------------------------ +DistName := $(PROJECT_NAME)-$(PROJ_VERSION) +DistDir := $(PROJ_OBJ_ROOT)/$(DistName) +TopDistDir := $(PROJ_OBJ_ROOT)/$(DistName) +DistTarGZip := $(PROJ_OBJ_ROOT)/$(DistName).tar.gz +DistZip := $(PROJ_OBJ_ROOT)/$(DistName).zip +DistTarBZ2 := $(PROJ_OBJ_ROOT)/$(DistName).tar.bz2 +DistAlways := CREDITS.TXT LICENSE.TXT README.txt README AUTHORS COPYING \ + ChangeLog INSTALL NEWS Makefile Makefile.common Makefile.rules \ + Makefile.config.in configure autoconf +DistOther := $(notdir $(wildcard \ + $(PROJ_SRC_DIR)/*.h \ + $(PROJ_SRC_DIR)/*.td \ + $(PROJ_SRC_DIR)/*.def \ + $(PROJ_SRC_DIR)/*.ll \ + $(PROJ_SRC_DIR)/*.in)) +DistSubDirs := $(SubDirs) +DistSources = $(Sources) $(EXTRA_DIST) +DistFiles = $(DistAlways) $(DistSources) $(DistOther) + +#------------------------------------------------------------------------ +# We MUST build distribution with OBJ_DIR != SRC_DIR +#------------------------------------------------------------------------ +ifeq ($(PROJ_SRC_DIR),$(PROJ_OBJ_DIR)) +dist dist-check dist-clean dist-gzip dist-bzip2 dist-zip :: + $(Echo) ERROR: Target $@ only available with OBJ_DIR != SRC_DIR + +else + +#------------------------------------------------------------------------ +# Prevent attempt to run dist targets from anywhere but the top level +#------------------------------------------------------------------------ +ifneq ($(LEVEL),.) +dist dist-check dist-clean dist-gzip dist-bzip2 dist-zip :: + $(Echo) ERROR: You must run $@ from $(PROJ_OBJ_ROOT) +else + +#------------------------------------------------------------------------ +# Provide the top level targets +#------------------------------------------------------------------------ + +dist-gzip:: $(DistTarGZip) + +$(DistTarGZip) : $(TopDistDir)/.makedistdir + $(Echo) Packing gzipped distribution tar file. + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(TAR) chf - "$(DistName)" | \ + $(GZIP) -c > "$(DistTarGZip)" + +dist-bzip2:: $(DistTarBZ2) + +$(DistTarBZ2) : $(TopDistDir)/.makedistdir + $(Echo) Packing bzipped distribution tar file. + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(TAR) chf - $(DistName) | \ + $(BZIP2) -c >$(DistTarBZ2) + +dist-zip:: $(DistZip) + +$(DistZip) : $(TopDistDir)/.makedistdir + $(Echo) Packing zipped distribution file. + $(Verb) rm -f $(DistZip) + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ZIP) -rq $(DistZip) $(DistName) + +dist :: $(DistTarGZip) $(DistTarBZ2) $(DistZip) + $(Echo) ===== DISTRIBUTION PACKAGING SUCCESSFUL ===== + +DistCheckDir := $(PROJ_OBJ_ROOT)/_distcheckdir + +dist-check:: $(DistTarGZip) + $(Echo) Checking distribution tar file. + $(Verb) if test -d $(DistCheckDir) ; then \ + $(RM) -rf $(DistCheckDir) ; \ + fi + $(Verb) $(MKDIR) $(DistCheckDir) + $(Verb) cd $(DistCheckDir) && \ + $(MKDIR) $(DistCheckDir)/build && \ + $(MKDIR) $(DistCheckDir)/install && \ + gunzip -c $(DistTarGZip) | $(TAR) xf - && \ + cd build && \ + ../$(DistName)/configure --prefix="$(DistCheckDir)/install" \ + --srcdir=../$(DistName) $(DIST_CHECK_CONFIG_OPTIONS) && \ + $(MAKE) all && \ + $(MAKE) check && \ + $(MAKE) unittests && \ + $(MAKE) install && \ + $(MAKE) uninstall && \ + $(MAKE) dist-clean && \ + $(EchoCmd) ===== $(DistTarGZip) Ready For Distribution ===== + +dist-clean:: + $(Echo) Cleaning distribution files + -$(Verb) $(RM) -rf $(DistTarGZip) $(DistTarBZ2) $(DistZip) $(DistName) \ + $(DistCheckDir) + +endif + +#------------------------------------------------------------------------ +# Provide the recursive distdir target for building the distribution directory +#------------------------------------------------------------------------ +distdir: $(DistDir)/.makedistdir +$(DistDir)/.makedistdir: $(DistSources) + $(Verb) if test "$(DistDir)" = "$(TopDistDir)" ; then \ + if test -d "$(DistDir)" ; then \ + find $(DistDir) -type d ! -perm -200 -exec chmod u+w {} ';' || \ + exit 1 ; \ + fi ; \ + $(EchoCmd) Removing old $(DistDir) ; \ + $(RM) -rf $(DistDir); \ + $(EchoCmd) Making 'all' to verify build ; \ + $(MAKE) ENABLE_OPTIMIZED=1 all ; \ + fi + $(Echo) Building Distribution Directory $(DistDir) + $(Verb) $(MKDIR) $(DistDir) + $(Verb) srcdirstrip=`echo "$(PROJ_SRC_DIR)" | sed 's|.|.|g'`; \ + srcrootstrip=`echo "$(PROJ_SRC_ROOT)" | sed 's|.|.|g'`; \ + for file in $(DistFiles) ; do \ + case "$$file" in \ + $(PROJ_SRC_DIR)/*) \ + file=`echo "$$file" | sed "s#^$$srcdirstrip/##"` \ + ;; \ + $(PROJ_SRC_ROOT)/*) \ + file=`echo "$$file" | \ + sed "s#^$$srcrootstrip/##"` \ + ;; \ + esac; \ + if test -f "$(PROJ_SRC_DIR)/$$file" || \ + test -d "$(PROJ_SRC_DIR)/$$file" ; then \ + from_dir="$(PROJ_SRC_DIR)" ; \ + elif test -f "$$file" || test -d "$$file" ; then \ + from_dir=. ; \ + fi ; \ + to_dir=`echo "$$file" | sed -e 's#/[^/]*$$##'` ; \ + if test "$$to_dir" != "$$file" && test "$$to_dir" != "."; then \ + to_dir="$(DistDir)/$$dir"; \ + $(MKDIR) "$$to_dir" ; \ + else \ + to_dir="$(DistDir)"; \ + fi; \ + mid_dir=`echo "$$file" | sed -n -e 's#^\(.*\)/[^/]*$$#\1#p'`; \ + if test -n "$$mid_dir" ; then \ + $(MKDIR) "$$to_dir/$$mid_dir" || exit 1; \ + fi ; \ + if test -d "$$from_dir/$$file"; then \ + if test -d "$(PROJ_SRC_DIR)/$$file" && \ + test "$$from_dir" != "$(PROJ_SRC_DIR)" ; then \ + cd $(PROJ_SRC_DIR) ; \ + $(TAR) cf - $$file --exclude .svn --exclude CVS | \ + ( cd $$to_dir ; $(TAR) xf - ) ; \ + cd $(PROJ_OBJ_DIR) ; \ + else \ + cd $$from_dir ; \ + $(TAR) cf - $$file --exclude .svn --exclude CVS | \ + ( cd $$to_dir ; $(TAR) xf - ) ; \ + cd $(PROJ_OBJ_DIR) ; \ + fi; \ + elif test -f "$$from_dir/$$file" ; then \ + $(CP) -p "$$from_dir/$$file" "$(DistDir)/$$file" || exit 1; \ + elif test -L "$$from_dir/$$file" ; then \ + $(CP) -pd "$$from_dir/$$file" $(DistDir)/$$file || exit 1; \ + elif echo "$(DistAlways)" | grep -v "$$file" >/dev/null ; then \ + $(EchoCmd) "===== WARNING: Distribution Source " \ + "$$from_dir/$$file Not Found!" ; \ + elif test "$(Verb)" != '@' ; then \ + $(EchoCmd) "Skipping non-existent $$from_dir/$$file" ; \ + fi; \ + done + $(Verb) for subdir in $(DistSubDirs) ; do \ + if test "$$subdir" \!= "." ; then \ + new_distdir="$(DistDir)/$$subdir" ; \ + test -d "$$new_distdir" || $(MKDIR) "$$new_distdir" || exit 1; \ + ( cd $$subdir && $(MAKE) ENABLE_OPTIMIZED=1 \ + DistDir="$$new_distdir" distdir ) || exit 1; \ + fi; \ + done + $(Verb) if test "$(DistDir)" = "$(TopDistDir)" ; then \ + $(EchoCmd) Eliminating CVS/.svn directories from distribution ; \ + $(RM) -rf `find $(TopDistDir) -type d \( -name CVS -o \ + -name .svn \) -print` ;\ + $(MAKE) dist-hook ; \ + $(FIND) $(TopDistDir) -type d ! -perm -777 -exec chmod a+rwx {} \; \ + -o ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; \ + -o ! -type d ! -perm -400 -exec chmod a+r {} \; \ + -o ! -type d ! -perm -444 -exec \ + $(SHELL) $(INSTALL_SH) -c -m a+r {} {} \; \ + || chmod -R a+r $(DistDir) ; \ + fi + +# This is invoked by distdir target, define it as a no-op to avoid errors if not +# defined by user. +dist-hook:: + +endif + +############################################################################### +# TOP LEVEL - targets only to apply at the top level directory +############################################################################### + +ifeq ($(LEVEL),.) + +#------------------------------------------------------------------------ +# Install support for the project's include files: +#------------------------------------------------------------------------ +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +install-local:: + $(Echo) Installing include files + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir) + $(Verb) if test -d "$(PROJ_SRC_ROOT)/include" ; then \ + cd $(PROJ_SRC_ROOT)/include && \ + for hdr in `find . -type f \ + '(' -name LICENSE.TXT \ + -o -name '*.def' \ + -o -name '*.h' \ + -o -name '*.inc' \ + -o -name '*.td' \ + ')' -print | grep -v CVS | \ + grep -v .svn` ; do \ + instdir=`dirname "$(DESTDIR)$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/include" ; then \ + cd $(PROJ_OBJ_ROOT)/include && \ + for hdr in `find . -type f \ + '(' -name LICENSE.TXT \ + -o -name '*.def' \ + -o -name '*.h' \ + -o -name '*.inc' \ + -o -name '*.td' \ + ')' -print | grep -v CVS | \ + grep -v .svn` ; do \ + instdir=`dirname "$(DESTDIR)$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +endif + +uninstall-local:: + $(Echo) Uninstalling include files + $(Verb) if [ -d "$(PROJ_SRC_ROOT)/include" ] ; then \ + cd $(PROJ_SRC_ROOT)/include && \ + $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f \ + '!' '(' -name '*~' -o -name '.#*' \ + -o -name '*.in' ')' -print ')' | \ + grep -v CVS | sed 's#^#$(DESTDIR)$(PROJ_includedir)/#'` ; \ + cd $(PROJ_SRC_ROOT)/include && \ + $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f -name '*.in' \ + -print ')' | sed 's#\.in$$##;s#^#$(DESTDIR)$(PROJ_includedir)/#'` ; \ + fi +endif +endif + +check-line-length: + @echo searching for overlength lines in files: $(Sources) + @echo + @echo + egrep -n '.{81}' $(Sources) /dev/null + +check-for-tabs: + @echo searching for tabs in files: $(Sources) + @echo + @echo + egrep -n ' ' $(Sources) /dev/null + +check-footprint: + @ls -l $(LibDir) | awk '\ + BEGIN { sum = 0; } \ + { sum += $$5; } \ + END { printf("Libraries: %6.3f MBytes\n", sum/(1024.0*1024.0)); }' + @ls -l $(ToolDir) | awk '\ + BEGIN { sum = 0; } \ + { sum += $$5; } \ + END { printf("Programs: %6.3f MBytes\n", sum/(1024.0*1024.0)); }' +#------------------------------------------------------------------------ +# Print out the directories used for building +#------------------------------------------------------------------------ +printvars:: + $(Echo) "BuildMode : " '$(BuildMode)' + $(Echo) "PROJ_SRC_ROOT: " '$(PROJ_SRC_ROOT)' + $(Echo) "PROJ_SRC_DIR : " '$(PROJ_SRC_DIR)' + $(Echo) "PROJ_OBJ_ROOT: " '$(PROJ_OBJ_ROOT)' + $(Echo) "PROJ_OBJ_DIR : " '$(PROJ_OBJ_DIR)' + $(Echo) "LLVM_SRC_ROOT: " '$(LLVM_SRC_ROOT)' + $(Echo) "LLVM_OBJ_ROOT: " '$(LLVM_OBJ_ROOT)' + $(Echo) "PROJ_prefix : " '$(PROJ_prefix)' + $(Echo) "PROJ_internal_prefix : " '$(PROJ_internal_prefix)' + $(Echo) "PROJ_bindir : " '$(PROJ_bindir)' + $(Echo) "PROJ_libdir : " '$(PROJ_libdir)' + $(Echo) "PROJ_etcdir : " '$(PROJ_etcdir)' + $(Echo) "PROJ_includedir : " '$(PROJ_includedir)' + $(Echo) "UserTargets : " '$(UserTargets)' + $(Echo) "ObjMakefiles : " '$(ObjMakefiles)' + $(Echo) "SrcMakefiles : " '$(SrcMakefiles)' + $(Echo) "ObjDir : " '$(ObjDir)' + $(Echo) "LibDir : " '$(LibDir)' + $(Echo) "ToolDir : " '$(ToolDir)' + $(Echo) "ExmplDir : " '$(ExmplDir)' + $(Echo) "Sources : " '$(Sources)' + $(Echo) "TDFiles : " '$(TDFiles)' + $(Echo) "INCFiles : " '$(INCFiles)' + $(Echo) "INCTMPFiles : " '$(INCTMPFiles)' + $(Echo) "PreConditions: " '$(PreConditions)' + $(Echo) "Compile.CXX : " '$(Compile.CXX)' + $(Echo) "Compile.C : " '$(Compile.C)' + $(Echo) "Archive : " '$(Archive)' + $(Echo) "YaccFiles : " '$(YaccFiles)' + $(Echo) "LexFiles : " '$(LexFiles)' + $(Echo) "Module : " '$(Module)' + $(Echo) "FilesToConfig: " '$(FilesToConfigPATH)' + $(Echo) "SubDirs : " '$(SubDirs)' + $(Echo) "ProjLibsPaths: " '$(ProjLibsPaths)' + $(Echo) "ProjLibsOptions: " '$(ProjLibsOptions)' + +### +# Debugging + +# General debugging rule, use 'make dbg-print-XXX' to print the +# definition, value and origin of XXX. +make-print-%: + $(error PRINT: $(value $*) = "$($*)" (from $(origin $*))) diff --git a/README.txt b/README.txt new file mode 100644 index 00000000..e957a4dc --- /dev/null +++ b/README.txt @@ -0,0 +1,18 @@ +Low Level Virtual Machine (LLVM) +================================ + +This directory and its subdirectories contain source code for the Low Level +Virtual Machine, a toolkit for the construction of highly optimized compilers, +optimizers, and runtime environments. + +LLVM is open source software. You may freely distribute it under the terms of +the license agreement found in LICENSE.txt. + +Please see the documentation provided in docs/ for further +assistance with LLVM, and in particular docs/GettingStarted.rst for getting +started with LLVM and docs/README.txt for an overview of LLVM's +documentation setup. + +If you're writing a package for LLVM, see docs/Packaging.rst for our +suggestions. + diff --git a/autoconf/AutoRegen.sh b/autoconf/AutoRegen.sh new file mode 100755 index 00000000..cbca7387 --- /dev/null +++ b/autoconf/AutoRegen.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +die() { + echo "$@" 1>&2 + exit 1 +} + +clean() { + echo $1 | sed -e 's/\\//g' +} + +### NOTE: ############################################################ +### These variables specify the tool versions we want to use. +### Periods should be escaped with backslash for use by grep. +### +### If you update these, please also update docs/GettingStarted.rst +want_autoconf_version='2\.60' +want_autoheader_version=$want_autoconf_version +want_aclocal_version='1\.9\.6' +want_libtool_version='1\.5\.22' +### END NOTE ######################################################### + +outfile=configure +configfile=configure.ac + +want_autoconf_version_clean=$(clean $want_autoconf_version) +want_autoheader_version_clean=$(clean $want_autoheader_version) +want_aclocal_version_clean=$(clean $want_aclocal_version) +want_libtool_version_clean=$(clean $want_libtool_version) + +test -d autoconf && test -f autoconf/$configfile && cd autoconf +test -f $configfile || die "Can't find 'autoconf' dir; please cd into it first" +autoconf --version | grep $want_autoconf_version > /dev/null +test $? -eq 0 || die "Your autoconf was not detected as being $want_autoconf_version_clean" +aclocal --version | grep '^aclocal.*'$want_aclocal_version > /dev/null +test $? -eq 0 || die "Your aclocal was not detected as being $want_aclocal_version_clean" +autoheader --version | grep '^autoheader.*'$want_autoheader_version > /dev/null +test $? -eq 0 || die "Your autoheader was not detected as being $want_autoheader_version_clean" +libtool --version | grep $want_libtool_version > /dev/null +test $? -eq 0 || die "Your libtool was not detected as being $want_libtool_version_clean" +echo "" +echo "### NOTE: ############################################################" +echo "### If you get *any* warnings from autoconf below you MUST fix the" +echo "### scripts in the m4 directory because there are future forward" +echo "### compatibility or platform support issues at risk. Please do NOT" +echo "### commit any configure script that was generated with warnings" +echo "### present. You should get just three 'Regenerating..' lines." +echo "######################################################################" +echo "" +echo "Regenerating aclocal.m4 with aclocal $want_aclocal_version_clean" +cwd=`pwd` +aclocal --force -I $cwd/m4 || die "aclocal failed" +echo "Regenerating configure with autoconf $want_autoconf_version_clean" +autoconf --force --warnings=all -o ../$outfile $configfile || die "autoconf failed" +cd .. +echo "Regenerating config.h.in with autoheader $want_autoheader_version_clean" +autoheader --warnings=all -I autoconf -I autoconf/m4 autoconf/$configfile || die "autoheader failed" +exit 0 diff --git a/autoconf/ExportMap.map b/autoconf/ExportMap.map new file mode 100644 index 00000000..17b185fe --- /dev/null +++ b/autoconf/ExportMap.map @@ -0,0 +1,7 @@ +{ + global: main; + __progname; + environ; + + local: *; +}; diff --git a/autoconf/LICENSE.TXT b/autoconf/LICENSE.TXT new file mode 100644 index 00000000..72fdd39e --- /dev/null +++ b/autoconf/LICENSE.TXT @@ -0,0 +1,24 @@ +------------------------------------------------------------------------------ +Autoconf Files +------------------------------------------------------------------------------ +All autoconf files are licensed under the LLVM license with the following +additions: + +llvm/autoconf/install-sh: + This script is licensed under the LLVM license, with the following + additional copyrights and restrictions: + + Copyright 1991 by the Massachusetts Institute of Technology + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation, and that the name of M.I.T. not be used in advertising or + publicity pertaining to distribution of the software without specific, + written prior permission. M.I.T. makes no representations about the + suitability of this software for any purpose. It is provided "as is" + without express or implied warranty. + +Please see the source files for additional copyrights. + diff --git a/autoconf/README.TXT b/autoconf/README.TXT new file mode 100644 index 00000000..3dabdf7b --- /dev/null +++ b/autoconf/README.TXT @@ -0,0 +1,49 @@ +Upgrading Libtool +=============================================================================== + +If you are in the mood to upgrade libtool, you must do the following: + + 1. Get the new version of libtool and put it in + 2. configure/build/install libtool with --prefix= + 3. Copy /ltdl.m4 to llvm/autoconf/m4 + 4. Copy /share/aclocal/libtool.m4 to llvm/autoconf/m4/libtool.m4 + 5. Copy /share/libtool/ltmain.sh to llvm/autoconf/ltmain.sh + 6. Copy /share/libtool/libltdl/ltdl.c to llvm/lib/System + 7. Copy /share/libtool/libltdl/ltdl.h to llvm/lib/System + 8. Edit the ltdl.h file to #include "llvm/Config/config.h" at the very top. You + might also need to resolve some compiler warnings (typically about + comparison of signed vs. unsigned values). But, you won't find out about + those until you build LLVM (step 13). + 9. Edit the llvm/autoconf/m4/libtool.m4 file so that: + a) in AC_PROB_LIBTOOL macro, the value of LIBTOOL is set to + $(top_builddir)/mklib, not $(top_builddir)/libtool + b) in AC_LIBTOOL_SETUP macro, the variable default_ofile is set to + "mklib" instead of "libtool" + c) s/AC_ENABLE_SHARED_DEFAULT/enable_shared_default/g + d) s/AC_ENABLE_STATIC_DEFAULT/enable_static_default/g + e) s/AC_ENABLE_FAST_INSTALL_DEFAULT/enable_fast_install_default/g +10. Run "autoupdate libtool.m4 ltdl.m4" in the llvm/autoconf/m4 directory. + This should correctly update the macro definitions in the libtool m4 + files to match the version of autoconf that LLVM uses. This converts + AC_HELP_STRING to AS_HELP_STRING and AC_TRY_LINK to AC_LINK_IFELSE, amongst + other things. You may need to manually adjust the files. +11. Run AutoRegen.sh to get the new macros into configure script +12. If there are any warnings from AutoRegen.sh, go to step 9. +13. Rebuild LLVM, making sure it reconfigures +14. Test the JIT which uses libltdl +15. If it all works, only THEN commit the changes. + +Upgrading autoconf +=============================================================================== + +If you are in the mood to upgrade autoconf, you should: + + 1. Consider not upgrading. + 2. No really, this is a hassle, you don't want to do it. + 3. Get the new version of autoconf and put it in + 4. configure/build/install autoconf with --prefix= + 5. Run autoupdate on all the m4 macros in llvm/autoconf/m4 + 6. Run autoupdate on llvm/autoconf/configure.ac + 7. Regenerate configure script with AutoRegen.sh + 8. If there are any warnings from AutoRegen.sh, fix them and go to step 7. + 9. Test, test, test. diff --git a/autoconf/config.guess b/autoconf/config.guess new file mode 100755 index 00000000..370da42d --- /dev/null +++ b/autoconf/config.guess @@ -0,0 +1,1523 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-08-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/autoconf/config.sub b/autoconf/config.sub new file mode 100755 index 00000000..a8d85281 --- /dev/null +++ b/autoconf/config.sub @@ -0,0 +1,1768 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-11-02' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | aarch64 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | hexagon \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | aarch64-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hexagon-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/autoconf/configure.ac b/autoconf/configure.ac new file mode 100644 index 00000000..7b4bae7e --- /dev/null +++ b/autoconf/configure.ac @@ -0,0 +1,1995 @@ +dnl === configure.ac --------------------------------------------------------=== +dnl The LLVM Compiler Infrastructure +dnl +dnl This file is distributed under the University of Illinois Open Source +dnl License. See LICENSE.TXT for details. +dnl +dnl===-----------------------------------------------------------------------=== +dnl This is the LLVM configuration script. It is processed by the autoconf +dnl program to produce a script named configure. This script contains the +dnl configuration checks that LLVM needs in order to support multiple platforms. +dnl This file is composed of 10 sections per the recommended organization of +dnl autoconf input defined in the autoconf documentation. As this file evolves, +dnl please keep the various types of checks within their sections. The sections +dnl are as follows: +dnl +dnl SECTION 1: Initialization & Setup +dnl SECTION 2: Architecture, target, and host checks +dnl SECTION 3: Command line arguments for the configure script. +dnl SECTION 4: Check for programs we need and that they are the right version +dnl SECTION 5: Check for libraries +dnl SECTION 6: Check for header files +dnl SECTION 7: Check for types and structures +dnl SECTION 8: Check for specific functions needed +dnl SECTION 9: Additional checks, variables, etc. +dnl SECTION 10: Specify the output files and generate it +dnl +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 1: Initialization & Setup +dnl=== +dnl===-----------------------------------------------------------------------=== +dnl Initialize autoconf and define the package name, version number and +dnl address for reporting bugs. + +AC_INIT([LLVM],[3.4.1],[http://llvm.org/bugs/]) + +LLVM_VERSION_MAJOR=3 +LLVM_VERSION_MINOR=4 +LLVM_VERSION_PATCH=1 +LLVM_VERSION_SUFFIX= + +AC_DEFINE_UNQUOTED([LLVM_VERSION_MAJOR], $LLVM_VERSION_MAJOR, [Major version of the LLVM API]) +AC_DEFINE_UNQUOTED([LLVM_VERSION_MINOR], $LLVM_VERSION_MINOR, [Minor version of the LLVM API]) +AC_DEFINE_UNQUOTED([LLVM_VERSION_PATCH], $LLVM_VERSION_PATCH, [Patch version of the LLVM API]) + +AC_SUBST([LLVM_VERSION_MAJOR]) +AC_SUBST([LLVM_VERSION_MINOR]) +AC_SUBST([LLVM_VERSION_PATCH]) +AC_SUBST([LLVM_VERSION_SUFFIX]) + +dnl Provide a copyright substitution and ensure the copyright notice is included +dnl in the output of --version option of the generated configure script. +AC_SUBST(LLVM_COPYRIGHT,["Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign."]) +AC_COPYRIGHT([Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign.]) + +dnl Indicate that we require autoconf 2.60 or later. +AC_PREREQ(2.60) + +dnl Verify that the source directory is valid. This makes sure that we are +dnl configuring LLVM and not some other package (it validates --srcdir argument) +AC_CONFIG_SRCDIR([lib/IR/Module.cpp]) + +dnl Place all of the extra autoconf files into the config subdirectory. Tell +dnl various tools where the m4 autoconf macros are. +AC_CONFIG_AUX_DIR([autoconf]) + +dnl Quit if the source directory has already been configured. +dnl NOTE: This relies upon undocumented autoconf behavior. +if test ${srcdir} != "." ; then + if test -f ${srcdir}/include/llvm/Config/config.h ; then + AC_MSG_ERROR([Already configured in ${srcdir}]) + fi +fi + +dnl Default to empty (i.e. assigning the null string to) CFLAGS and CXXFLAGS, +dnl instead of the autoconf default (for example, '-g -O2' for CC=gcc). +: ${CFLAGS=} +: ${CXXFLAGS=} + +dnl We need to check for the compiler up here to avoid anything else +dnl starting with a different one. +AC_PROG_CC(clang llvm-gcc gcc) +AC_PROG_CXX(clang++ llvm-g++ g++) +AC_PROG_CPP + +dnl If CXX is Clang, check that it can find and parse C++ standard library +dnl headers. +if test "$CXX" = "clang++" ; then + AC_MSG_CHECKING([whether clang works]) + AC_LANG_PUSH([C++]) + dnl Note that space between 'include' and '(' is required. There's a broken + dnl regex in aclocal that otherwise will think that we call m4's include + dnl builtin. + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +#if __has_include () +#include +#endif +#if __has_include () +#include +#endif +]])], +[ + AC_MSG_RESULT([yes]) +], +[ + AC_MSG_RESULT([no]) + AC_MSG_ERROR([Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler ./configure ...]) +]) + AC_LANG_POP([C++]) +fi + +dnl Configure all of the projects present in our source tree. While we could +dnl just AC_CONFIG_SUBDIRS on the set of directories in projects that have a +dnl configure script, that usage of the AC_CONFIG_SUBDIRS macro is deprecated. +dnl Instead we match on the known projects. + +dnl +dnl One tricky part of doing this is that some projects depend upon other +dnl projects. For example, several projects rely upon the LLVM test suite. +dnl We want to configure those projects first so that their object trees are +dnl created before running the configure scripts of projects that depend upon +dnl them. +dnl + +dnl Several projects use llvm-gcc, so configure that first +if test -d ${srcdir}/projects/llvm-gcc ; then + AC_CONFIG_SUBDIRS([projects/llvm-gcc]) +fi + +dnl Several projects use the LLVM test suite, so configure it next. +if test -d ${srcdir}/projects/test-suite ; then + AC_CONFIG_SUBDIRS([projects/test-suite]) +fi + +dnl llvm-test is the old name of the test-suite, kept here for backwards +dnl compatibility +if test -d ${srcdir}/projects/llvm-test ; then + AC_CONFIG_SUBDIRS([projects/llvm-test]) +fi + +dnl Some projects use poolalloc; configure that next +if test -d ${srcdir}/projects/poolalloc ; then + AC_CONFIG_SUBDIRS([projects/poolalloc]) +fi + +if test -d ${srcdir}/projects/llvm-poolalloc ; then + AC_CONFIG_SUBDIRS([projects/llvm-poolalloc]) +fi + +dnl Check for all other projects +for i in `ls ${srcdir}/projects` +do + if test -d ${srcdir}/projects/${i} ; then + case ${i} in + sample) AC_CONFIG_SUBDIRS([projects/sample]) ;; + privbracket) AC_CONFIG_SUBDIRS([projects/privbracket]) ;; + llvm-stacker) AC_CONFIG_SUBDIRS([projects/llvm-stacker]) ;; + llvm-reopt) AC_CONFIG_SUBDIRS([projects/llvm-reopt]);; + llvm-java) AC_CONFIG_SUBDIRS([projects/llvm-java]) ;; + llvm-tv) AC_CONFIG_SUBDIRS([projects/llvm-tv]) ;; + safecode) AC_CONFIG_SUBDIRS([projects/safecode]) ;; + llvm-kernel) AC_CONFIG_SUBDIRS([projects/llvm-kernel]) ;; + compiler-rt) ;; + llvm-gcc) ;; + test-suite) ;; + llvm-test) ;; + poolalloc) ;; + llvm-poolalloc) ;; + *) + AC_MSG_WARN([Unknown project (${i}) won't be configured automatically]) + ;; + esac + fi +done + +dnl Disable the build of polly, even if it is checked out into tools/polly. +AC_ARG_ENABLE(polly, + AS_HELP_STRING([--enable-polly], + [Use polly if available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_POLLY,[1]) ;; + no) AC_SUBST(ENABLE_POLLY,[0]) ;; + default) AC_SUBST(ENABLE_POLLY,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-polly. Use "yes" or "no"]) ;; +esac + + +dnl Check if polly is checked out into tools/polly and configure it if +dnl available. +if (test -d ${srcdir}/tools/polly) && (test $ENABLE_POLLY -eq 1) ; then + AC_SUBST(LLVM_HAS_POLLY,1) + AC_CONFIG_SUBDIRS([tools/polly]) +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 2: Architecture, target, and host checks +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Check the target for which we're compiling and the host that will do the +dnl compilations. This will tell us which LLVM compiler will be used for +dnl compiling SSA into object code. This needs to be done early because +dnl following tests depend on it. +AC_CANONICAL_TARGET + +dnl Determine the platform type and cache its value. This helps us configure +dnl the System library to the correct build platform. +AC_CACHE_CHECK([type of operating system we're going to host on], + [llvm_cv_os_type], +[case $host in + *-*-aix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="AIX" + llvm_cv_platform_type="Unix" ;; + *-*-irix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="IRIX" + llvm_cv_platform_type="Unix" ;; + *-*-cygwin*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Cygwin" + llvm_cv_platform_type="Unix" ;; + *-*-darwin*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Darwin" + llvm_cv_platform_type="Unix" ;; + *-*-minix*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Minix" + llvm_cv_platform_type="Unix" ;; + *-*-freebsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="FreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-kfreebsd-gnu) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="GNU/kFreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-openbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="OpenBSD" + llvm_cv_platform_type="Unix" ;; + *-*-netbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="NetBSD" + llvm_cv_platform_type="Unix" ;; + *-*-dragonfly*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="DragonFly" + llvm_cv_platform_type="Unix" ;; + *-*-hpux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="HP-UX" + llvm_cv_platform_type="Unix" ;; + *-*-interix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Interix" + llvm_cv_platform_type="Unix" ;; + *-*-linux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Linux" + llvm_cv_platform_type="Unix" ;; + *-*-gnu*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="GNU" + llvm_cv_platform_type="Unix" ;; + *-*-solaris*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_no_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="SunOS" + llvm_cv_platform_type="Unix" ;; + *-*-auroraux*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="AuroraUX" + llvm_cv_platform_type="Unix" ;; + *-*-win32*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Win32" + llvm_cv_platform_type="Win32" ;; + *-*-mingw*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="MingW" + llvm_cv_platform_type="Win32" ;; + *-*-haiku*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Haiku" + llvm_cv_platform_type="Unix" ;; + *-unknown-eabi*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *-unknown-elf*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *) + llvm_cv_link_all_option="" + llvm_cv_no_link_all_option="" + llvm_cv_os_type="Unknown" + llvm_cv_platform_type="Unknown" ;; +esac]) + +AC_CACHE_CHECK([type of operating system we're going to target], + [llvm_cv_target_os_type], +[case $target in + *-*-aix*) + llvm_cv_target_os_type="AIX" ;; + *-*-irix*) + llvm_cv_target_os_type="IRIX" ;; + *-*-cygwin*) + llvm_cv_target_os_type="Cygwin" ;; + *-*-darwin*) + llvm_cv_target_os_type="Darwin" ;; + *-*-minix*) + llvm_cv_target_os_type="Minix" ;; + *-*-freebsd*) + llvm_cv_target_os_type="FreeBSD" ;; + *-*-kfreebsd-gnu) + llvm_cv_target_os_type="GNU/kFreeBSD" ;; + *-*-openbsd*) + llvm_cv_target_os_type="OpenBSD" ;; + *-*-netbsd*) + llvm_cv_target_os_type="NetBSD" ;; + *-*-dragonfly*) + llvm_cv_target_os_type="DragonFly" ;; + *-*-hpux*) + llvm_cv_target_os_type="HP-UX" ;; + *-*-interix*) + llvm_cv_target_os_type="Interix" ;; + *-*-linux*) + llvm_cv_target_os_type="Linux" ;; + *-*-gnu*) + llvm_cv_target_os_type="GNU" ;; + *-*-solaris*) + llvm_cv_target_os_type="SunOS" ;; + *-*-auroraux*) + llvm_cv_target_os_type="AuroraUX" ;; + *-*-win32*) + llvm_cv_target_os_type="Win32" ;; + *-*-mingw*) + llvm_cv_target_os_type="MingW" ;; + *-*-haiku*) + llvm_cv_target_os_type="Haiku" ;; + *-*-rtems*) + llvm_cv_target_os_type="RTEMS" ;; + *-*-nacl*) + llvm_cv_target_os_type="NativeClient" ;; + *-unknown-eabi*) + llvm_cv_target_os_type="Freestanding" ;; + *) + llvm_cv_target_os_type="Unknown" ;; +esac]) + +dnl Make sure we aren't attempting to configure for an unknown system +if test "$llvm_cv_os_type" = "Unknown" ; then + AC_MSG_ERROR([Operating system is unknown, configure can't continue]) +fi + +dnl Set the "OS" Makefile variable based on the platform type so the +dnl makefile can configure itself to specific build hosts +AC_SUBST(OS,$llvm_cv_os_type) +AC_SUBST(HOST_OS,$llvm_cv_os_type) +AC_SUBST(TARGET_OS,$llvm_cv_target_os_type) + +dnl Set the LINKALL and NOLINKALL Makefile variables based on the platform +AC_SUBST(LINKALL,$llvm_cv_link_all_option) +AC_SUBST(NOLINKALL,$llvm_cv_no_link_all_option) + +dnl Set the "LLVM_ON_*" variables based on llvm_cv_platform_type +dnl This is used by lib/Support to determine the basic kind of implementation +dnl to use. +case $llvm_cv_platform_type in + Unix) + AC_DEFINE([LLVM_ON_UNIX],[1],[Define if this is Unixish platform]) + AC_SUBST(LLVM_ON_UNIX,[1]) + AC_SUBST(LLVM_ON_WIN32,[0]) + ;; + Win32) + AC_DEFINE([LLVM_ON_WIN32],[1],[Define if this is Win32ish platform]) + AC_SUBST(LLVM_ON_UNIX,[0]) + AC_SUBST(LLVM_ON_WIN32,[1]) + ;; +esac + +dnl Determine what our target architecture is and configure accordingly. +dnl This will allow Makefiles to make a distinction between the hardware and +dnl the OS. +AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], +[case $target in + i?86-*) llvm_cv_target_arch="x86" ;; + amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;; + sparc*-*) llvm_cv_target_arch="Sparc" ;; + powerpc*-*) llvm_cv_target_arch="PowerPC" ;; + arm*-*) llvm_cv_target_arch="ARM" ;; + aarch64*-*) llvm_cv_target_arch="AArch64" ;; + mips-* | mips64-*) llvm_cv_target_arch="Mips" ;; + mipsel-* | mips64el-*) llvm_cv_target_arch="Mips" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; + msp430-*) llvm_cv_target_arch="MSP430" ;; + hexagon-*) llvm_cv_target_arch="Hexagon" ;; + nvptx-*) llvm_cv_target_arch="NVPTX" ;; + s390x-*) llvm_cv_target_arch="SystemZ" ;; + *) llvm_cv_target_arch="Unknown" ;; +esac]) + +if test "$llvm_cv_target_arch" = "Unknown" ; then + AC_MSG_WARN([Configuring LLVM for an unknown target archicture]) +fi + +dnl Determine the LLVM native architecture for the target +case "$llvm_cv_target_arch" in + x86) LLVM_NATIVE_ARCH="X86" ;; + x86_64) LLVM_NATIVE_ARCH="X86" ;; + *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;; +esac + +dnl Define a substitution, ARCH, for the target architecture +AC_SUBST(ARCH,$llvm_cv_target_arch) + +dnl Determine what our host architecture. +dnl This will allow MCJIT regress tests runs only for supported +dnl platforms. +case $host in + i?86-*) host_arch="x86" ;; + amd64-* | x86_64-*) host_arch="x86_64" ;; + sparc*-*) host_arch="Sparc" ;; + powerpc*-*) host_arch="PowerPC" ;; + arm*-*) host_arch="ARM" ;; + aarch64*-*) host_arch="AArch64" ;; + mips-* | mips64-*) host_arch="Mips" ;; + mipsel-* | mips64el-*) host_arch="Mips" ;; + xcore-*) host_arch="XCore" ;; + msp430-*) host_arch="MSP430" ;; + hexagon-*) host_arch="Hexagon" ;; + s390x-*) host_arch="SystemZ" ;; + *) host_arch="Unknown" ;; +esac + +if test "$host_arch" = "Unknown" ; then + AC_MSG_WARN([Configuring LLVM for an unknown host archicture]) +fi + +AC_SUBST(HOST_ARCH,$host_arch) + +dnl Check for the endianness of the target +AC_C_BIGENDIAN(AC_SUBST([ENDIAN],[big]),AC_SUBST([ENDIAN],[little])) + +dnl Check for build platform executable suffix if we're cross-compiling +if test "$cross_compiling" = yes; then + AC_SUBST(LLVM_CROSS_COMPILING, [1]) + AC_BUILD_EXEEXT + ac_build_prefix=${build_alias}- + AC_CHECK_PROG(BUILD_CXX, ${ac_build_prefix}g++, ${ac_build_prefix}g++) + if test -z "$BUILD_CXX"; then + AC_CHECK_PROG(BUILD_CXX, g++, g++) + if test -z "$BUILD_CXX"; then + AC_CHECK_PROG(BUILD_CXX, c++, c++, , , /usr/ucb/c++) + fi + fi +else + AC_SUBST(LLVM_CROSS_COMPILING, [0]) +fi + +dnl Check to see if there's a .svn or .git directory indicating that this +dnl build is being done from a checkout. This sets up several defaults for +dnl the command line switches. When we build with a checkout directory, +dnl we get a debug with assertions turned on. Without, we assume a source +dnl release and we get an optimized build without assertions. +dnl See --enable-optimized and --enable-assertions below +if test -d ".svn" -o -d "${srcdir}/.svn" -o -d ".git" -o -d "${srcdir}/.git"; then + cvsbuild="yes" + optimize="no" + AC_SUBST(CVSBUILD,[[CVSBUILD=1]]) +else + cvsbuild="no" + optimize="yes" +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 3: Command line arguments for the configure script. +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl --enable-libcpp : check whether or not to use libc++ on the command line +AC_ARG_ENABLE(libcpp, + AS_HELP_STRING([--enable-libcpp], + [Use libc++ if available (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_LIBCPP,[1]) ;; + no) AC_SUBST(ENABLE_LIBCPP,[0]) ;; + default) AC_SUBST(ENABLE_LIBCPP,[0]);; + *) AC_MSG_ERROR([Invalid setting for --enable-libcpp. Use "yes" or "no"]) ;; +esac + +dnl --enable-cxx11 : check whether or not to use -std=c++11 on the command line +AC_ARG_ENABLE(cxx11, + AS_HELP_STRING([--enable-cxx11], + [Use c++11 if available (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_CXX11,[1]) ;; + no) AC_SUBST(ENABLE_CXX11,[0]) ;; + default) AC_SUBST(ENABLE_CXX11,[0]);; + *) AC_MSG_ERROR([Invalid setting for --enable-cxx11. Use "yes" or "no"]) ;; +esac + +dnl --enable-fission : check whether or not to use -gsplit-dwarf on the command +dnl line +AC_ARG_ENABLE(split-dwarf, + AS_HELP_STRING([--enable-split-dwarf], + [Use split-dwarf if available (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_SPLIT_DWARF,[1]) ;; + no) AC_SUBST(ENABLE_SPLIT_DWARF,[0]) ;; + default) AC_SUBST(ENABLE_SPLIT_DWARF,[0]);; + *) AC_MSG_ERROR([Invalid setting for --enable-split-dwarf. Use "yes" or "no"]) ;; +esac + +dnl --enable-clang-arcmt: check whether to enable clang arcmt +clang_arcmt="yes" +AC_ARG_ENABLE(clang-arcmt, + AS_HELP_STRING([--enable-clang-arcmt], + [Enable building of clang ARCMT (default is YES)]), + clang_arcmt="$enableval", + enableval="yes") +case "$enableval" in + yes) AC_SUBST(ENABLE_CLANG_ARCMT,[1]) ;; + no) AC_SUBST(ENABLE_CLANG_ARCMT,[0]) ;; + default) AC_SUBST(ENABLE_CLANG_ARCMT,[1]);; + *) AC_MSG_ERROR([Invalid setting for --enable-clang-arcmt. Use "yes" or "no"]) ;; +esac + +dnl --enable-clang-static-analyzer: check whether to enable static-analyzer +clang_static_analyzer="yes" +AC_ARG_ENABLE(clang-static-analyzer, + AS_HELP_STRING([--enable-clang-static-analyzer], + [Enable building of clang Static Analyzer (default is YES)]), + clang_static_analyzer="$enableval", + enableval="yes") +case "$enableval" in + yes) AC_SUBST(ENABLE_CLANG_STATIC_ANALYZER,[1]) ;; + no) + if test ${clang_arcmt} != "no" ; then + AC_MSG_ERROR([Cannot enable clang ARC Migration Tool while disabling static analyzer.]) + fi + AC_SUBST(ENABLE_CLANG_STATIC_ANALYZER,[0]) + ;; + default) AC_SUBST(ENABLE_CLANG_STATIC_ANALYZER,[1]);; + *) AC_MSG_ERROR([Invalid setting for --enable-clang-static-analyzer. Use "yes" or "no"]) ;; +esac + +dnl --enable-clang-rewriter: check whether to enable clang rewriter +AC_ARG_ENABLE(clang-rewriter, + AS_HELP_STRING([--enable-clang-rewriter], + [Enable building of clang rewriter (default is YES)]),, + enableval="yes") +case "$enableval" in + yes) AC_SUBST(ENABLE_CLANG_REWRITER,[1]) ;; + no) + if test ${clang_arcmt} != "no" ; then + AC_MSG_ERROR([Cannot enable clang ARC Migration Tool while disabling rewriter.]) + fi + if test ${clang_static_analyzer} != "no" ; then + AC_MSG_ERROR([Cannot enable clang static analyzer while disabling rewriter.]) + fi + AC_SUBST(ENABLE_CLANG_REWRITER,[0]) + ;; + default) AC_SUBST(ENABLE_CLANG_REWRITER,[1]);; + *) AC_MSG_ERROR([Invalid setting for --enable-clang-rewriter. Use "yes" or "no"]) ;; +esac + +dnl --enable-optimized : check whether they want to do an optimized build: +AC_ARG_ENABLE(optimized, AS_HELP_STRING( + --enable-optimized,[Compile with optimizations enabled (default is NO)]),,enableval=$optimize) +if test ${enableval} = "no" ; then + AC_SUBST(ENABLE_OPTIMIZED,[[]]) +else + AC_SUBST(ENABLE_OPTIMIZED,[[ENABLE_OPTIMIZED=1]]) +fi + +dnl --enable-profiling : check whether they want to do a profile build: +AC_ARG_ENABLE(profiling, AS_HELP_STRING( + --enable-profiling,[Compile with profiling enabled (default is NO)]),,enableval="no") +if test ${enableval} = "no" ; then + AC_SUBST(ENABLE_PROFILING,[[]]) +else + AC_SUBST(ENABLE_PROFILING,[[ENABLE_PROFILING=1]]) +fi + +dnl --enable-assertions : check whether they want to turn on assertions or not: +AC_ARG_ENABLE(assertions,AS_HELP_STRING( + --enable-assertions,[Compile with assertion checks enabled (default is YES)]),, enableval="yes") +if test ${enableval} = "yes" ; then + AC_SUBST(DISABLE_ASSERTIONS,[[]]) +else + AC_SUBST(DISABLE_ASSERTIONS,[[DISABLE_ASSERTIONS=1]]) +fi + +dnl --enable-werror : check whether we want Werror on by default +AC_ARG_ENABLE(werror,AS_HELP_STRING( + --enable-werror,[Compile with -Werror enabled (default is NO)]),, enableval="no") +case "$enableval" in + yes) AC_SUBST(ENABLE_WERROR,[1]) ;; + no) AC_SUBST(ENABLE_WERROR,[0]) ;; + default) AC_SUBST(ENABLE_WERROR,[0]);; + *) AC_MSG_ERROR([Invalid setting for --enable-werror. Use "yes" or "no"]) ;; +esac + +dnl --enable-expensive-checks : check whether they want to turn on expensive debug checks: +AC_ARG_ENABLE(expensive-checks,AS_HELP_STRING( + --enable-expensive-checks,[Compile with expensive debug checks enabled (default is NO)]),, enableval="no") +if test ${enableval} = "yes" ; then + AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[ENABLE_EXPENSIVE_CHECKS=1]]) + AC_SUBST(EXPENSIVE_CHECKS,[[yes]]) +else + AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[]]) + AC_SUBST(EXPENSIVE_CHECKS,[[no]]) +fi + +dnl --enable-debug-runtime : should runtime libraries have debug symbols? +AC_ARG_ENABLE(debug-runtime, + AS_HELP_STRING(--enable-debug-runtime,[Build runtime libs with debug symbols (default is NO)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(DEBUG_RUNTIME,[[]]) +else + AC_SUBST(DEBUG_RUNTIME,[[DEBUG_RUNTIME=1]]) +fi + +dnl --enable-debug-symbols : should even optimized compiler libraries +dnl have debug symbols? +AC_ARG_ENABLE(debug-symbols, + AS_HELP_STRING(--enable-debug-symbols,[Build compiler with debug symbols (default is NO if optimization is on and YES if it's off)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(DEBUG_SYMBOLS,[[]]) +else + AC_SUBST(DEBUG_SYMBOLS,[[DEBUG_SYMBOLS=1]]) +fi + +dnl --enable-keep-symbols : do not strip installed executables +AC_ARG_ENABLE(keep-symbols, + AS_HELP_STRING(--enable-keep-symbols,[Do not strip installed executables)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(KEEP_SYMBOLS,[[]]) +else + AC_SUBST(KEEP_SYMBOLS,[[KEEP_SYMBOLS=1]]) +fi + +dnl --enable-jit: check whether they want to enable the jit +AC_ARG_ENABLE(jit, + AS_HELP_STRING(--enable-jit, + [Enable Just In Time Compiling (default is YES)]),, + enableval=default) +if test ${enableval} = "no" +then + AC_SUBST(JIT,[[]]) +else + case "$llvm_cv_target_arch" in + x86) AC_SUBST(TARGET_HAS_JIT,1) ;; + Sparc) AC_SUBST(TARGET_HAS_JIT,0) ;; + PowerPC) AC_SUBST(TARGET_HAS_JIT,1) ;; + x86_64) AC_SUBST(TARGET_HAS_JIT,1) ;; + ARM) AC_SUBST(TARGET_HAS_JIT,1) ;; + AArch64) AC_SUBST(TARGET_HAS_JIT,0) ;; + Mips) AC_SUBST(TARGET_HAS_JIT,1) ;; + XCore) AC_SUBST(TARGET_HAS_JIT,0) ;; + MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;; + Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;; + NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;; + SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;; + *) AC_SUBST(TARGET_HAS_JIT,0) ;; + esac +fi + +dnl Allow enablement of building and installing docs +AC_ARG_ENABLE(docs, + AS_HELP_STRING([--enable-docs], + [Build documents (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_DOCS,[1]) ;; + no) AC_SUBST(ENABLE_DOCS,[0]) ;; + default) AC_SUBST(ENABLE_DOCS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-docs. Use "yes" or "no"]) ;; +esac + +dnl Allow enablement of doxygen generated documentation +AC_ARG_ENABLE(doxygen, + AS_HELP_STRING([--enable-doxygen], + [Build doxygen documentation (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_DOXYGEN,[1]) ;; + no) AC_SUBST(ENABLE_DOXYGEN,[0]) ;; + default) AC_SUBST(ENABLE_DOXYGEN,[0]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-doxygen. Use "yes" or "no"]) ;; +esac + +dnl Allow disablement of threads +AC_ARG_ENABLE(threads, + AS_HELP_STRING([--enable-threads], + [Use threads if available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(LLVM_ENABLE_THREADS,[1]) ;; + no) AC_SUBST(LLVM_ENABLE_THREADS,[0]) ;; + default) AC_SUBST(LLVM_ENABLE_THREADS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-threads. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([LLVM_ENABLE_THREADS],$LLVM_ENABLE_THREADS, + [Define if threads enabled]) + +dnl Allow disablement of pthread.h +AC_ARG_ENABLE(pthreads, + AS_HELP_STRING([--enable-pthreads], + [Use pthreads if available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_PTHREADS,[1]) ;; + no) AC_SUBST(ENABLE_PTHREADS,[0]) ;; + default) AC_SUBST(ENABLE_PTHREADS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-pthreads. Use "yes" or "no"]) ;; +esac + +dnl Allow disablement of zlib +AC_ARG_ENABLE(zlib, + AS_HELP_STRING([--enable-zlib], + [Use zlib for compression/decompression if + available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(LLVM_ENABLE_ZLIB,[1]) ;; + no) AC_SUBST(LLVM_ENABLE_ZLIB,[0]) ;; + default) AC_SUBST(LLVM_ENABLE_ZLIB,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-zlib. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([LLVM_ENABLE_ZLIB],$LLVM_ENABLE_ZLIB, + [Define if zlib is enabled]) + +dnl Allow building without position independent code +AC_ARG_ENABLE(pic, + AS_HELP_STRING([--enable-pic], + [Build LLVM with Position Independent Code (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_PIC,[1]) ;; + no) AC_SUBST(ENABLE_PIC,[0]) ;; + default) AC_SUBST(ENABLE_PIC,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-pic. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_PIC],$ENABLE_PIC, + [Define if position independent code is enabled]) + +dnl Allow building a shared library and linking tools against it. +AC_ARG_ENABLE(shared, + AS_HELP_STRING([--enable-shared], + [Build a shared library and link tools against it (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_SHARED,[1]) ;; + no) AC_SUBST(ENABLE_SHARED,[0]) ;; + default) AC_SUBST(ENABLE_SHARED,[0]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-shared. Use "yes" or "no"]) ;; +esac + +dnl Allow libstdc++ is embedded in LLVM.dll. +AC_ARG_ENABLE(embed-stdcxx, + AS_HELP_STRING([--enable-embed-stdcxx], + [Build a shared library with embedded libstdc++ for Win32 DLL (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_EMBED_STDCXX,[1]) ;; + no) AC_SUBST(ENABLE_EMBED_STDCXX,[0]) ;; + default) AC_SUBST(ENABLE_EMBED_STDCXX,[0]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-embed-stdcxx. Use "yes" or "no"]) ;; +esac + +dnl Enable embedding timestamp information into build. +AC_ARG_ENABLE(timestamps, + AS_HELP_STRING([--enable-timestamps], + [Enable embedding timestamp information in build (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_TIMESTAMPS,[1]) ;; + no) AC_SUBST(ENABLE_TIMESTAMPS,[0]) ;; + default) AC_SUBST(ENABLE_TIMESTAMPS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-timestamps. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_TIMESTAMPS],$ENABLE_TIMESTAMPS, + [Define if timestamp information (e.g., __DATE__) is allowed]) + +dnl Enable support for showing backtraces. +AC_ARG_ENABLE(backtraces, AS_HELP_STRING( + [--enable-backtraces], + [Enable embedding backtraces on crash (default is YES)]), + [case "$enableval" in + yes) llvm_cv_enable_backtraces="yes" ;; + no) llvm_cv_enable_backtraces="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-backtraces. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_backtraces="yes") +if test "$llvm_cv_enable_backtraces" = "yes" ; then + AC_DEFINE([ENABLE_BACKTRACES],[1], + [Define if you want backtraces on crash]) +fi + +dnl Enable installing platform specific signal handling overrides, for improved +dnl CrashRecovery support or interaction with crash reporting software. This +dnl support may be inappropriate for some clients embedding LLVM as a library. +AC_ARG_ENABLE(crash-overrides, AS_HELP_STRING( + [--enable-crash-overrides], + [Enable crash handling overrides (default is YES)]), + [case "$enableval" in + yes) llvm_cv_enable_crash_overrides="yes" ;; + no) llvm_cv_enable_crash_overrides="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-crash-overrides. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_crash_overrides="yes") +if test "$llvm_cv_enable_crash_overrides" = "yes" ; then + AC_DEFINE([ENABLE_CRASH_OVERRIDES],[1], + [Define to enable crash handling overrides]) +fi + +dnl Allow specific targets to be specified for building (or not) +TARGETS_TO_BUILD="" +AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], + [Build specific host targets: all or target1,target2,... Valid targets are: + host, x86, x86_64, sparc, powerpc, arm, aarch64, mips, hexagon, + xcore, msp430, nvptx, systemz, r600, and cpp (default=all)]),, + enableval=all) +if test "$enableval" = host-only ; then + enableval=host +fi +case "$enableval" in + all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;; + *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_target" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + powerpc) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + aarch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;; + arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + mipsel) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + mips64) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + mips64el) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; + nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; + systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;; + host) case "$llvm_cv_target_arch" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + Sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + PowerPC) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + AArch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;; + ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; + NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; + SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + *) AC_MSG_ERROR([Can not set target to build]) ;; + esac ;; + *) AC_MSG_ERROR([Unrecognized target $a_target]) ;; + esac + done + ;; +esac + +AC_ARG_ENABLE([experimental-targets],AS_HELP_STRING([--enable-experimental-targets], + [Build experimental host targets: disable or target1,target2,... + (default=disable)]),, + enableval=disable) + +if test ${enableval} != "disable" +then + TARGETS_TO_BUILD="$enableval $TARGETS_TO_BUILD" +fi + +AC_SUBST(TARGETS_TO_BUILD,$TARGETS_TO_BUILD) + +dnl Determine whether we are building LLVM support for the native architecture. +dnl If so, define LLVM_NATIVE_ARCH to that LLVM target. +for a_target in $TARGETS_TO_BUILD; do + if test "$a_target" = "$LLVM_NATIVE_ARCH"; then + AC_DEFINE_UNQUOTED(LLVM_NATIVE_ARCH, $LLVM_NATIVE_ARCH, + [LLVM architecture name for the native architecture, if available]) + LLVM_NATIVE_TARGET="LLVMInitialize${LLVM_NATIVE_ARCH}Target" + LLVM_NATIVE_TARGETINFO="LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo" + LLVM_NATIVE_TARGETMC="LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC" + LLVM_NATIVE_ASMPRINTER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter" + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then + LLVM_NATIVE_ASMPARSER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser" + fi + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/Disassembler/Makefile ; then + LLVM_NATIVE_DISASSEMBLER="LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler" + fi + AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGET, $LLVM_NATIVE_TARGET, + [LLVM name for the native Target init function, if available]) + AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGETINFO, $LLVM_NATIVE_TARGETINFO, + [LLVM name for the native TargetInfo init function, if available]) + AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGETMC, $LLVM_NATIVE_TARGETMC, + [LLVM name for the native target MC init function, if available]) + AC_DEFINE_UNQUOTED(LLVM_NATIVE_ASMPRINTER, $LLVM_NATIVE_ASMPRINTER, + [LLVM name for the native AsmPrinter init function, if available]) + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then + AC_DEFINE_UNQUOTED(LLVM_NATIVE_ASMPARSER, $LLVM_NATIVE_ASMPARSER, + [LLVM name for the native AsmParser init function, if available]) + fi + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/Disassembler/Makefile ; then + AC_DEFINE_UNQUOTED(LLVM_NATIVE_DISASSEMBLER, $LLVM_NATIVE_DISASSEMBLER, + [LLVM name for the native Disassembler init function, if available]) + fi + fi +done + +dnl Build the LLVM_TARGET and LLVM_... macros for Targets.def and the individual +dnl target feature def files. +LLVM_ENUM_TARGETS="" +LLVM_ENUM_ASM_PRINTERS="" +LLVM_ENUM_ASM_PARSERS="" +LLVM_ENUM_DISASSEMBLERS="" +for target_to_build in $TARGETS_TO_BUILD; do + LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS" + if test -f ${srcdir}/lib/Target/${target_to_build}/*AsmPrinter.cpp ; then + LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmParser/Makefile ; then + LLVM_ENUM_ASM_PARSERS="LLVM_ASM_PARSER($target_to_build) $LLVM_ENUM_ASM_PARSERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/Disassembler/Makefile ; then + LLVM_ENUM_DISASSEMBLERS="LLVM_DISASSEMBLER($target_to_build) $LLVM_ENUM_DISASSEMBLERS"; + fi +done +AC_SUBST(LLVM_ENUM_TARGETS) +AC_SUBST(LLVM_ENUM_ASM_PRINTERS) +AC_SUBST(LLVM_ENUM_ASM_PARSERS) +AC_SUBST(LLVM_ENUM_DISASSEMBLERS) + +dnl Override the option to use for optimized builds. +AC_ARG_WITH(optimize-option, + AS_HELP_STRING([--with-optimize-option], + [Select the compiler options to use for optimized builds]),, + withval=default) +AC_MSG_CHECKING([optimization flags]) +case "$withval" in + default) + case "$llvm_cv_os_type" in + FreeBSD) optimize_option=-O2 ;; + MingW) optimize_option=-O2 ;; + *) optimize_option=-O3 ;; + esac ;; + *) optimize_option="$withval" ;; +esac +AC_SUBST(OPTIMIZE_OPTION,$optimize_option) +AC_MSG_RESULT([$optimize_option]) + +dnl Specify extra build options +AC_ARG_WITH(extra-options, + AS_HELP_STRING([--with-extra-options], + [Specify additional options to compile LLVM with]),, + withval=default) +case "$withval" in + default) EXTRA_OPTIONS= ;; + *) EXTRA_OPTIONS=$withval ;; +esac +AC_SUBST(EXTRA_OPTIONS,$EXTRA_OPTIONS) + +dnl Specify extra linker build options +AC_ARG_WITH(extra-ld-options, + AS_HELP_STRING([--with-extra-ld-options], + [Specify additional options to link LLVM with]),, + withval=default) +case "$withval" in + default) EXTRA_LD_OPTIONS= ;; + *) EXTRA_LD_OPTIONS=$withval ;; +esac +AC_SUBST(EXTRA_LD_OPTIONS,$EXTRA_LD_OPTIONS) + +dnl Allow specific bindings to be specified for building (or not) +AC_ARG_ENABLE([bindings],AS_HELP_STRING([--enable-bindings], + [Build specific language bindings: all,auto,none,{binding-name} (default=auto)]),, + enableval=default) +BINDINGS_TO_BUILD="" +case "$enableval" in + yes | default | auto) BINDINGS_TO_BUILD="auto" ;; + all ) BINDINGS_TO_BUILD="ocaml" ;; + none | no) BINDINGS_TO_BUILD="" ;; + *)for a_binding in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_binding" in + ocaml) BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" ;; + *) AC_MSG_ERROR([Unrecognized binding $a_binding]) ;; + esac + done + ;; +esac + +dnl Allow the ocaml libdir to be overridden. This could go in a configure +dnl script for bindings/ocaml/configure, except that its auto value depends on +dnl OCAMLC, which is found here to support tests. +AC_ARG_WITH([ocaml-libdir], + [AS_HELP_STRING([--with-ocaml-libdir], + [Specify install location for ocaml bindings (default is stdlib)])], + [], + [withval=auto]) +case "$withval" in + auto) with_ocaml_libdir="$withval" ;; + /* | [[A-Za-z]]:[[\\/]]*) with_ocaml_libdir="$withval" ;; + *) AC_MSG_ERROR([Invalid path for --with-ocaml-libdir. Provide full path]) ;; +esac + +AC_ARG_WITH(clang-srcdir, + AS_HELP_STRING([--with-clang-srcdir], + [Directory to the out-of-tree Clang source]),, + withval="-") +case "$withval" in + -) clang_src_root="" ;; + /* | [[A-Za-z]]:[[\\/]]*) clang_src_root="$withval" ;; + *) clang_src_root="$ac_pwd/$withval" ;; +esac +AC_SUBST(CLANG_SRC_ROOT,[$clang_src_root]) + +AC_ARG_WITH(clang-resource-dir, + AS_HELP_STRING([--with-clang-resource-dir], + [Relative directory from the Clang binary for resource files]),, + withval="") +AC_DEFINE_UNQUOTED(CLANG_RESOURCE_DIR,"$withval", + [Relative directory for resource files]) + +AC_ARG_WITH(c-include-dirs, + AS_HELP_STRING([--with-c-include-dirs], + [Colon separated list of directories clang will search for headers]),, + withval="") +AC_DEFINE_UNQUOTED(C_INCLUDE_DIRS,"$withval", + [Directories clang will search for headers]) + +# Clang normally uses the system c++ headers and libraries. With this option, +# clang will use the ones provided by a gcc installation instead. This option should +# be passed the same value that was used with --prefix when configuring gcc. +AC_ARG_WITH(gcc-toolchain, + AS_HELP_STRING([--with-gcc-toolchain], + [Directory where gcc is installed.]),, + withval="") +AC_DEFINE_UNQUOTED(GCC_INSTALL_PREFIX,"$withval", + [Directory where gcc is installed.]) + +AC_ARG_WITH(default-sysroot, + AS_HELP_STRING([--with-default-sysroot], + [Add --sysroot= to all compiler invocations.]),, + withval="") +AC_DEFINE_UNQUOTED(DEFAULT_SYSROOT,"$withval", + [Default to all compiler invocations for --sysroot=.]) + +dnl Allow linking of LLVM with GPLv3 binutils code. +AC_ARG_WITH(binutils-include, + AS_HELP_STRING([--with-binutils-include], + [Specify path to binutils/include/ containing plugin-api.h file for gold plugin.]),, + withval=default) +case "$withval" in + default) WITH_BINUTILS_INCDIR=default ;; + /* | [[A-Za-z]]:[[\\/]]*) WITH_BINUTILS_INCDIR=$withval ;; + *) AC_MSG_ERROR([Invalid path for --with-binutils-include. Provide full path]) ;; +esac +if test "x$WITH_BINUTILS_INCDIR" != xdefault ; then + AC_SUBST(BINUTILS_INCDIR,$WITH_BINUTILS_INCDIR) + if test ! -f "$WITH_BINUTILS_INCDIR/plugin-api.h"; then + echo "$WITH_BINUTILS_INCDIR/plugin-api.h" + AC_MSG_ERROR([Invalid path to directory containing plugin-api.h.]); + fi +fi + +dnl Specify the URL where bug reports should be submitted. +AC_ARG_WITH(bug-report-url, + AS_HELP_STRING([--with-bug-report-url], + [Specify the URL where bug reports should be submitted (default=http://llvm.org/bugs/)]),, + withval="http://llvm.org/bugs/") +AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval", + [Bug report URL.]) + +dnl --enable-terminfo: check whether the user wants to control use of terminfo: +AC_ARG_ENABLE(terminfo,AS_HELP_STRING( + [--enable-terminfo], + [Query the terminfo database if available (default is YES)]), + [case "$enableval" in + yes) llvm_cv_enable_terminfo="yes" ;; + no) llvm_cv_enable_terminfo="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-terminfo. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_terminfo="yes") + +dnl --enable-libffi : check whether the user wants to turn off libffi: +AC_ARG_ENABLE(libffi,AS_HELP_STRING( + --enable-libffi,[Check for the presence of libffi (default is NO)]), + [case "$enableval" in + yes) llvm_cv_enable_libffi="yes" ;; + no) llvm_cv_enable_libffi="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-libffi. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_libffi=no) + +AC_ARG_WITH(internal-prefix, + AS_HELP_STRING([--with-internal-prefix], + [Installation directory for internal files]),, + withval="") +AC_SUBST(INTERNAL_PREFIX,[$withval]) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 4: Check for programs we need and that they are the right version +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_PROG_NM +AC_SUBST(NM) + +dnl Check for the tools that the makefiles require +AC_CHECK_GNU_MAKE +AC_PROG_LN_S +AC_PATH_PROG(CMP, [cmp], [cmp]) +AC_PATH_PROG(CP, [cp], [cp]) +AC_PATH_PROG(DATE, [date], [date]) +AC_PATH_PROG(FIND, [find], [find]) +AC_PATH_PROG(GREP, [grep], [grep]) +AC_PATH_PROG(MKDIR,[mkdir],[mkdir]) +AC_PATH_PROG(MV, [mv], [mv]) +AC_PROG_RANLIB +AC_CHECK_TOOL(AR, ar, false) +AC_PATH_PROG(RM, [rm], [rm]) +AC_PATH_PROG(SED, [sed], [sed]) +AC_PATH_PROG(TAR, [tar], [gtar]) +AC_PATH_PROG(BINPWD,[pwd], [pwd]) + +dnl Looking for misc. graph plotting software +AC_PATH_PROG(GRAPHVIZ, [Graphviz], [echo Graphviz]) +if test "$GRAPHVIZ" != "echo Graphviz" ; then + AC_DEFINE([HAVE_GRAPHVIZ],[1],[Define if the Graphviz program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + GRAPHVIZ=`echo $GRAPHVIZ | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_GRAPHVIZ],"$GRAPHVIZ${EXEEXT}", + [Define to path to Graphviz program if found or 'echo Graphviz' otherwise]) +fi +AC_PATH_PROG(DOT, [dot], [echo dot]) +if test "$DOT" != "echo dot" ; then + AC_DEFINE([HAVE_DOT],[1],[Define if the dot program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + DOT=`echo $DOT | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_DOT],"$DOT${EXEEXT}", + [Define to path to dot program if found or 'echo dot' otherwise]) +fi +AC_PATH_PROG(FDP, [fdp], [echo fdp]) +if test "$FDP" != "echo fdp" ; then + AC_DEFINE([HAVE_FDP],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + FDP=`echo $FDP | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_FDP],"$FDP${EXEEXT}", + [Define to path to fdp program if found or 'echo fdp' otherwise]) +fi +AC_PATH_PROG(NEATO, [neato], [echo neato]) +if test "$NEATO" != "echo neato" ; then + AC_DEFINE([HAVE_NEATO],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + NEATO=`echo $NEATO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_NEATO],"$NEATO${EXEEXT}", + [Define to path to neato program if found or 'echo neato' otherwise]) +fi +AC_PATH_PROG(TWOPI, [twopi], [echo twopi]) +if test "$TWOPI" != "echo twopi" ; then + AC_DEFINE([HAVE_TWOPI],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + TWOPI=`echo $TWOPI | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_TWOPI],"$TWOPI${EXEEXT}", + [Define to path to twopi program if found or 'echo twopi' otherwise]) +fi +AC_PATH_PROG(CIRCO, [circo], [echo circo]) +if test "$CIRCO" != "echo circo" ; then + AC_DEFINE([HAVE_CIRCO],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + CIRCO=`echo $CIRCO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_CIRCO],"$CIRCO${EXEEXT}", + [Define to path to circo program if found or 'echo circo' otherwise]) +fi +AC_PATH_PROGS(GV, [gv gsview32], [echo gv]) +if test "$GV" != "echo gv" ; then + AC_DEFINE([HAVE_GV],[1],[Define if the gv program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + GV=`echo $GV | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_GV],"$GV${EXEEXT}", + [Define to path to gv program if found or 'echo gv' otherwise]) +fi +AC_PATH_PROG(DOTTY, [dotty], [echo dotty]) +if test "$DOTTY" != "echo dotty" ; then + AC_DEFINE([HAVE_DOTTY],[1],[Define if the dotty program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + DOTTY=`echo $DOTTY | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_DOTTY],"$DOTTY${EXEEXT}", + [Define to path to dotty program if found or 'echo dotty' otherwise]) +fi +AC_PATH_PROGS(XDOT, [xdot xdot.py], [echo xdot]) +if test "$XDOT" != "echo xdot" ; then + AC_DEFINE([HAVE_XDOT],[1],[Define if the xdot program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + XDOT=`echo $XDOT | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_XDOT],"$XDOT${EXEEXT}", + [Define to path to xdot program if found or 'echo xdot' otherwise]) +fi + +dnl Find the install program +AC_PROG_INSTALL +dnl Prepend src dir to install path dir if it's a relative path +dnl This is a hack for installs that take place in something other +dnl than the top level. +case "$INSTALL" in + [[\\/$]]* | ?:[[\\/]]* ) ;; + *) INSTALL="\\\$(TOPSRCDIR)/$INSTALL" ;; +esac + +dnl Checks for documentation and testing tools that we can do without. If these +dnl are not found then they are set to "true" which always succeeds but does +dnl nothing. This just lets the build output show that we could have done +dnl something if the tool was available. +AC_PATH_PROG(BZIP2, [bzip2]) +AC_PATH_PROG(CAT, [cat]) +AC_PATH_PROG(DOXYGEN, [doxygen]) +AC_PATH_PROG(GROFF, [groff]) +AC_PATH_PROG(GZIPBIN, [gzip]) +AC_PATH_PROG(PDFROFF, [pdfroff]) +AC_PATH_PROG(ZIP, [zip]) +AC_PATH_PROGS(OCAMLC, [ocamlc]) +AC_PATH_PROGS(OCAMLOPT, [ocamlopt]) +AC_PATH_PROGS(OCAMLDEP, [ocamldep]) +AC_PATH_PROGS(OCAMLDOC, [ocamldoc]) +AC_PATH_PROGS(GAS, [gas as]) + +dnl Get the version of the linker in use. +AC_LINK_GET_VERSION + +dnl Determine whether the linker supports the -R option. +AC_LINK_USE_R + +dnl Determine whether the compiler supports the -rdynamic option. +AC_LINK_EXPORT_DYNAMIC + +dnl Determine whether the linker supports the --version-script option. +AC_LINK_VERSION_SCRIPT + +dnl Check for libtool and the library that has dlopen function (which must come +dnl before the AC_PROG_LIBTOOL check in order to enable dlopening libraries with +dnl libtool). +AC_LIBTOOL_DLOPEN +AC_LIB_LTDL + +AC_MSG_CHECKING([tool compatibility]) + +dnl Ensure that compilation tools are GCC or a GNU compatible compiler such as +dnl ICC; we use GCC specific options in the makefiles so the compiler needs +dnl to support those options. +dnl "icc" emits gcc signatures +dnl "icc -no-gcc" emits no gcc signature BUT is still compatible +ICC=no +IXX=no +case $CC in + icc*|icpc*) + ICC=yes + IXX=yes + ;; + *) + ;; +esac + +if test "$GCC" != "yes" && test "$ICC" != "yes" +then + AC_MSG_ERROR([gcc|icc required but not found]) +fi + +dnl Ensure that compilation tools are compatible with GCC extensions +if test "$GXX" != "yes" && test "$IXX" != "yes" +then + AC_MSG_ERROR([g++|clang++|icc required but not found]) +fi + +dnl Verify that GCC is version 3.0 or higher +if test "$GCC" = "yes" +then + AC_COMPILE_IFELSE( +[ + AC_LANG_SOURCE([[ + #if !defined(__GNUC__) || __GNUC__ < 3 + #error Unsupported GCC version + #endif + ]]) +], +[], [AC_MSG_ERROR([gcc 3.x required, but you have a lower version])]) +fi + +dnl Check for GNU Make. We use its extensions, so don't build without it +if test -z "$llvm_cv_gnu_make_command" +then + AC_MSG_ERROR([GNU Make required but not found]) +fi + +dnl Tool compatibility is okay if we make it here. +AC_MSG_RESULT([ok]) + +dnl Check optional compiler flags. +AC_MSG_CHECKING([optional compiler flags]) +CXX_FLAG_CHECK(NO_VARIADIC_MACROS, [-Wno-variadic-macros]) +CXX_FLAG_CHECK(NO_MISSING_FIELD_INITIALIZERS, [-Wno-missing-field-initializers]) +CXX_FLAG_CHECK(COVERED_SWITCH_DEFAULT, [-Wcovered-switch-default]) + +dnl GCC's potential uninitialized use analysis is weak and presents lots of +dnl false positives, so disable it. +NO_UNINITIALIZED= +NO_MAYBE_UNINITIALIZED= +if test "$GXX" = "yes" +then + CXX_FLAG_CHECK(NO_MAYBE_UNINITIALIZED, [-Wno-maybe-uninitialized]) + dnl gcc 4.7 introduced -Wmaybe-uninitialized to distinguish cases which are + dnl known to be uninitialized from cases which might be uninitialized. We + dnl still want to catch the first kind of errors. + if test -z "$NO_MAYBE_UNINITIALIZED" + then + CXX_FLAG_CHECK(NO_UNINITIALIZED, [-Wno-uninitialized]) + fi +fi +AC_MSG_RESULT([$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS $COVERED_SWITCH_DEFAULT $NO_UNINITIALIZED $NO_MAYBE_UNINITIALIZED]) + +AC_ARG_WITH([python], + [AS_HELP_STRING([--with-python], [path to python])], + [PYTHON="$withval"]) + +if test -n "$PYTHON" && test -x "$PYTHON" ; then + AC_MSG_CHECKING([for python]) + AC_MSG_RESULT([user defined: $with_python]) +else + if test -n "$PYTHON" ; then + AC_MSG_WARN([specified python ($PYTHON) is not usable, searching path]) + fi + + AC_PATH_PROG([PYTHON], [python python2 python26], + [AC_MSG_RESULT([not found]) + AC_MSG_ERROR([could not find python 2.5 or higher])]) +fi + +AC_MSG_CHECKING([for python >= 2.5]) +ac_python_version=`$PYTHON -V 2>&1 | cut -d' ' -f2` +ac_python_version_major=`echo $ac_python_version | cut -d'.' -f1` +ac_python_version_minor=`echo $ac_python_version | cut -d'.' -f2` +ac_python_version_patch=`echo $ac_python_version | cut -d'.' -f3` +if test "$ac_python_version_major" -gt "2" || \ + (test "$ac_python_version_major" -eq "2" && \ + test "$ac_python_version_minor" -ge "5") ; then + AC_MSG_RESULT([$PYTHON ($ac_python_version)]) +else + AC_MSG_RESULT([not found]) + AC_MSG_FAILURE([found python $ac_python_version ($PYTHON); required >= 2.5]) +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 5: Check for libraries +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_CHECK_LIB(m,sin) +if test "$llvm_cv_os_type" = "MingW" ; then + AC_CHECK_LIB(imagehlp, main) + AC_CHECK_LIB(psapi, main) + AC_CHECK_LIB(shell32, main) +fi + +dnl dlopen() is required for plugin support. +AC_SEARCH_LIBS(dlopen,dl,AC_DEFINE([HAVE_DLOPEN],[1], + [Define if dlopen() is available on this platform.]), + AC_MSG_WARN([dlopen() not found - disabling plugin support])) + +dnl Search for the clock_gettime() function. Note that we rely on the POSIX +dnl macros to detect whether clock_gettime is available, this just finds the +dnl right libraries to link with. +AC_SEARCH_LIBS(clock_gettime,rt) + +dnl The curses library is optional; used for querying terminal info +if test "$llvm_cv_enable_terminfo" = "yes" ; then + dnl We need the has_color functionality in curses for it to be useful. + AC_SEARCH_LIBS(setupterm,tinfo terminfo curses ncurses ncursesw, + AC_DEFINE([HAVE_TERMINFO],[1], + [Define if the setupterm() function is supported this platform.])) +fi + +dnl libffi is optional; used to call external functions from the interpreter +if test "$llvm_cv_enable_libffi" = "yes" ; then + AC_SEARCH_LIBS(ffi_call,ffi,AC_DEFINE([HAVE_FFI_CALL],[1], + [Define if libffi is available on this platform.]), + AC_MSG_ERROR([libffi not found - configure without --enable-libffi to compile without it])) +fi + +dnl mallinfo is optional; the code can compile (minus features) without it +AC_SEARCH_LIBS(mallinfo,malloc,AC_DEFINE([HAVE_MALLINFO],[1], + [Define if mallinfo() is available on this platform.])) + +dnl pthread locking functions are optional - but llvm will not be thread-safe +dnl without locks. +if test "$LLVM_ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + AC_CHECK_LIB(pthread, pthread_mutex_init) + AC_SEARCH_LIBS(pthread_mutex_lock,pthread, + AC_DEFINE([HAVE_PTHREAD_MUTEX_LOCK],[1], + [Have pthread_mutex_lock])) + AC_SEARCH_LIBS(pthread_rwlock_init,pthread, + AC_DEFINE([HAVE_PTHREAD_RWLOCK_INIT],[1], + [Have pthread_rwlock_init])) + AC_SEARCH_LIBS(pthread_getspecific,pthread, + AC_DEFINE([HAVE_PTHREAD_GETSPECIFIC],[1], + [Have pthread_getspecific])) +fi + +dnl zlib is optional; used for compression/uncompression +if test "$LLVM_ENABLE_ZLIB" -eq 1 ; then + AC_CHECK_LIB(z, compress2) +fi + +dnl Allow extra x86-disassembler library +AC_ARG_WITH(udis86, + AS_HELP_STRING([--with-udis86=], + [Use udis86 external x86 disassembler library]), + [ + AC_SUBST(USE_UDIS86, [1]) + case "$withval" in + /usr/lib|yes) ;; + *) LDFLAGS="$LDFLAGS -L${withval}" ;; + esac + AC_CHECK_LIB(udis86, ud_init, [], [ + echo "Error! You need to have libudis86 around." + exit -1 + ]) + ], + AC_SUBST(USE_UDIS86, [0])) +AC_DEFINE_UNQUOTED([USE_UDIS86],$USE_UDIS86, + [Define if use udis86 library]) + +dnl Allow OProfile support for JIT output. +AC_ARG_WITH(oprofile, + AS_HELP_STRING([--with-oprofile=], + [Tell OProfile >= 0.9.4 how to symbolize JIT output]), + [ + AC_SUBST(USE_OPROFILE, [1]) + case "$withval" in + /usr|yes) llvm_cv_oppath=/usr/lib/oprofile ;; + no) llvm_cv_oppath= + AC_SUBST(USE_OPROFILE, [0]) ;; + *) llvm_cv_oppath="${withval}/lib/oprofile" + CPPFLAGS="-I${withval}/include";; + esac + case $llvm_cv_os_type in + Linux) + if test -n "$llvm_cv_oppath" ; then + LIBS="$LIBS -lopagent -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}" + dnl Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=537744: + dnl libbfd is not included properly in libopagent in some Debian + dnl versions. If libbfd isn't found at all, we assume opagent works + dnl anyway. + AC_SEARCH_LIBS(bfd_init, bfd, [], []) + AC_SEARCH_LIBS(op_open_agent, opagent, [], [ + echo "Error! You need to have libopagent around." + exit -1 + ]) + AC_CHECK_HEADER([opagent.h], [], [ + echo "Error! You need to have opagent.h around." + exit -1 + ]) + fi ;; + *) + AC_MSG_ERROR([OProfile support is available on Linux only.]) ;; + esac + ], + [ + AC_SUBST(USE_OPROFILE, [0]) + ]) +AC_DEFINE_UNQUOTED([LLVM_USE_OPROFILE],$USE_OPROFILE, + [Define if we have the oprofile JIT-support library]) + +dnl Enable support for Intel JIT Events API. +AC_ARG_WITH(intel-jitevents, + AS_HELP_STRING([--with-intel-jitevents Notify Intel JIT profiling API of generated code]), + [ + case "$withval" in + yes) AC_SUBST(USE_INTEL_JITEVENTS,[1]);; + no) AC_SUBST(USE_INTEL_JITEVENTS,[0]);; + *) AC_MSG_ERROR([Invalid setting for --with-intel-jitevents. Use "yes" or "no"]);; + esac + + case $llvm_cv_os_type in + Linux|Win32|Cygwin|MingW) ;; + *) AC_MSG_ERROR([Intel JIT API support is available on Linux and Windows only.]);; + esac + + case "$llvm_cv_target_arch" in + x86|x86_64) ;; + *) AC_MSG_ERROR([Target architecture $llvm_cv_target_arch does not support Intel JIT Events API.]);; + esac + ], + [ + AC_SUBST(USE_INTEL_JITEVENTS, [0]) + ]) +AC_DEFINE_UNQUOTED([LLVM_USE_INTEL_JITEVENTS],$USE_INTEL_JITEVENTS, + [Define if we have the Intel JIT API runtime support library]) + +dnl Check for libxml2 +dnl Right now we're just checking for the existence, we could also check for a +dnl particular version via --version on xml2-config +AC_CHECK_PROGS(XML2CONFIG, xml2-config) + +AC_MSG_CHECKING(for libxml2 includes) +if test "x$XML2CONFIG" = "x"; then + AC_MSG_RESULT(xml2-config not found) +else + LIBXML2_INC=`$XML2CONFIG --cflags` + AC_MSG_RESULT($LIBXML2_INC) + AC_CHECK_LIB(xml2, xmlReadFile,[AC_DEFINE([CLANG_HAVE_LIBXML],1,[Define if we have libxml2]) + LIBXML2_LIBS="-lxml2"]) +fi +AC_SUBST(LIBXML2_LIBS) +AC_SUBST(LIBXML2_INC) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 6: Check for header files +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl First, use autoconf provided macros for specific headers that we need +dnl We don't check for ancient stuff or things that are guaranteed to be there +dnl by the C++ standard. We always use the versions of C headers. +dnl Generally we're looking for POSIX headers. +AC_HEADER_DIRENT +AC_HEADER_MMAP_ANONYMOUS +AC_HEADER_STAT +AC_HEADER_SYS_WAIT +AC_HEADER_TIME + +AC_LANG_PUSH([C++]) +AC_CHECK_HEADERS([cxxabi.h]) +AC_LANG_POP([C++]) +AC_CHECK_HEADERS([dlfcn.h execinfo.h fcntl.h inttypes.h link.h]) +AC_CHECK_HEADERS([malloc.h setjmp.h signal.h stdint.h termios.h unistd.h]) +AC_CHECK_HEADERS([utime.h]) +AC_CHECK_HEADERS([sys/mman.h sys/param.h sys/resource.h sys/time.h sys/uio.h]) +AC_CHECK_HEADERS([sys/ioctl.h malloc/malloc.h mach/mach.h]) +AC_CHECK_HEADERS([valgrind/valgrind.h]) +AC_CHECK_HEADERS([fenv.h]) +AC_CHECK_DECLS([FE_ALL_EXCEPT, FE_INEXACT], [], [], [[#include ]]) +if test "$LLVM_ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + AC_CHECK_HEADERS(pthread.h, + AC_SUBST(HAVE_PTHREAD, 1), + AC_SUBST(HAVE_PTHREAD, 0)) +else + AC_SUBST(HAVE_PTHREAD, 0) +fi +if test "$LLVM_ENABLE_ZLIB" -eq 1 ; then + AC_CHECK_HEADERS(zlib.h, + AC_SUBST(HAVE_LIBZ, 1), + AC_SUBST(HAVE_LIBZ, 0)) +else + AC_SUBST(HAVE_LIBZ, 0) +fi + +dnl Try to find ffi.h. +if test "$llvm_cv_enable_libffi" = "yes" ; then + AC_CHECK_HEADERS([ffi.h ffi/ffi.h]) +fi + +dnl Try to find Darwin specific crash reporting libraries. +AC_CHECK_HEADERS([CrashReporterClient.h]) + +dnl Try to find Darwin specific crash reporting global. +AC_MSG_CHECKING([__crashreporter_info__]) +AC_LINK_IFELSE( +[ + AC_LANG_SOURCE([[ + extern const char *__crashreporter_info__; + int main() { + __crashreporter_info__ = "test"; + return 0; + } + ]]) +], +[ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_CRASHREPORTER_INFO], [1], [can use __crashreporter_info__]) +], +[ + AC_MSG_RESULT([no]) + AC_DEFINE([HAVE_CRASHREPORTER_INFO], [0], [can use __crashreporter_info__]) +]) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 7: Check for types and structures +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_HUGE_VAL_CHECK +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_DEFINE_UNQUOTED([RETSIGTYPE],[void],[Define as the return type of signal handlers (`int' or `void').]) +AC_STRUCT_TM +AC_CHECK_TYPES([int64_t],,AC_MSG_ERROR([Type int64_t required but not found])) +AC_CHECK_TYPES([uint64_t],, + AC_CHECK_TYPES([u_int64_t],, + AC_MSG_ERROR([Type uint64_t or u_int64_t required but not found]))) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 8: Check for specific functions needed +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_CHECK_FUNCS([backtrace ceilf floorf roundf rintf nearbyintf getcwd ]) +AC_CHECK_FUNCS([powf fmodf strtof round ]) +AC_CHECK_FUNCS([log log2 log10 exp exp2]) +AC_CHECK_FUNCS([getpagesize getrusage getrlimit setrlimit gettimeofday ]) +AC_CHECK_FUNCS([isatty mkdtemp mkstemp ]) +AC_CHECK_FUNCS([mktemp posix_spawn pread realpath sbrk setrlimit ]) +AC_CHECK_FUNCS([strerror strerror_r setenv arc4random ]) +AC_CHECK_FUNCS([strtoll strtoq sysconf malloc_zone_statistics ]) +AC_CHECK_FUNCS([setjmp longjmp sigsetjmp siglongjmp writev]) +AC_CHECK_FUNCS([futimes futimens]) +AC_C_PRINTF_A +AC_FUNC_RAND48 + +dnl Check the declaration "Secure API" on Windows environments. +AC_CHECK_DECLS([strerror_s]) + +dnl Check symbols in libgcc.a for JIT on Mingw. +if test "$llvm_cv_os_type" = "MingW" ; then + AC_CHECK_LIB(gcc,_alloca,AC_DEFINE([HAVE__ALLOCA],[1],[Have host's _alloca])) + AC_CHECK_LIB(gcc,__alloca,AC_DEFINE([HAVE___ALLOCA],[1],[Have host's __alloca])) + AC_CHECK_LIB(gcc,__chkstk,AC_DEFINE([HAVE___CHKSTK],[1],[Have host's __chkstk])) + AC_CHECK_LIB(gcc,___chkstk,AC_DEFINE([HAVE____CHKSTK],[1],[Have host's ___chkstk])) + + AC_CHECK_LIB(gcc,__ashldi3,AC_DEFINE([HAVE___ASHLDI3],[1],[Have host's __ashldi3])) + AC_CHECK_LIB(gcc,__ashrdi3,AC_DEFINE([HAVE___ASHRDI3],[1],[Have host's __ashrdi3])) + AC_CHECK_LIB(gcc,__divdi3,AC_DEFINE([HAVE___DIVDI3],[1],[Have host's __divdi3])) + AC_CHECK_LIB(gcc,__fixdfdi,AC_DEFINE([HAVE___FIXDFDI],[1],[Have host's __fixdfdi])) + AC_CHECK_LIB(gcc,__fixsfdi,AC_DEFINE([HAVE___FIXSFDI],[1],[Have host's __fixsfdi])) + AC_CHECK_LIB(gcc,__floatdidf,AC_DEFINE([HAVE___FLOATDIDF],[1],[Have host's __floatdidf])) + AC_CHECK_LIB(gcc,__lshrdi3,AC_DEFINE([HAVE___LSHRDI3],[1],[Have host's __lshrdi3])) + AC_CHECK_LIB(gcc,__moddi3,AC_DEFINE([HAVE___MODDI3],[1],[Have host's __moddi3])) + AC_CHECK_LIB(gcc,__udivdi3,AC_DEFINE([HAVE___UDIVDI3],[1],[Have host's __udivdi3])) + AC_CHECK_LIB(gcc,__umoddi3,AC_DEFINE([HAVE___UMODDI3],[1],[Have host's __umoddi3])) + + AC_CHECK_LIB(gcc,__main,AC_DEFINE([HAVE___MAIN],[1],[Have host's __main])) + AC_CHECK_LIB(gcc,__cmpdi2,AC_DEFINE([HAVE___CMPDI2],[1],[Have host's __cmpdi2])) +fi + +dnl Check Win32 API EnumerateLoadedModules. +if test "$llvm_cv_os_type" = "MingW" ; then + AC_MSG_CHECKING([whether EnumerateLoadedModules() accepts new decl]) + AC_COMPILE_IFELSE( +[ + AC_LANG_SOURCE([[ + #include + #include + extern void foo(PENUMLOADED_MODULES_CALLBACK); + extern void foo(BOOL(CALLBACK*)(PCSTR,ULONG_PTR,ULONG,PVOID)); + ]]) +], +[ + AC_MSG_RESULT([yes]) + llvm_cv_win32_elmcb_pcstr="PCSTR" +], +[ + AC_MSG_RESULT([no]) + llvm_cv_win32_elmcb_pcstr="PSTR" +]) + AC_DEFINE_UNQUOTED([WIN32_ELMCB_PCSTR],$llvm_cv_win32_elmcb_pcstr,[Type of 1st arg on ELM Callback]) +fi + +dnl Check for variations in the Standard C++ library and STL. These macros are +dnl provided by LLVM in the autoconf/m4 directory. +AC_FUNC_ISNAN +AC_FUNC_ISINF + +dnl Check for mmap support.We also need to know if /dev/zero is required to +dnl be opened for allocating RWX memory. +dnl Make sure we aren't attempting to configure for an unknown system +if test "$llvm_cv_platform_type" = "Unix" ; then + AC_FUNC_MMAP + AC_FUNC_MMAP_FILE + AC_NEED_DEV_ZERO_FOR_MMAP + + if test "$ac_cv_func_mmap_fixed_mapped" = "no" + then + AC_MSG_WARN([mmap() of a fixed address required but not supported]) + fi + if test "$ac_cv_func_mmap_file" = "no" + then + AC_MSG_WARN([mmap() of files required but not found]) + fi +fi + +dnl atomic builtins are required for threading support. +AC_MSG_CHECKING(for GCC atomic builtins) +dnl Since we'll be using these atomic builtins in C++ files we should test +dnl the C++ compiler. +AC_LANG_PUSH([C++]) +AC_LINK_IFELSE( +[ + AC_LANG_SOURCE([[ + int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } + ]]) +], +[ + AC_MSG_RESULT([yes]) + AC_DEFINE([LLVM_HAS_ATOMICS], [1], [Has gcc/MSVC atomic intrinsics]) +], +[ + AC_MSG_RESULT([no]) + AC_DEFINE([LLVM_HAS_ATOMICS], [0], [Has gcc/MSVC atomic intrinsics]) + AC_MSG_WARN([LLVM will be built thread-unsafe because atomic builtins are missing]) +]) +AC_LANG_POP([C++]) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 9: Additional checks, variables, etc. +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Handle 32-bit linux systems running a 64-bit kernel. +dnl This has to come after section 4 because it invokes the compiler. +if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then + AC_IS_LINUX_MIXED + if test "$llvm_cv_linux_mixed" = "yes"; then + llvm_cv_target_arch="x86" + ARCH="x86" + fi +fi + +dnl Check whether __dso_handle is present +AC_CHECK_FUNCS([__dso_handle]) + +dnl Propagate the shared library extension that the libltdl checks did to +dnl the Makefiles so we can use it there too +AC_SUBST(SHLIBEXT,$libltdl_cv_shlibext) + +dnl Propagate the run-time library path variable that the libltdl +dnl checks found to the Makefiles so we can use it there too +AC_SUBST(SHLIBPATH_VAR,$libltdl_cv_shlibpath_var) + +dnl Translate the various configuration directories and other basic +dnl information into substitutions that will end up in Makefile.config.in +dnl that these configured values can be used by the makefiles +if test "${prefix}" = "NONE" ; then + prefix="/usr/local" +fi +eval LLVM_PREFIX="${prefix}"; +eval LLVM_BINDIR="${prefix}/bin"; +eval LLVM_DATADIR="${prefix}/share/llvm"; +eval LLVM_DOCSDIR="${prefix}/share/doc/llvm"; +eval LLVM_ETCDIR="${prefix}/etc/llvm"; +eval LLVM_INCLUDEDIR="${prefix}/include"; +eval LLVM_INFODIR="${prefix}/info"; +eval LLVM_MANDIR="${prefix}/man"; +LLVM_CONFIGTIME=`date` +AC_SUBST(LLVM_PREFIX) +AC_SUBST(LLVM_BINDIR) +AC_SUBST(LLVM_DATADIR) +AC_SUBST(LLVM_DOCSDIR) +AC_SUBST(LLVM_ETCDIR) +AC_SUBST(LLVM_INCLUDEDIR) +AC_SUBST(LLVM_INFODIR) +AC_SUBST(LLVM_MANDIR) +AC_SUBST(LLVM_CONFIGTIME) + +dnl Disable embedding timestamps in the build directory, with ENABLE_TIMESTAMPS. +if test "${ENABLE_TIMESTAMPS}" = "0"; then + LLVM_CONFIGTIME="(timestamp not enabled)" +fi + +dnl Place the various directories into the config.h file as #defines so that we +dnl can know about the installation paths within LLVM. +AC_DEFINE_UNQUOTED(LLVM_PREFIX,"$LLVM_PREFIX", + [Installation prefix directory]) +AC_DEFINE_UNQUOTED(LLVM_BINDIR, "$LLVM_BINDIR", + [Installation directory for binary executables]) +AC_DEFINE_UNQUOTED(LLVM_DATADIR, "$LLVM_DATADIR", + [Installation directory for data files]) +AC_DEFINE_UNQUOTED(LLVM_DOCSDIR, "$LLVM_DOCSDIR", + [Installation directory for documentation]) +AC_DEFINE_UNQUOTED(LLVM_ETCDIR, "$LLVM_ETCDIR", + [Installation directory for config files]) +AC_DEFINE_UNQUOTED(LLVM_INCLUDEDIR, "$LLVM_INCLUDEDIR", + [Installation directory for include files]) +AC_DEFINE_UNQUOTED(LLVM_INFODIR, "$LLVM_INFODIR", + [Installation directory for .info files]) +AC_DEFINE_UNQUOTED(LLVM_MANDIR, "$LLVM_MANDIR", + [Installation directory for man pages]) +AC_DEFINE_UNQUOTED(LLVM_CONFIGTIME, "$LLVM_CONFIGTIME", + [Time at which LLVM was configured]) +AC_DEFINE_UNQUOTED(LLVM_HOST_TRIPLE, "$host", + [Host triple LLVM will be executed on]) +AC_DEFINE_UNQUOTED(LLVM_DEFAULT_TARGET_TRIPLE, "$target", + [Target triple LLVM will generate code for by default]) + +dnl Determine which bindings to build. +if test "$BINDINGS_TO_BUILD" = auto ; then + BINDINGS_TO_BUILD="" + if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" + fi +fi +AC_SUBST(BINDINGS_TO_BUILD,$BINDINGS_TO_BUILD) + +dnl This isn't really configurey, but it avoids having to repeat the list in +dnl other files. +AC_SUBST(ALL_BINDINGS,ocaml) + +dnl Do any work necessary to ensure that bindings have what they need. +binding_prereqs_failed=0 +for a_binding in $BINDINGS_TO_BUILD ; do + case "$a_binding" in + ocaml) + if test "x$OCAMLC" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc]) + binding_prereqs_failed=1 + fi + if test "x$OCAMLDEP" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep]) + binding_prereqs_failed=1 + fi + if test "x$OCAMLOPT" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt]) + dnl ocamlopt is optional! + fi + if test "x$with_ocaml_libdir" != xauto ; then + AC_SUBST(OCAML_LIBDIR,$with_ocaml_libdir) + else + ocaml_stdlib="`"$OCAMLC" -where`" + if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" + then + # ocaml stdlib is beneath our prefix; use stdlib + AC_SUBST(OCAML_LIBDIR,$ocaml_stdlib) + else + # ocaml stdlib is outside our prefix; use libdir/ocaml + AC_SUBST(OCAML_LIBDIR,${prefix}/lib/ocaml) + fi + fi + ;; + esac +done +if test "$binding_prereqs_failed" = 1 ; then + AC_MSG_ERROR([Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings.]) +fi + +dnl Determine whether the compiler supports -fvisibility-inlines-hidden. +AC_CXX_USE_VISIBILITY_INLINES_HIDDEN + +dnl Determine linker rpath flag +if test "$llvm_cv_link_use_r" = "yes" ; then + RPATH="-Wl,-R" +else + RPATH="-Wl,-rpath" +fi +AC_SUBST(RPATH) + +dnl Determine linker rdynamic flag +if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then + RDYNAMIC="-rdynamic" +else + RDYNAMIC="" +fi +AC_SUBST(RDYNAMIC) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 10: Specify the output files and generate it +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Configure header files +dnl WARNING: dnl If you add or remove any of the following config headers, then +dnl you MUST also update Makefile so that the variable FilesToConfig +dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the +dnl files can be updated automatically when their *.in sources change. +AC_CONFIG_HEADERS([include/llvm/Config/config.h include/llvm/Config/llvm-config.h]) +AH_TOP([#ifndef CONFIG_H +#define CONFIG_H]) +AH_BOTTOM([#endif]) + +AC_CONFIG_FILES([include/llvm/Config/Targets.def]) +AC_CONFIG_FILES([include/llvm/Config/AsmPrinters.def]) +AC_CONFIG_FILES([include/llvm/Config/AsmParsers.def]) +AC_CONFIG_FILES([include/llvm/Config/Disassemblers.def]) +AC_CONFIG_HEADERS([include/llvm/Support/DataTypes.h]) + +dnl Configure the makefile's configuration data +AC_CONFIG_FILES([Makefile.config]) + +dnl Configure the RPM spec file for LLVM +AC_CONFIG_FILES([llvm.spec]) + +dnl Configure doxygen's configuration file +AC_CONFIG_FILES([docs/doxygen.cfg]) + +dnl Configure clang, if present +if test "${clang_src_root}" = ""; then + clang_src_root="$srcdir/tools/clang" +fi +if test -f ${clang_src_root}/README.txt; then + dnl Use variables to stay under 80 columns. + configh="include/clang/Config/config.h" + doxy="docs/doxygen.cfg" + AC_CONFIG_HEADERS([tools/clang/${configh}:${clang_src_root}/${configh}.in]) + AC_CONFIG_FILES([tools/clang/${doxy}:${clang_src_root}/${doxy}.in]) +fi + +dnl OCaml findlib META file +AC_CONFIG_FILES([bindings/ocaml/llvm/META.llvm]) + +dnl Add --program-prefix value to Makefile.rules. Already an ARG variable. +test "x$program_prefix" = "xNONE" && program_prefix="" +AC_SUBST([program_prefix]) + + +dnl Do special configuration of Makefiles +AC_CONFIG_COMMANDS([setup],,[llvm_src="${srcdir}"]) +AC_CONFIG_MAKEFILE(Makefile) +AC_CONFIG_MAKEFILE(Makefile.common) +AC_CONFIG_MAKEFILE(examples/Makefile) +AC_CONFIG_MAKEFILE(lib/Makefile) +AC_CONFIG_MAKEFILE(test/Makefile) +AC_CONFIG_MAKEFILE(test/Makefile.tests) +AC_CONFIG_MAKEFILE(unittests/Makefile) +AC_CONFIG_MAKEFILE(tools/Makefile) +AC_CONFIG_MAKEFILE(utils/Makefile) +AC_CONFIG_MAKEFILE(projects/Makefile) +AC_CONFIG_MAKEFILE(bindings/Makefile) +AC_CONFIG_MAKEFILE(bindings/ocaml/Makefile.ocaml) + +dnl Finally, crank out the output +AC_OUTPUT diff --git a/autoconf/depcomp b/autoconf/depcomp new file mode 100755 index 00000000..11e2d3bf --- /dev/null +++ b/autoconf/depcomp @@ -0,0 +1,522 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2004-05-31.23 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit 0 + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # Dependencies are output in .lo.d with libtool 1.4. + # With libtool 1.5 they are output both in $dir.libs/$base.o.d + # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the + # latter, because the former will be cleaned when $dir.libs is + # erased. + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir$base.o.d" + tmpdepfile3="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + tmpdepfile3="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + elif test -f "$tmpdepfile2"; then + tmpdepfile="$tmpdepfile2" + else + tmpdepfile="$tmpdepfile3" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/autoconf/install-sh b/autoconf/install-sh new file mode 100755 index 00000000..dd97db7a --- /dev/null +++ b/autoconf/install-sh @@ -0,0 +1,322 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2004-09-10.20 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/autoconf/ltmain.sh b/autoconf/ltmain.sh new file mode 100644 index 00000000..21ace012 --- /dev/null +++ b/autoconf/ltmain.sh @@ -0,0 +1,6863 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes. +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | -*-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $absdir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/autoconf/m4/build_exeext.m4 b/autoconf/m4/build_exeext.m4 new file mode 100644 index 00000000..1bdecc1b --- /dev/null +++ b/autoconf/m4/build_exeext.m4 @@ -0,0 +1,42 @@ +# Check for the extension used for executables on build platform. +# This is necessary for cross-compiling where the build platform +# may differ from the host platform. +AC_DEFUN([AC_BUILD_EXEEXT], +[ +AC_MSG_CHECKING([for executable suffix on build platform]) +AC_CACHE_VAL(ac_cv_build_exeext, +[if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_build_exeext=.exe +else + ac_build_prefix=${build_alias}- + + AC_CHECK_PROG(BUILD_CC, ${ac_build_prefix}gcc, ${ac_build_prefix}gcc) + if test -z "$BUILD_CC"; then + AC_CHECK_PROG(BUILD_CC, gcc, gcc) + if test -z "$BUILD_CC"; then + AC_CHECK_PROG(BUILD_CC, cc, cc, , , /usr/ucb/cc) + fi + fi + test -z "$BUILD_CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH]) + ac_build_link='${BUILD_CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AS_MESSAGE_LOG_FD' + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_build_exeext= + if AC_TRY_EVAL(ac_build_link); then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.dSYM) ;; + *) ac_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + AC_MSG_ERROR([installation or configuration problem: compiler cannot create executables.]) + fi + rm -f conftest* + test x"${ac_cv_build_exeext}" = x && ac_cv_build_exeext=blank +fi]) +BUILD_EXEEXT="" +test x"${ac_cv_build_exeext}" != xblank && BUILD_EXEEXT=${ac_cv_build_exeext} +AC_MSG_RESULT(${ac_cv_build_exeext}) +ac_build_exeext=$BUILD_EXEEXT +AC_SUBST(BUILD_EXEEXT)]) diff --git a/autoconf/m4/c_printf_a.m4 b/autoconf/m4/c_printf_a.m4 new file mode 100644 index 00000000..61bac8c9 --- /dev/null +++ b/autoconf/m4/c_printf_a.m4 @@ -0,0 +1,31 @@ +# +# Determine if the printf() functions have the %a format character. +# This is modified from: +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_slist.html +AC_DEFUN([AC_C_PRINTF_A], +[AC_CACHE_CHECK([if printf has the %a format character],[llvm_cv_c_printf_a], +[AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#include +#include +]],[[ +volatile double A, B; +char Buffer[100]; +A = 1; +A /= 10.0; +sprintf(Buffer, "%a", A); +B = atof(Buffer); +if (A != B) + return (1); +if (A != 0x1.999999999999ap-4) + return (1); +return (0);]])], + llvm_cv_c_printf_a=yes, + llvmac_cv_c_printf_a=no, + llvmac_cv_c_printf_a=no) + AC_LANG_POP([C])]) + if test "$llvm_cv_c_printf_a" = "yes"; then + AC_DEFINE([HAVE_PRINTF_A],[1],[Define to have the %a format string]) + fi +]) diff --git a/autoconf/m4/check_gnu_make.m4 b/autoconf/m4/check_gnu_make.m4 new file mode 100644 index 00000000..7355e1c8 --- /dev/null +++ b/autoconf/m4/check_gnu_make.m4 @@ -0,0 +1,26 @@ +# +# Check for GNU Make. This is originally from +# http://www.gnu.org/software/ac-archive/htmldoc/check_gnu_make.html +# +AC_DEFUN([AC_CHECK_GNU_MAKE], +[AC_CACHE_CHECK([for GNU make],[llvm_cv_gnu_make_command], +dnl Search all the common names for GNU make +[llvm_cv_gnu_make_command='' + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) + then + llvm_cv_gnu_make_command=$a ; + break; + fi + done]) +dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, +dnl '#' otherwise + if test "x$llvm_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + else + ifGNUmake='#' ; + AC_MSG_RESULT("Not found"); + fi + AC_SUBST(ifGNUmake) +]) diff --git a/autoconf/m4/config_makefile.m4 b/autoconf/m4/config_makefile.m4 new file mode 100644 index 00000000..b1eaffdc --- /dev/null +++ b/autoconf/m4/config_makefile.m4 @@ -0,0 +1,9 @@ +# +# Configure a Makefile without clobbering it if it exists and is not out of +# date. This macro is unique to LLVM. +# +AC_DEFUN([AC_CONFIG_MAKEFILE], +[AC_CONFIG_COMMANDS($1, + [${llvm_src}/autoconf/mkinstalldirs `dirname $1` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/$1 $1]) +]) diff --git a/autoconf/m4/config_project.m4 b/autoconf/m4/config_project.m4 new file mode 100644 index 00000000..eea7faf1 --- /dev/null +++ b/autoconf/m4/config_project.m4 @@ -0,0 +1,14 @@ +# +# Provide the arguments and other processing needed for an LLVM project +# +AC_DEFUN([LLVM_CONFIG_PROJECT], + [AC_ARG_WITH([llvmsrc], + AS_HELP_STRING([--with-llvmsrc],[Location of LLVM Source Code]), + [llvm_src="$withval"],[llvm_src="]$1["]) + AC_SUBST(LLVM_SRC,$llvm_src) + AC_ARG_WITH([llvmobj], + AS_HELP_STRING([--with-llvmobj],[Location of LLVM Object Code]), + [llvm_obj="$withval"],[llvm_obj="]$2["]) + AC_SUBST(LLVM_OBJ,$llvm_obj) + AC_CONFIG_COMMANDS([setup],,[llvm_src="${LLVM_SRC}"]) +]) diff --git a/autoconf/m4/cxx_flag_check.m4 b/autoconf/m4/cxx_flag_check.m4 new file mode 100644 index 00000000..4b097445 --- /dev/null +++ b/autoconf/m4/cxx_flag_check.m4 @@ -0,0 +1,2 @@ +AC_DEFUN([CXX_FLAG_CHECK], + [AC_SUBST($1, `$CXX -Werror patsubst($2, [^-Wno-], [-W]) -fsyntax-only -xc /dev/null 2>/dev/null && echo $2`)]) diff --git a/autoconf/m4/find_std_program.m4 b/autoconf/m4/find_std_program.m4 new file mode 100644 index 00000000..c789df8e --- /dev/null +++ b/autoconf/m4/find_std_program.m4 @@ -0,0 +1,118 @@ +dnl Check for a standard program that has a bin, include and lib directory +dnl +dnl Parameters: +dnl $1 - prefix directory to check +dnl $2 - program name to check +dnl $3 - header file to check +dnl $4 - library file to check +AC_DEFUN([CHECK_STD_PROGRAM], +[m4_define([allcapsname],translit($2,a-z,A-Z)) +if test -n "$1" -a -d "$1" -a -n "$2" -a -d "$1/bin" -a -x "$1/bin/$2" ; then + AC_SUBST([USE_]allcapsname(),["USE_]allcapsname()[ = 1"]) + AC_SUBST(allcapsname(),[$1/bin/$2]) + AC_SUBST(allcapsname()[_BIN],[$1/bin]) + AC_SUBST(allcapsname()[_DIR],[$1]) + if test -n "$3" -a -d "$1/include" -a -f "$1/include/$3" ; then + AC_SUBST(allcapsname()[_INC],[$1/include]) + fi + if test -n "$4" -a -d "$1/lib" -a -f "$1/lib/$4" ; then + AC_SUBST(allcapsname()[_LIB],[$1/lib]) + fi +fi +]) + +dnl Find a program via --with options, in the path, or well known places +dnl +dnl Parameters: +dnl $1 - program's executable name +dnl $2 - header file name to check (optional) +dnl $3 - library file name to check (optional) +dnl $4 - alternate (long) name for the program +AC_DEFUN([FIND_STD_PROGRAM], +[m4_define([allcapsname],translit($1,a-z,A-Z)) +m4_define([stdprog_long_name],ifelse($4,,translit($1,[ !@#$%^&*()-+={}[]:;"',./?],[-]),translit($4,[ !@#$%^&*()-+={}[]:;"',./?],[-]))) +AC_MSG_CHECKING([for ]stdprog_long_name()[ bin/lib/include locations]) +AC_ARG_WITH($1, + AS_HELP_STRING([--with-]stdprog_long_name()[=DIR], + [Specify that the ]stdprog_long_name()[ install prefix is DIR]), + $1[pfxdir=$withval],$1[pfxdir=nada]) +AC_ARG_WITH($1[-bin], + AS_HELP_STRING([--with-]stdprog_long_name()[-bin=DIR], + [Specify that the ]stdprog_long_name()[ binary is in DIR]), + $1[bindir=$withval],$1[bindir=nada]) +AC_ARG_WITH($1[-lib], + AS_HELP_STRING([--with-]stdprog_long_name()[-lib=DIR], + [Specify that ]stdprog_long_name()[ libraries are in DIR]), + $1[libdir=$withval],$1[libdir=nada]) +AC_ARG_WITH($1[-inc], + AS_HELP_STRING([--with-]stdprog_long_name()[-inc=DIR], + [Specify that the ]stdprog_long_name()[ includes are in DIR]), + $1[incdir=$withval],$1[incdir=nada]) +eval pfxval=\$\{$1pfxdir\} +eval binval=\$\{$1bindir\} +eval incval=\$\{$1incdir\} +eval libval=\$\{$1libdir\} +if test "${pfxval}" != "nada" ; then + CHECK_STD_PROGRAM(${pfxval},$1,$2,$3) +elif test "${binval}" != "nada" ; then + if test "${libval}" != "nada" ; then + if test "${incval}" != "nada" ; then + if test -d "${binval}" ; then + if test -d "${incval}" ; then + if test -d "${libval}" ; then + AC_SUBST(allcapsname(),${binval}/$1) + AC_SUBST(allcapsname()[_BIN],${binval}) + AC_SUBST(allcapsname()[_INC],${incval}) + AC_SUBST(allcapsname()[_LIB],${libval}) + AC_SUBST([USE_]allcapsname(),["USE_]allcapsname()[ = 1"]) + AC_MSG_RESULT([found via --with options]) + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-libdir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-incdir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-bindir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-incdir option must be specified]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-libdir option must be specified]) + fi +else + tmppfxdir=`which $1 2>&1` + if test -n "$tmppfxdir" -a -d "${tmppfxdir%*$1}" -a \ + -d "${tmppfxdir%*$1}/.." ; then + tmppfxdir=`cd "${tmppfxdir%*$1}/.." ; pwd` + CHECK_STD_PROGRAM($tmppfxdir,$1,$2,$3) + AC_MSG_RESULT([found in PATH at ]$tmppfxdir) + else + checkresult="yes" + eval checkval=\$\{"USE_"allcapsname()\} + CHECK_STD_PROGRAM([/usr],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/usr/local],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/sw],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/opt],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/],$1,$2,$3) + if test -z "${checkval}" ; then + checkresult="no" + fi + fi + fi + fi + fi + AC_MSG_RESULT($checkresult) + fi +fi +]) diff --git a/autoconf/m4/func_isinf.m4 b/autoconf/m4/func_isinf.m4 new file mode 100644 index 00000000..40dc48b2 --- /dev/null +++ b/autoconf/m4/func_isinf.m4 @@ -0,0 +1,42 @@ +dnl +dnl This function determins if the isinf function isavailable on this +dnl platform. +dnl + +AC_DEFUN([AC_FUNC_ISINF],[ + +AC_SINGLE_CXX_CHECK([ac_cv_func_isinf_in_math_h], + [isinf], [], + [float f; isinf(f);]) +if test "$ac_cv_func_isinf_in_math_h" = "yes" ; then + AC_DEFINE([HAVE_ISINF_IN_MATH_H], [1], + [Set to 1 if the isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_isinf_in_cmath], + [isinf], [], + [float f; isinf(f);]) +if test "$ac_cv_func_isinf_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_ISINF_IN_CMATH], [1], + [Set to 1 if the isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_std_isinf_in_cmath], + [std::isinf], [], + [float f; std::isinf(f);]) +if test "$ac_cv_func_std_isinf_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_STD_ISINF_IN_CMATH], [1], + [Set to 1 if the std::isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_finite_in_ieeefp_h], + [finite], [], + [float f; finite(f);]) +if test "$ac_cv_func_finite_in_ieeefp_h" = "yes" ; then + AC_DEFINE([HAVE_FINITE_IN_IEEEFP_H], [1], + [Set to 1 if the finite function is found in ]) +fi + +]) + + diff --git a/autoconf/m4/func_isnan.m4 b/autoconf/m4/func_isnan.m4 new file mode 100644 index 00000000..eb5ca0da --- /dev/null +++ b/autoconf/m4/func_isnan.m4 @@ -0,0 +1,27 @@ +# +# This function determines if the isnan function is available on this +# platform. +# +AC_DEFUN([AC_FUNC_ISNAN],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_isnan_in_math_h], + [isnan], [], + [float f; isnan(f);]) + +if test "$ac_cv_func_isnan_in_math_h" = "yes" ; then + AC_DEFINE([HAVE_ISNAN_IN_MATH_H],1,[Set to 1 if the isnan function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_isnan_in_cmath], + [isnan], [], + [float f; isnan(f);]) +if test "$ac_cv_func_isnan_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_ISNAN_IN_CMATH],1,[Set to 1 if the isnan function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_std_isnan_in_cmath], + [std::isnan], [], + [float f; std::isnan(f);]) +if test "$ac_cv_func_std_isnan_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_STD_ISNAN_IN_CMATH],1,[Set to 1 if the std::isnan function is found in ]) +fi +]) diff --git a/autoconf/m4/func_mmap_file.m4 b/autoconf/m4/func_mmap_file.m4 new file mode 100644 index 00000000..372c87fb --- /dev/null +++ b/autoconf/m4/func_mmap_file.m4 @@ -0,0 +1,26 @@ +# +# Check for the ability to mmap a file. +# +AC_DEFUN([AC_FUNC_MMAP_FILE], +[AC_CACHE_CHECK(for mmap of files, +ac_cv_func_mmap_file, +[ AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#include +#include +#include +]],[[ + int fd; + fd = creat ("foo",0777); + fd = (int) mmap (0, 1, PROT_READ, MAP_SHARED, fd, 0); + unlink ("foo"); + return (fd != (int) MAP_FAILED);]])], + [ac_cv_func_mmap_file=yes],[ac_cv_func_mmap_file=no],[ac_cv_func_mmap_file=no]) + AC_LANG_POP([C]) +]) +if test "$ac_cv_func_mmap_file" = yes; then + AC_DEFINE([HAVE_MMAP_FILE],[],[Define if mmap() can map files into memory]) + AC_SUBST(MMAP_FILE,[yes]) +fi +]) diff --git a/autoconf/m4/header_mmap_anonymous.m4 b/autoconf/m4/header_mmap_anonymous.m4 new file mode 100644 index 00000000..2270d295 --- /dev/null +++ b/autoconf/m4/header_mmap_anonymous.m4 @@ -0,0 +1,21 @@ +# +# Check for anonymous mmap macros. This is modified from +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_slist.html +# +AC_DEFUN([AC_HEADER_MMAP_ANONYMOUS], +[AC_CACHE_CHECK(for MAP_ANONYMOUS vs. MAP_ANON, +ac_cv_header_mmap_anon, +[ AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#include +#include +#include ]], + [[mmap (0, 1, PROT_READ, MAP_ANONYMOUS, -1, 0); return (0);]])], + ac_cv_header_mmap_anon=yes, + ac_cv_header_mmap_anon=no) + AC_LANG_POP([C]) +]) +if test "$ac_cv_header_mmap_anon" = yes; then + AC_DEFINE([HAVE_MMAP_ANONYMOUS],[1],[Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if it uses MAP_ANON]) +fi +]) diff --git a/autoconf/m4/huge_val.m4 b/autoconf/m4/huge_val.m4 new file mode 100644 index 00000000..d224d7cb --- /dev/null +++ b/autoconf/m4/huge_val.m4 @@ -0,0 +1,18 @@ +# +# This function determins if the HUGE_VAL macro is compilable with the +# -pedantic switch or not. XCode < 2.4.1 doesn't get it right. +# +AC_DEFUN([AC_HUGE_VAL_CHECK],[ + AC_CACHE_CHECK([for HUGE_VAL sanity], [ac_cv_huge_val_sanity],[ + AC_LANG_PUSH([C++]) + ac_save_CXXFLAGS=$CXXFLAGS + CXXFLAGS="$CXXFLAGS -pedantic" + AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[double x = HUGE_VAL; return x != x;]])], + [ac_cv_huge_val_sanity=yes],[ac_cv_huge_val_sanity=no], + [ac_cv_huge_val_sanity=yes]) + CXXFLAGS=$ac_save_CXXFLAGS + AC_LANG_POP([C++]) + ]) + AC_SUBST(HUGE_VAL_SANITY,$ac_cv_huge_val_sanity) +]) diff --git a/autoconf/m4/libtool.m4 b/autoconf/m4/libtool.m4 new file mode 100644 index 00000000..385d00b4 --- /dev/null +++ b/autoconf/m4/libtool.m4 @@ -0,0 +1,6389 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 48 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/mklib' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.60)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=mklib +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd* | bitrig*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock],[avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic],[try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock],[avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*|ppc64le-*linux*|powerpc64le-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly* | bitrig*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1.*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AS_HELP_STRING([--with-tags@<:@=TAGS@:>@],[include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name "$tagname" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([enable_shared_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],[build shared libraries @<:@default=enable_shared_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]enable_shared_default) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([enable_static_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],[build static libraries @<:@default=enable_static_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]enable_static_default) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([enable_Fast_install_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],[optimize for fast installation @<:@default=enable_Fast_install_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]enable_Fast_install_default) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld],[assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]].*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd* | bitrig*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1.*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd* | bitrig*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) diff --git a/autoconf/m4/link_options.m4 b/autoconf/m4/link_options.m4 new file mode 100644 index 00000000..b58d6174 --- /dev/null +++ b/autoconf/m4/link_options.m4 @@ -0,0 +1,109 @@ +# +# Get the linker version string. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_GET_VERSION], + [AC_CACHE_CHECK([for linker version],[llvm_cv_link_version], + [ + version_string="$(ld -v 2>&1 | head -1)" + + # Check for ld64. + if (echo "$version_string" | grep -q "ld64"); then + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#.*ld64-\([^ ]*\)\( (.*)\)\{0,1\}#\1#") + else + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#[^0-9]*\([0-9.]*\).*#\1#") + fi + ]) + AC_DEFINE_UNQUOTED([HOST_LINK_VERSION],"$llvm_cv_link_version", + [Linker version detected at compile time.]) +]) + +# +# Determine if the system can handle the -R option being passed to the linker. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_USE_R], +[AC_CACHE_CHECK([for compiler -Wl,-R option],[llvm_cv_link_use_r], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-R." + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [llvm_cv_link_use_r=yes],[llvm_cv_link_use_r=no]) + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_r" = yes ; then + AC_DEFINE([HAVE_LINK_R],[1],[Define if you can use -Wl,-R. to pass -R. to the linker, in order to add the current directory to the dynamic linker search path.]) + fi +]) + +# +# Determine if the system can handle the -rdynamic option being passed +# to the compiler. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_EXPORT_DYNAMIC], +[AC_CACHE_CHECK([for compiler -rdynamic option], + [llvm_cv_link_use_export_dynamic], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -rdynamic" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [llvm_cv_link_use_export_dynamic=yes],[llvm_cv_link_use_export_dynamic=no]) + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_export_dynamic" = yes ; then + AC_DEFINE([HAVE_LINK_EXPORT_DYNAMIC],[1],[Define if you can use -rdynamic.]) + fi +]) + +# +# Determine if the system can handle the --version-script option being +# passed to the linker. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_VERSION_SCRIPT], +[AC_CACHE_CHECK([for compiler -Wl,--version-script option], + [llvm_cv_link_use_version_script], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + + # The following code is from the autoconf manual, + # "11.13: Limitations of Usual Tools". + # Create a temporary directory $tmp in $TMPDIR (default /tmp). + # Use mktemp if possible; otherwise fall back on mkdir, + # with $RANDOM to make collisions less likely. + : ${TMPDIR=/tmp} + { + tmp=` + (umask 077 && mktemp -d "$TMPDIR/fooXXXXXX") 2>/dev/null + ` && + test -n "$tmp" && test -d "$tmp" + } || { + tmp=$TMPDIR/foo$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || exit $? + + echo "{" > "$tmp/export.map" + echo " global: main;" >> "$tmp/export.map" + echo " local: *;" >> "$tmp/export.map" + echo "};" >> "$tmp/export.map" + + CFLAGS="$CFLAGS -Wl,--version-script=$tmp/export.map" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [llvm_cv_link_use_version_script=yes],[llvm_cv_link_use_version_script=no]) + rm "$tmp/export.map" + rmdir "$tmp" + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_version_script" = yes ; then + AC_SUBST(HAVE_LINK_VERSION_SCRIPT,1) + fi +]) + diff --git a/autoconf/m4/linux_mixed_64_32.m4 b/autoconf/m4/linux_mixed_64_32.m4 new file mode 100644 index 00000000..123491f8 --- /dev/null +++ b/autoconf/m4/linux_mixed_64_32.m4 @@ -0,0 +1,17 @@ +# +# Some Linux machines run a 64-bit kernel with a 32-bit userspace. 'uname -m' +# shows these as x86_64. Ask the system 'gcc' what it thinks. +# +AC_DEFUN([AC_IS_LINUX_MIXED], +[AC_CACHE_CHECK(for 32-bit userspace on 64-bit system,llvm_cv_linux_mixed, +[ AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#ifndef __x86_64__ + error: Not x86-64 even if uname says so! + #endif + ]])], + [llvm_cv_linux_mixed=no], + [llvm_cv_linux_mixed=yes]) + AC_LANG_POP([C]) +]) +]) diff --git a/autoconf/m4/ltdl.m4 b/autoconf/m4/ltdl.m4 new file mode 100644 index 00000000..b3302fa6 --- /dev/null +++ b/autoconf/m4/ltdl.m4 @@ -0,0 +1,397 @@ +## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- +## Copyright (C) 1999-2000 Free Software Foundation, Inc. +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 7 AC_LIB_LTDL + +# AC_WITH_LTDL +# ------------ +# Clients of libltdl can use this macro to allow the installer to +# choose between a shipped copy of the ltdl sources or a preinstalled +# version of the library. +AC_DEFUN([AC_WITH_LTDL], +[AC_REQUIRE([AC_LIB_LTDL]) +AC_SUBST([LIBLTDL]) +AC_SUBST([INCLTDL]) + +# Unless the user asks us to check, assume no installed ltdl exists. +use_installed_libltdl=no + +AC_ARG_WITH([included_ltdl], + [ --with-included-ltdl use the GNU ltdl sources included here]) + +if test "x$with_included_ltdl" != xyes; then + # We are not being forced to use the included libltdl sources, so + # decide whether there is a useful installed version we can use. + AC_CHECK_HEADER([ltdl.h], + [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], + [with_included_ltdl=no], + [with_included_ltdl=yes]) + ]) +fi + +if test "x$enable_ltdl_install" != xyes; then + # If the user did not specify an installable libltdl, then default + # to a convenience lib. + AC_LIBLTDL_CONVENIENCE +fi + +if test "x$with_included_ltdl" = xno; then + # If the included ltdl is not to be used. then Use the + # preinstalled libltdl we found. + AC_DEFINE([HAVE_LTDL], [1], + [Define this if a modern libltdl is already installed]) + LIBLTDL=-lltdl +fi + +# Report our decision... +AC_MSG_CHECKING([whether to use included libltdl]) +AC_MSG_RESULT([$with_included_ltdl]) + +AC_CONFIG_SUBDIRS([libltdl]) +])# AC_WITH_LTDL + + +# AC_LIB_LTDL +# ----------- +# Perform all the checks necessary for compilation of the ltdl objects +# -- including compiler checks and header checks. +AC_DEFUN([AC_LIB_LTDL], +[AC_PREREQ(2.60) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_C_CONST]) +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_HEADER_DIRENT]) +AC_REQUIRE([_LT_AC_CHECK_DLFCN]) +AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) +AC_REQUIRE([AC_LTDL_SHLIBEXT]) +AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) +AC_REQUIRE([AC_LTDL_OBJDIR]) +AC_REQUIRE([AC_LTDL_DLPREOPEN]) +AC_REQUIRE([AC_LTDL_DLLIB]) +AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) +AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) +AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) + +AC_CHECK_HEADERS([errno.h malloc.h memory.h unistd.h]) +AC_CHECK_HEADERS([mach-o/dyld.h]) + +AC_CHECK_FUNCS([closedir opendir readdir]) +])# AC_LIB_LTDL + + +# AC_LTDL_ENABLE_INSTALL +# ---------------------- +AC_DEFUN([AC_LTDL_ENABLE_INSTALL], +[AC_ARG_ENABLE([ltdl-install], + [AS_HELP_STRING([--enable-ltdl-install],[install libltdl])]) + +AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) +AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) +])# AC_LTDL_ENABLE_INSTALL + + +# AC_LTDL_SYS_DLOPEN_DEPLIBS +# -------------------------- +AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_CHECK([whether deplibs are loaded by dlopen], + [libltdl_cv_sys_dlopen_deplibs], + [# PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[[45]]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[[12345]]*|irix6.[[01]]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[[1234]]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explicitly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + ]) +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], + [Define if the OS needs help to load dependent libraries for dlopen().]) +fi +])# AC_LTDL_SYS_DLOPEN_DEPLIBS + + +# AC_LTDL_SHLIBEXT +# ---------------- +AC_DEFUN([AC_LTDL_SHLIBEXT], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which extension is used for loadable modules], + [libltdl_cv_shlibext], +[ +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + ]) +if test -n "$libltdl_cv_shlibext"; then + AC_DEFINE_UNQUOTED([LTDL_SHLIB_EXT], ["$libltdl_cv_shlibext"], + [Define to the extension used for shared libraries, say, ".so".]) +fi +])# AC_LTDL_SHLIBEXT + +# AC_LTDL_SYSSEARCHPATH +# --------------------- +AC_DEFUN([AC_LTDL_SYSSEARCHPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([for the default library search path], + [libltdl_cv_sys_search_path], + [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + AC_DEFINE_UNQUOTED([LTDL_SYSSEARCHPATH], ["$sys_search_path"], + [Define to the system default library search path.]) +fi +])# AC_LTDL_SYSSEARCHPATH + + +# AC_LTDL_OBJDIR +# -------------- +AC_DEFUN([AC_LTDL_OBJDIR], +[AC_CACHE_CHECK([for objdir], + [libltdl_cv_objdir], + [libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + ]) +AC_DEFINE_UNQUOTED([LTDL_OBJDIR], ["$libltdl_cv_objdir/"], + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# AC_LTDL_OBJDIR + + +# AC_LTDL_DLPREOPEN +# ----------------- +AC_DEFUN([AC_LTDL_DLPREOPEN], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + [libltdl_cv_preloaded_symbols], + [if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + ]) +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1], + [Define if libtool can extract symbol lists from object files.]) +fi +])# AC_LTDL_DLPREOPEN + + +# AC_LTDL_DLLIB +# ------------- +AC_DEFUN([AC_LTDL_DLLIB], +[LIBADD_DL= +AC_SUBST(LIBADD_DL) +AC_LANG_PUSH([C]) + +AC_CHECK_FUNC([shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.])], + [AC_CHECK_LIB([dld], [shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_LIB([dl], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H +# include +#endif + ]], [[dlopen(0, 0);]])],[AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"],[AC_CHECK_LIB([svld], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], + [AC_CHECK_LIB([dld], [dld_link], + [AC_DEFINE([HAVE_DLD], [1], + [Define if you have the GNU dld library.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_FUNC([_dyld_func_lookup], + [AC_DEFINE([HAVE_DYLD], [1], + [Define if you have the _dyld_func_lookup function.])]) + ]) + ]) + ]) + ]) + ]) +]) + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + AC_CHECK_FUNCS([dlerror]) + LIBS="$lt_save_LIBS" +fi +AC_LANG_POP +])# AC_LTDL_DLLIB + + +# AC_LTDL_SYMBOL_USCORE +# --------------------- +# does the compiler prefix global symbols with an underscore? +AC_DEFUN([AC_LTDL_SYMBOL_USCORE], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([for _ prefix in compiled symbols], + [ac_cv_sys_symbol_underscore], + [ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.c >&AS_MESSAGE_LOG_FD + fi + rm -rf conftest* + ]) +])# AC_LTDL_SYMBOL_USCORE + + +# AC_LTDL_DLSYM_USCORE +# -------------------- +AC_DEFUN([AC_LTDL_DLSYM_USCORE], +[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + [libltdl_cv_need_uscore], + [libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + _LT_AC_TRY_DLOPEN_SELF( + [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], + [], [libltdl_cv_need_uscore=cross]) + LIBS="$save_LIBS" + ]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE([NEED_USCORE], [1], + [Define if dlsym() requires a leading underscore in symbol names.]) +fi +])# AC_LTDL_DLSYM_USCORE + +# AC_LTDL_FUNC_ARGZ +# ----------------- +AC_DEFUN([AC_LTDL_FUNC_ARGZ], +[AC_CHECK_HEADERS([argz.h]) + +AC_CHECK_TYPES([error_t], + [], + [AC_DEFINE([error_t], [int], + [Define to a type to use for `error_t' if it is not otherwise available.])], + [#if HAVE_ARGZ_H +# include +#endif]) + +AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) +])# AC_LTDL_FUNC_ARGZ diff --git a/autoconf/m4/need_dev_zero_for_mmap.m4 b/autoconf/m4/need_dev_zero_for_mmap.m4 new file mode 100644 index 00000000..57b32283 --- /dev/null +++ b/autoconf/m4/need_dev_zero_for_mmap.m4 @@ -0,0 +1,17 @@ +# +# When allocating RWX memory, check whether we need to use /dev/zero +# as the file descriptor or not. +# +AC_DEFUN([AC_NEED_DEV_ZERO_FOR_MMAP], +[AC_CACHE_CHECK([if /dev/zero is needed for mmap], +ac_cv_need_dev_zero_for_mmap, +[if test "$llvm_cv_os_type" = "Interix" ; then + ac_cv_need_dev_zero_for_mmap=yes + else + ac_cv_need_dev_zero_for_mmap=no + fi +]) +if test "$ac_cv_need_dev_zero_for_mmap" = yes; then + AC_DEFINE([NEED_DEV_ZERO_FOR_MMAP],[1], + [Define if /dev/zero should be used when mapping RWX memory, or undefine if its not necessary]) +fi]) diff --git a/autoconf/m4/path_tclsh.m4 b/autoconf/m4/path_tclsh.m4 new file mode 100644 index 00000000..85433de7 --- /dev/null +++ b/autoconf/m4/path_tclsh.m4 @@ -0,0 +1,39 @@ +dnl This macro checks for tclsh which is required to run dejagnu. On some +dnl platforms (notably FreeBSD), tclsh is named tclshX.Y - this handles +dnl that for us so we can get the latest installed tclsh version. +dnl +AC_DEFUN([DJ_AC_PATH_TCLSH], [ +no_itcl=true +AC_MSG_CHECKING(for the tclsh program in tclinclude directory) +AC_ARG_WITH(tclinclude, + AS_HELP_STRING([--with-tclinclude], + [directory where tcl headers are]), + [with_tclinclude=${withval}],[with_tclinclude='']) +AC_CACHE_VAL(ac_cv_path_tclsh,[ +dnl first check to see if --with-itclinclude was specified +if test x"${with_tclinclude}" != x ; then + if test -f ${with_tclinclude}/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}; pwd)` + elif test -f ${with_tclinclude}/src/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}/src; pwd)` + else + AC_MSG_ERROR([${with_tclinclude} directory doesn't contain tclsh]) + fi +fi]) + +dnl see if one is installed +if test x"${ac_cv_path_tclsh}" = x ; then + AC_MSG_RESULT(none) + AC_PATH_PROGS([TCLSH],[tclsh8.4 tclsh8.4.8 tclsh8.4.7 tclsh8.4.6 tclsh8.4.5 tclsh8.4.4 tclsh8.4.3 tclsh8.4.2 tclsh8.4.1 tclsh8.4.0 tclsh8.3 tclsh8.3.5 tclsh8.3.4 tclsh8.3.3 tclsh8.3.2 tclsh8.3.1 tclsh8.3.0 tclsh]) + if test x"${TCLSH}" = x ; then + ac_cv_path_tclsh=''; + else + ac_cv_path_tclsh="${TCLSH}"; + fi +else + AC_MSG_RESULT(${ac_cv_path_tclsh}) + TCLSH="${ac_cv_path_tclsh}" + AC_SUBST(TCLSH) +fi +]) + diff --git a/autoconf/m4/rand48.m4 b/autoconf/m4/rand48.m4 new file mode 100644 index 00000000..76f08faa --- /dev/null +++ b/autoconf/m4/rand48.m4 @@ -0,0 +1,12 @@ +# +# This function determins if the srand48,drand48,lrand48 functions are +# available on this platform. +# +AC_DEFUN([AC_FUNC_RAND48],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_rand48], + [srand48/lrand48/drand48], [], + [srand48(0);lrand48();drand48();]) +if test "$ac_cv_func_rand48" = "yes" ; then +AC_DEFINE([HAVE_RAND48],1,[Define to 1 if srand48/lrand48/drand48 exist in ]) +fi +]) diff --git a/autoconf/m4/sanity_check.m4 b/autoconf/m4/sanity_check.m4 new file mode 100644 index 00000000..639fccca --- /dev/null +++ b/autoconf/m4/sanity_check.m4 @@ -0,0 +1,31 @@ +dnl Check a program for version sanity. The test runs a program, passes it an +dnl argument to make it print out some identification string, and filters that +dnl output with a regular expression. If the output is non-empty, the program +dnl passes the sanity check. +dnl $1 - Name or full path of the program to run +dnl $2 - Argument to pass to print out identification string +dnl $3 - grep RE to match identification string +dnl $4 - set to 1 to make errors only a warning +AC_DEFUN([CHECK_PROGRAM_SANITY], +[ +AC_MSG_CHECKING([sanity for program ]$1) +sanity="0" +sanity_path=`which $1 2>/dev/null` +if test "$?" -eq 0 -a -x "$sanity_path" ; then + sanity=`$1 $2 2>&1 | grep "$3"` + if test -z "$sanity" ; then + AC_MSG_RESULT([no]) + sanity="0" + if test "$4" -eq 1 ; then + AC_MSG_WARN([Program ]$1[ failed to pass sanity check.]) + else + AC_MSG_ERROR([Program ]$1[ failed to pass sanity check.]) + fi + else + AC_MSG_RESULT([yes]) + sanity="1" + fi +else + AC_MSG_RESULT([not found]) +fi +]) diff --git a/autoconf/m4/single_cxx_check.m4 b/autoconf/m4/single_cxx_check.m4 new file mode 100644 index 00000000..cb473264 --- /dev/null +++ b/autoconf/m4/single_cxx_check.m4 @@ -0,0 +1,16 @@ +dnl +dnl AC_SINGLE_CXX_CHECK(CACHEVAR, FUNCTION, HEADER, PROGRAM) +dnl $1, $2, $3, $4, + +AC_DEFUN([AC_SINGLE_CXX_CHECK], +[ + AC_CACHE_CHECK([for $2 in $3], [$1], + [ + AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]][$3], [$4])], + [$1][[=yes]], + [$1][[=no]]) + AC_LANG_POP([C++]) + ]) +]) + diff --git a/autoconf/m4/visibility_inlines_hidden.m4 b/autoconf/m4/visibility_inlines_hidden.m4 new file mode 100644 index 00000000..b1cc42aa --- /dev/null +++ b/autoconf/m4/visibility_inlines_hidden.m4 @@ -0,0 +1,24 @@ +# +# Determine if the compiler accepts -fvisibility-inlines-hidden +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_CXX_USE_VISIBILITY_INLINES_HIDDEN], +[AC_CACHE_CHECK([for compiler -fvisibility-inlines-hidden option], + [llvm_cv_cxx_visibility_inlines_hidden], +[ AC_LANG_PUSH([C++]) + oldcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -O0 -fvisibility-inlines-hidden -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [template struct X { void __attribute__((noinline)) f() {} };], + [X().f();])], + [llvm_cv_cxx_visibility_inlines_hidden=yes],[llvm_cv_cxx_visibility_inlines_hidden=no]) + CXXFLAGS="$oldcxxflags" + AC_LANG_POP([C++]) +]) +if test "$llvm_cv_cxx_visibility_inlines_hidden" = yes ; then + AC_SUBST([ENABLE_VISIBILITY_INLINES_HIDDEN],[1]) +else + AC_SUBST([ENABLE_VISIBILITY_INLINES_HIDDEN],[0]) +fi +]) diff --git a/autoconf/missing b/autoconf/missing new file mode 100755 index 00000000..64b5f901 --- /dev/null +++ b/autoconf/missing @@ -0,0 +1,353 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2004-09-07.08 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit 0 + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit 0 + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/autoconf/mkinstalldirs b/autoconf/mkinstalldirs new file mode 100755 index 00000000..1ee2d580 --- /dev/null +++ b/autoconf/mkinstalldirs @@ -0,0 +1,150 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2004-02-15.20 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit 0 + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + # echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + # echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + # echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/bindings/LLVMBuild.txt b/bindings/LLVMBuild.txt new file mode 100644 index 00000000..241ac096 --- /dev/null +++ b/bindings/LLVMBuild.txt @@ -0,0 +1,21 @@ +;===- ./bindings/LLVMBuild.txt ---------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Group +name = Bindings +parent = $ROOT diff --git a/bindings/Makefile b/bindings/Makefile new file mode 100644 index 00000000..c545b288 --- /dev/null +++ b/bindings/Makefile @@ -0,0 +1,16 @@ +##===- bindings/Makefile -----------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := .. + +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS = $(BINDINGS_TO_BUILD) + +include $(LEVEL)/Makefile.common diff --git a/bindings/README.txt b/bindings/README.txt new file mode 100644 index 00000000..7693cb2c --- /dev/null +++ b/bindings/README.txt @@ -0,0 +1,3 @@ +This directory contains bindings for the LLVM compiler infrastructure to allow +programs written in languages other than C or C++ to take advantage of the LLVM +infrastructure--for instance, a self-hosted compiler front-end. diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile new file mode 100644 index 00000000..44562fe8 --- /dev/null +++ b/bindings/ocaml/Makefile @@ -0,0 +1,20 @@ +##===- bindings/ocaml/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../.. +DIRS = llvm bitreader bitwriter irreader analysis target executionengine \ + transforms linker backends +ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml + +ocamldoc: + $(Verb) for i in $(DIRS) ; do \ + $(MAKE) -C $$i ocamldoc; \ + done + +include $(LEVEL)/Makefile.common diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml new file mode 100644 index 00000000..f8ed841d --- /dev/null +++ b/bindings/ocaml/Makefile.ocaml @@ -0,0 +1,491 @@ +##===- bindings/ocaml/Makefile.ocaml -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# An OCaml library is a unique project type in the context of LLVM, so rules are +# here rather than in Makefile.rules. +# +# Reference materials on installing OCaml libraries: +# +# https://fedoraproject.org/wiki/Packaging/OCaml +# http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt +# +##===----------------------------------------------------------------------===## + +include $(LEVEL)/Makefile.config + +# CFLAGS needs to be set before Makefile.rules is included. +CXX.Flags += -I"$(shell $(OCAMLC) -where)" +C.Flags += -I"$(shell $(OCAMLC) -where)" + +ifeq ($(ENABLE_SHARED),1) +LINK_COMPONENTS := all +endif + +include $(LEVEL)/Makefile.common + +# Intentionally ignore PROJ_prefix here. We want the ocaml stdlib. However, the +# user can override this with OCAML_LIBDIR or configure --with-ocaml-libdir=. +PROJ_libocamldir := $(DESTDIR)$(OCAML_LIBDIR) +OcamlDir := $(LibDir)/ocaml + +# Info from llvm-config and similar +ifndef IS_CLEANING_TARGET +ifdef UsedComponents +UsedLibs = $(shell $(LLVM_CONFIG) --libs $(UsedComponents)) +UsedLibNames = $(shell $(LLVM_CONFIG) --libnames $(UsedComponents)) +endif +endif + +# How do we link OCaml executables with LLVM? +# 1) If this is a --enable-shared build, build stub libraries. This also allows +# to use LLVM from toplevels. +# 2) If this is a --disable-shared build, embed ocamlc options for building +# a custom runtime and a static executable. It is not possible to use LLVM +# from toplevels. +ifneq ($(ObjectsO),) +ifeq ($(ENABLE_SHARED),1) +OCAMLSTUBS := 1 +endif +endif + +# Tools +OCAMLCFLAGS += -I $(ObjDir) -I $(OcamlDir) +ifndef IS_CLEANING_TARGET +ifneq ($(ObjectsO),) +OCAMLAFLAGS += $(patsubst %,-cclib %, \ + $(filter-out -L$(LibDir),-l$(LIBRARYNAME) \ + $(shell $(LLVM_CONFIG) --ldflags)) \ + $(UsedLibs)) +else +OCAMLAFLAGS += $(patsubst %,-cclib %, \ + $(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG) --ldflags)) \ + $(UsedLibs)) +endif +endif + +# -g was introduced in 3.10.0. +#ifneq ($(ENABLE_OPTIMIZED),1) +# OCAMLDEBUGFLAG := -g +#endif + +Compile.CMI := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMO := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) + +ifdef OCAMLSTUBS +# Avoid the need for LD_LIBRARY_PATH +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS),Darwin) +OCAMLRPATH := $(RPATH) -Wl,'$(SharedLibDir)' +endif +endif +endif + +ifdef OCAMLSTUBS +Archive.CMA := $(strip $(OCAMLC) -a -dllib -l$(LIBRARYNAME) $(OCAMLDEBUGFLAG) \ + -o) +else +Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ + -o) +endif + +ifdef OCAMLSTUBS +Archive.CMXA := $(strip $(OCAMLOPT) -a $(patsubst %,-cclib %, \ + $(LLVMLibsOptions) -l$(LIBRARYNAME) \ + -L$(SharedLibDir) $(OCAMLRPATH)) \ + $(OCAMLDEBUGFLAG) -o) +else +Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) +endif + +ifdef OCAMLOPT +Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamlLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o) +else +Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o) +endif + +# Source files +ifndef OcamlSources1 +OcamlSources1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.ml)) +endif + +ifndef OcamlHeaders1 +OcamlHeaders1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.mli)) +endif + +OcamlSources2 := $(filter-out $(ExcludeSources),$(OcamlSources1)) +OcamlHeaders2 := $(filter-out $(ExcludeHeaders),$(OcamlHeaders1)) + +OcamlSources := $(OcamlSources2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) +OcamlHeaders := $(OcamlHeaders2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) + +# Intermediate files +ObjectsCMI := $(OcamlSources:%.ml=%.cmi) +ObjectsCMO := $(OcamlSources:%.ml=%.cmo) +ObjectsCMX := $(OcamlSources:%.ml=%.cmx) + +ifdef LIBRARYNAME +LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma +LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa +endif + +ifdef TOOLNAME +ToolEXE := $(ObjDir)/$(TOOLNAME)$(EXEEXT) +endif + +# Output files +# The .cmo files are the only intermediates; all others are to be installed. +OutputsCMI := $(ObjectsCMI:$(ObjDir)/%.cmi=$(OcamlDir)/%.cmi) +OutputsCMX := $(ObjectsCMX:$(ObjDir)/%.cmx=$(OcamlDir)/%.cmx) +OutputLibs := $(UsedLibNames:%=$(OcamlDir)/%) + +ifdef LIBRARYNAME +LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a +OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma) +OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa) +endif + +ifdef OCAMLSTUBS +SharedLib := $(OcamlDir)/dll$(LIBRARYNAME)$(SHLIBEXT) +endif + +ifdef TOOLNAME +ifdef EXAMPLE_TOOL +OutputEXE := $(ExmplDir)/$(strip $(TOOLNAME))$(EXEEXT) +else +OutputEXE := $(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT) +endif +endif + +# Installation targets +DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%) + +ifdef LIBRARYNAME +DestA := $(PROJ_libocamldir)/lib$(LIBRARYNAME).a +DestCMA := $(PROJ_libocamldir)/$(LIBRARYNAME).cma +DestCMXA := $(PROJ_libocamldir)/$(LIBRARYNAME).cmxa +endif + +ifdef OCAMLSTUBS +DestSharedLib := $(PROJ_libocamldir)/dll$(LIBRARYNAME)$(SHLIBEXT) +endif + +##===- Dependencies -------------------------------------------------------===## +# Copy the sources into the intermediate directory because older ocamlc doesn't +# support -o except when linking (outputs are placed next to inputs). + +$(ObjDir)/%.mli: $(PROJ_SRC_DIR)/%.mli $(ObjDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(ObjDir)/%.ml: $(PROJ_SRC_DIR)/%.ml $(ObjDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi) + +ifdef LIBRARYNAME +$(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ + $(OcamlDir)/.dir $(ObjDir)/.dir + $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + +-include $(ObjDir)/$(LIBRARYNAME).ocamldep +endif + +ifdef TOOLNAME +$(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ + $(OcamlDir)/.dir $(ObjDir)/.dir + $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + +-include $(ObjDir)/$(TOOLNAME).ocamldep +endif + +##===- Build static library from C sources --------------------------------===## + +ifdef LibraryA +all-local:: $(LibraryA) +clean-local:: clean-a +install-local:: install-a +uninstall-local:: uninstall-a + +$(LibraryA): $(ObjectsO) $(OcamlDir)/.dir + $(Echo) "Building $(BuildMode) $(notdir $@)" + -$(Verb) $(RM) -f $@ + $(Verb) $(Archive) $@ $(ObjectsO) + $(Verb) $(Ranlib) $@ + +clean-a:: + -$(Verb) $(RM) -f $(LibraryA) + +install-a:: $(LibraryA) + $(Echo) "Installing $(BuildMode) $(DestA)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(INSTALL) $(LibraryA) $(DestA) + $(Verb) + +uninstall-a:: + $(Echo) "Uninstalling $(DestA)" + -$(Verb) $(RM) -f $(DestA) +endif + + +##===- Build stub library from C sources ----------------------------------===## + +ifdef SharedLib +all-local:: $(SharedLib) +clean-local:: clean-shared +install-local:: install-shared +uninstall-local:: uninstall-shared + +$(SharedLib): $(ObjectsO) $(OcamlDir)/.dir + $(Echo) "Building $(BuildMode) $(notdir $@)" + $(Verb) $(Link) $(SharedLinkOptions) $(OCAMLRPATH) $(LLVMLibsOptions) \ + -o $@ $(ObjectsO) + +clean-shared:: + -$(Verb) $(RM) -f $(SharedLib) + +install-shared:: $(SharedLib) + $(Echo) "Installing $(BuildMode) $(DestSharedLib)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(INSTALL) $(SharedLib) $(DestSharedLib) + $(Verb) + +uninstall-shared:: + $(Echo) "Uninstalling $(DestSharedLib)" + -$(Verb) $(RM) -f $(DestSharedLib) +endif + + +##===- Deposit dependent libraries adjacent to Ocaml libs -----------------===## + +all-local:: build-deplibs +clean-local:: clean-deplibs +install-local:: install-deplibs +uninstall-local:: uninstall-deplibs + +build-deplibs: $(OutputLibs) + +$(OcamlDir)/%.a: $(LibDir)/%.a + $(Verb) ln -sf $< $@ + +$(OcamlDir)/%.o: $(LibDir)/%.o + $(Verb) ln -sf $< $@ + +clean-deplibs: + $(Verb) $(RM) -f $(OutputLibs) + +install-deplibs: + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) for i in $(DestLibs:$(PROJ_libocamldir)/%=%); do \ + ln -sf "$(PROJ_libdir)/$$i" "$(PROJ_libocamldir)/$$i"; \ + done + +uninstall-deplibs: + $(Verb) $(RM) -f $(DestLibs) + + +##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===## + +ifneq ($(OcamlHeaders),) +all-local:: build-cmis +clean-local:: clean-cmis +install-local:: install-cmis +uninstall-local:: uninstall-cmis + +build-cmis: $(OutputsCMI) + +$(OcamlDir)/%.cmi: $(ObjDir)/%.cmi $(OcamlDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(ObjDir)/%.cmi: $(ObjDir)/%.mli $(ObjDir)/.dir + $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" + $(Verb) $(Compile.CMI) $@ $< + +clean-cmis:: + -$(Verb) $(RM) -f $(OutputsCMI) + +# Also install the .mli's (headers) as documentation. +install-cmis: $(OutputsCMI) $(OcamlHeaders) + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ + $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ + $(DataInstall) $(ObjDir)/$$i "$(PROJ_libocamldir)/$$i"; \ + done + $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ + $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ + done + +uninstall-cmis:: + $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ + $(RM) -f "$(PROJ_libocamldir)/$$i"; \ + done + $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ + $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ + $(RM) -f "$(PROJ_libocamldir)/$$i"; \ + done +endif + + +##===- Build ocaml bytecode archive (.ml's -> .cmo's -> .cma) -------------===## + +$(ObjDir)/%.cmo: $(ObjDir)/%.ml + $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" + $(Verb) $(Compile.CMO) $@ $< + +ifdef LIBRARYNAME +all-local:: $(OutputCMA) +clean-local:: clean-cma +install-local:: install-cma +uninstall-local:: uninstall-cma + +$(OutputCMA): $(LibraryCMA) $(OcamlDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(LibraryCMA): $(ObjectsCMO) $(OcamlDir)/.dir + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.CMA) $@ $(ObjectsCMO) + +clean-cma:: + $(Verb) $(RM) -f $(OutputCMA) $(UsedLibNames:%=$(OcamlDir)/%) + +install-cma:: $(OutputCMA) + $(Echo) "Installing $(BuildMode) $(DestCMA)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(DataInstall) $(OutputCMA) "$(DestCMA)" + +uninstall-cma:: + $(Echo) "Uninstalling $(DestCMA)" + -$(Verb) $(RM) -f $(DestCMA) +endif + +##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===## + +# The ocamlopt compiler is supported on a set of targets disjoint from LLVM's. +# If unavailable, 'configure' will not define OCAMLOPT in Makefile.config. +ifdef OCAMLOPT + +$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx + $(Verb) $(CP) -f $< $@ + +$(ObjDir)/%.cmx: $(ObjDir)/%.ml + $(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build" + $(Verb) $(Compile.CMX) $@ $< + +ifdef LIBRARYNAME +all-local:: $(OutputCMXA) $(OutputsCMX) +clean-local:: clean-cmxa +install-local:: install-cmxa +uninstall-local:: uninstall-cmxa + +$(OutputCMXA): $(LibraryCMXA) + $(Verb) $(CP) -f $< $@ + $(Verb) $(CP) -f $(<:.cmxa=.a) $(@:.cmxa=.a) + +$(LibraryCMXA): $(ObjectsCMX) + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.CMXA) $@ $(ObjectsCMX) + $(Verb) $(RM) -f $(@:.cmxa=.o) + +clean-cmxa:: + $(Verb) $(RM) -f $(OutputCMXA) $(OutputCMXA:.cmxa=.a) $(OutputsCMX) + +install-cmxa:: $(OutputCMXA) $(OutputsCMX) + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Echo) "Installing $(BuildMode) $(DestCMXA)" + $(Verb) $(DataInstall) $(OutputCMXA) $(DestCMXA) + $(Echo) "Installing $(BuildMode) $(DestCMXA:.cmxa=.a)" + $(Verb) $(DataInstall) $(OutputCMXA:.cmxa=.a) $(DestCMXA:.cmxa=.a) + $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ + $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ + done + +uninstall-cmxa:: + $(Echo) "Uninstalling $(DestCMXA)" + $(Verb) $(RM) -f $(DestCMXA) + $(Echo) "Uninstalling $(DestCMXA:.cmxa=.a)" + $(Verb) $(RM) -f $(DestCMXA:.cmxa=.a) + $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ + $(RM) -f $(PROJ_libocamldir)/$$i; \ + done +endif +endif + +##===- Build executables --------------------------------------------------===## + +ifdef TOOLNAME +all-local:: $(OutputEXE) +clean-local:: clean-exe + +$(OutputEXE): $(ToolEXE) $(OcamlDir)/.dir + $(Verb) $(CP) -f $< $@ + +ifndef OCAMLOPT +$(ToolEXE): $(ObjectsCMO) $(OcamlDir)/.dir + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.EXE) $@ $(ObjectsCMO) +else +$(ToolEXE): $(ObjectsCMX) $(OcamlDir)/.dir + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.EXE) $@ $(ObjectsCMX) +endif +endif + +##===- Generate documentation ---------------------------------------------===## + +$(ObjDir)/$(LIBRARYNAME).odoc: $(ObjectsCMI) + $(Echo) "Documenting $(notdir $@)" + $(Verb) $(OCAMLDOC) -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) + +ocamldoc: $(ObjDir)/$(LIBRARYNAME).odoc + +##===- Debugging gunk -----------------------------------------------------===## +printvars:: printcamlvars + +printcamlvars:: + $(Echo) "LLVM_CONFIG : " '$(LLVM_CONFIG)' + $(Echo) "OCAMLCFLAGS : " '$(OCAMLCFLAGS)' + $(Echo) "OCAMLAFLAGS : " '$(OCAMLAFLAGS)' + $(Echo) "OCAMLC : " '$(OCAMLC)' + $(Echo) "OCAMLOPT : " '$(OCAMLOPT)' + $(Echo) "OCAMLDEP : " '$(OCAMLDEP)' + $(Echo) "Compile.CMI : " '$(Compile.CMI)' + $(Echo) "Compile.CMO : " '$(Compile.CMO)' + $(Echo) "Archive.CMA : " '$(Archive.CMA)' + $(Echo) "Compile.CMX : " '$(Compile.CMX)' + $(Echo) "Archive.CMXA : " '$(Archive.CMXA)' + $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' + $(Echo) "LibraryCMA : " '$(LibraryCMA)' + $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' + $(Echo) "SharedLib : " '$(SharedLib)' + $(Echo) "OcamlSources1: " '$(OcamlSources1)' + $(Echo) "OcamlSources2: " '$(OcamlSources2)' + $(Echo) "OcamlSources : " '$(OcamlSources)' + $(Echo) "OcamlHeaders1: " '$(OcamlHeaders1)' + $(Echo) "OcamlHeaders2: " '$(OcamlHeaders2)' + $(Echo) "OcamlHeaders : " '$(OcamlHeaders)' + $(Echo) "ObjectsCMI : " '$(ObjectsCMI)' + $(Echo) "ObjectsCMO : " '$(ObjectsCMO)' + $(Echo) "ObjectsCMX : " '$(ObjectsCMX)' + $(Echo) "OCAML_LIBDIR : " '$(OCAML_LIBDIR)' + $(Echo) "DestA : " '$(DestA)' + $(Echo) "DestCMA : " '$(DestCMA)' + $(Echo) "DestCMXA : " '$(DestCMXA)' + $(Echo) "DestSharedLib: " '$(DestSharedLib)' + $(Echo) "UsedLibs : " '$(UsedLibs)' + $(Echo) "UsedLibNames : " '$(UsedLibNames)' + +.PHONY: printcamlvars build-cmis \ + clean-a clean-cmis clean-cma clean-cmxa \ + install-a install-cmis install-cma install-cmxa \ + install-exe \ + uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa \ + uninstall-exe diff --git a/bindings/ocaml/analysis/Makefile b/bindings/ocaml/analysis/Makefile new file mode 100644 index 00000000..cbfcb246 --- /dev/null +++ b/bindings/ocaml/analysis/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/analysis/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_analysis interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_analysis +UsedComponents := analysis +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/analysis/analysis_ocaml.c b/bindings/ocaml/analysis/analysis_ocaml.c new file mode 100644 index 00000000..91be2d3f --- /dev/null +++ b/bindings/ocaml/analysis/analysis_ocaml.c @@ -0,0 +1,72 @@ +/*===-- analysis_ocaml.c - LLVM OCaml Glue ----------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Analysis.h" +#include "caml/alloc.h" +#include "caml/mlvalues.h" +#include "caml/memory.h" + + +/* Llvm.llmodule -> string option */ +CAMLprim value llvm_verify_module(LLVMModuleRef M) { + CAMLparam0(); + CAMLlocal2(String, Option); + + char *Message; + int Result = LLVMVerifyModule(M, LLVMReturnStatusAction, &Message); + + if (0 == Result) { + Option = Val_int(0); + } else { + Option = alloc(1, 0); + String = copy_string(Message); + Store_field(Option, 0, String); + } + + LLVMDisposeMessage(Message); + + CAMLreturn(Option); +} + +/* Llvm.llvalue -> bool */ +CAMLprim value llvm_verify_function(LLVMValueRef Fn) { + return Val_bool(LLVMVerifyFunction(Fn, LLVMReturnStatusAction) == 0); +} + +/* Llvm.llmodule -> unit */ +CAMLprim value llvm_assert_valid_module(LLVMModuleRef M) { + LLVMVerifyModule(M, LLVMAbortProcessAction, 0); + return Val_unit; +} + +/* Llvm.llvalue -> unit */ +CAMLprim value llvm_assert_valid_function(LLVMValueRef Fn) { + LLVMVerifyFunction(Fn, LLVMAbortProcessAction); + return Val_unit; +} + +/* Llvm.llvalue -> unit */ +CAMLprim value llvm_view_function_cfg(LLVMValueRef Fn) { + LLVMViewFunctionCFG(Fn); + return Val_unit; +} + +/* Llvm.llvalue -> unit */ +CAMLprim value llvm_view_function_cfg_only(LLVMValueRef Fn) { + LLVMViewFunctionCFGOnly(Fn); + return Val_unit; +} diff --git a/bindings/ocaml/analysis/llvm_analysis.ml b/bindings/ocaml/analysis/llvm_analysis.ml new file mode 100644 index 00000000..21088ab6 --- /dev/null +++ b/bindings/ocaml/analysis/llvm_analysis.ml @@ -0,0 +1,22 @@ +(*===-- llvm_analysis.ml - LLVM OCaml Interface -----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +external verify_module : Llvm.llmodule -> string option = "llvm_verify_module" + +external verify_function : Llvm.llvalue -> bool = "llvm_verify_function" + +external assert_valid_module : Llvm.llmodule -> unit + = "llvm_assert_valid_module" + +external assert_valid_function : Llvm.llvalue -> unit + = "llvm_assert_valid_function" +external view_function_cfg : Llvm.llvalue -> unit = "llvm_view_function_cfg" +external view_function_cfg_only : Llvm.llvalue -> unit + = "llvm_view_function_cfg_only" diff --git a/bindings/ocaml/analysis/llvm_analysis.mli b/bindings/ocaml/analysis/llvm_analysis.mli new file mode 100644 index 00000000..1a0af02b --- /dev/null +++ b/bindings/ocaml/analysis/llvm_analysis.mli @@ -0,0 +1,46 @@ +(*===-- llvm_analysis.mli - LLVM OCaml Interface ----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Intermediate representation analysis. + + This interface provides an OCaml API for LLVM IR analyses, the classes in + the Analysis library. *) + +(** [verify_module m] returns [None] if the module [m] is valid, and + [Some reason] if it is invalid. [reason] is a string containing a + human-readable validation report. See [llvm::verifyModule]. *) +external verify_module : Llvm.llmodule -> string option = "llvm_verify_module" + +(** [verify_function f] returns [None] if the function [f] is valid, and + [Some reason] if it is invalid. [reason] is a string containing a + human-readable validation report. See [llvm::verifyFunction]. *) +external verify_function : Llvm.llvalue -> bool = "llvm_verify_function" + +(** [verify_module m] returns if the module [m] is valid, but prints a + validation report to [stderr] and aborts the program if it is invalid. See + [llvm::verifyModule]. *) +external assert_valid_module : Llvm.llmodule -> unit + = "llvm_assert_valid_module" + +(** [verify_function f] returns if the function [f] is valid, but prints a + validation report to [stderr] and aborts the program if it is invalid. See + [llvm::verifyFunction]. *) +external assert_valid_function : Llvm.llvalue -> unit + = "llvm_assert_valid_function" + +(** [view_function_cfg f] opens up a ghostscript window displaying the CFG of + the current function with the code for each basic block inside. + See [llvm::Function::viewCFG]. *) +external view_function_cfg : Llvm.llvalue -> unit = "llvm_view_function_cfg" + +(** [view_function_cfg_only f] works just like [view_function_cfg], but does not + include the contents of basic blocks into the nodes. + See [llvm::Function::viewCFGOnly]. *) +external view_function_cfg_only : Llvm.llvalue -> unit + = "llvm_view_function_cfg_only" diff --git a/bindings/ocaml/backends/META.llvm_backend.in b/bindings/ocaml/backends/META.llvm_backend.in new file mode 100644 index 00000000..0d4a6d68 --- /dev/null +++ b/bindings/ocaml/backends/META.llvm_backend.in @@ -0,0 +1,8 @@ +name = "llvm_@TARGET@" +version = "@PACKAGE_VERSION@" +description = "@TARGET@ Backend for LLVM" +requires = "llvm" +archive(byte) = "llvm_@TARGET@.cma" +archive(native) = "llvm_@TARGET@.cmxa" +directory = "." +linkopts = "-ccopt -lstdc++" \ No newline at end of file diff --git a/bindings/ocaml/backends/Makefile b/bindings/ocaml/backends/Makefile new file mode 100644 index 00000000..ff39212c --- /dev/null +++ b/bindings/ocaml/backends/Makefile @@ -0,0 +1,61 @@ +##===- bindings/ocaml/backends/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the master makefile for backend-specific bindings. It works by +# creating a stub makefile for each configured target, e.g. Makefile.ARM, and +# invoking it to compile the corresponding library, e.g. Llvm_ARM. +# +# This scheme allows to keep changes to Makefile.ocaml minimal. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.common + +include $(LEVEL)/Makefile.config +include $(LEVEL)/Makefile.common + +all-local:: all-backends +clean-local:: clean-backends +install-local:: install-backends +uninstall-local:: uninstall-backends + +stubs: + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(ECHO) "TARGET := $$i" > Makefile.$$i; \ + $(ECHO) "include Makefile.common" >> Makefile.$$i; \ + done + +all-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i all; \ + done + +clean-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i clean; \ + $(RM) -f Makefile.$$i; \ + done + +install-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i install; \ + done + +uninstall-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i uninstall; \ + done + +ocamldoc: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i ocamldoc; \ + done + +.PHONY: all-backends clean-backends install-backends uninstall-backends ocamldoc diff --git a/bindings/ocaml/backends/Makefile.common b/bindings/ocaml/backends/Makefile.common new file mode 100644 index 00000000..be65dd0f --- /dev/null +++ b/bindings/ocaml/backends/Makefile.common @@ -0,0 +1,65 @@ +##===- bindings/ocaml/backends/Makefile.common -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the slave makefile for backend-specific bindings. This makefile should +# be included after defining TARGET. It will then substitute @TARGET@ for +# the value of TARGET in various *.in files and build an OCaml library in +# a regular way. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_$(TARGET) +UsedComponents := $(TARGET) +UsedOcamlInterfaces := llvm + +include $(LEVEL)/Makefile.config + +SOURCES := $(TARGET)_ocaml.c +OcamlHeaders1 := $(PROJ_SRC_DIR)/llvm_$(TARGET).mli +OcamlSources1 := $(PROJ_SRC_DIR)/llvm_$(TARGET).ml + +include ../Makefile.ocaml + +$(ObjDir)/llvm_$(TARGET).ml: $(PROJ_SRC_DIR)/llvm_backend.ml.in $(ObjDir)/.dir + $(Verb) $(SED) -e 's/@TARGET@/$(TARGET)/' $< > $@ + +$(ObjDir)/llvm_$(TARGET).mli: $(PROJ_SRC_DIR)/llvm_backend.mli.in $(ObjDir)/.dir + $(Verb) $(SED) -e 's/@TARGET@/$(TARGET)/' $< > $@ + +$(ObjDir)/$(TARGET)_ocaml.o: $(PROJ_SRC_DIR)/backend_ocaml.c $(ObjDir)/.dir + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Verb) $(Compile.C) -DTARGET=$(TARGET) $< -o $@ + + +##===- OCamlFind Package --------------------------------------------------===## + +all-local:: copy-meta +install-local:: install-meta +uninstall-local:: uninstall-meta + +DestMETA := $(PROJ_libocamldir)/META.llvm_$(TARGET) + +# Easy way of generating META in the objdir +copy-meta: $(OcamlDir)/META.llvm_$(TARGET) + +$(OcamlDir)/META.llvm_$(TARGET): META.llvm_backend.in + $(Verb) $(SED) -e 's/@TARGET@/$(TARGET)/' \ + -e 's/@PACKAGE_VERSION@/$(LLVMVersion)/' $< > $@ + +install-meta:: $(OcamlDir)/META.llvm_$(TARGET) + $(Echo) "Install $(BuildMode) $(DestMETA)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(DataInstall) $< "$(DestMETA)" + +uninstall-meta:: + $(Echo) "Uninstalling $(DestMETA)" + -$(Verb) $(RM) -f "$(DestMETA)" + +.PHONY: copy-meta install-meta uninstall-meta diff --git a/bindings/ocaml/backends/backend_ocaml.c b/bindings/ocaml/backends/backend_ocaml.c new file mode 100644 index 00000000..2d4ba852 --- /dev/null +++ b/bindings/ocaml/backends/backend_ocaml.c @@ -0,0 +1,37 @@ +/*===-- backend_ocaml.c - LLVM OCaml Glue -----------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Target.h" +#include "caml/alloc.h" +#include "caml/memory.h" + +// TODO: Figure out how to call these only for targets which support them. +// LLVMInitialize ## target ## AsmPrinter(); +// LLVMInitialize ## target ## AsmParser(); +// LLVMInitialize ## target ## Disassembler(); + +#define INITIALIZER1(target) \ + CAMLprim value llvm_initialize_ ## target(value Unit) { \ + LLVMInitialize ## target ## TargetInfo(); \ + LLVMInitialize ## target ## Target(); \ + LLVMInitialize ## target ## TargetMC(); \ + return Val_unit; \ + } + +#define INITIALIZER(target) INITIALIZER1(target) + +INITIALIZER(TARGET) diff --git a/bindings/ocaml/backends/llvm_backend.ml.in b/bindings/ocaml/backends/llvm_backend.ml.in new file mode 100644 index 00000000..bd1e5860 --- /dev/null +++ b/bindings/ocaml/backends/llvm_backend.ml.in @@ -0,0 +1,10 @@ +(*===-- llvm_backend.ml.in - LLVM OCaml Interface -------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +external initialize : unit -> unit = "llvm_initialize_@TARGET@" diff --git a/bindings/ocaml/backends/llvm_backend.mli.in b/bindings/ocaml/backends/llvm_backend.mli.in new file mode 100644 index 00000000..9506789a --- /dev/null +++ b/bindings/ocaml/backends/llvm_backend.mli.in @@ -0,0 +1,19 @@ +(*===-- llvm_backend.mli.in - LLVM OCaml Interface ------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** @TARGET@ Initialization. + + This interface provides an OCaml API for initialization of + the @TARGET@ LLVM target. By referencing this module, you will cause + OCaml to load or link in the LLVM libraries corresponding to the target. + By calling [initialize], you will register components of this target + in the target registry, which is necessary in order to emit assembly, + object files, and so on. *) + +external initialize : unit -> unit = "llvm_initialize_@TARGET@" \ No newline at end of file diff --git a/bindings/ocaml/bitreader/Makefile b/bindings/ocaml/bitreader/Makefile new file mode 100644 index 00000000..a1c7de89 --- /dev/null +++ b/bindings/ocaml/bitreader/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/bitreader/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_bitreader interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_bitreader +UsedComponents := bitreader +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/bitreader/bitreader_ocaml.c b/bindings/ocaml/bitreader/bitreader_ocaml.c new file mode 100644 index 00000000..0264e731 --- /dev/null +++ b/bindings/ocaml/bitreader/bitreader_ocaml.c @@ -0,0 +1,73 @@ +/*===-- bitwriter_ocaml.c - LLVM OCaml Glue ---------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/BitReader.h" +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" + + +/* Can't use the recommended caml_named_value mechanism for backwards + compatibility reasons. This is largely equivalent. */ +static value llvm_bitreader_error_exn; + +CAMLprim value llvm_register_bitreader_exns(value Error) { + llvm_bitreader_error_exn = Field(Error, 0); + register_global_root(&llvm_bitreader_error_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + + +/*===-- Modules -----------------------------------------------------------===*/ + +/* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ +CAMLprim value llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { + CAMLparam0(); + CAMLlocal2(Variant, MessageVal); + char *Message; + + LLVMModuleRef M; + if (LLVMGetBitcodeModuleInContext(C, MemBuf, &M, &Message)) + llvm_raise(llvm_bitreader_error_exn, Message); + + CAMLreturn((value) M); +} + +/* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ +CAMLprim value llvm_parse_bitcode(LLVMContextRef C, + LLVMMemoryBufferRef MemBuf) { + CAMLparam0(); + CAMLlocal2(Variant, MessageVal); + LLVMModuleRef M; + char *Message; + + if (LLVMParseBitcodeInContext(C, MemBuf, &M, &Message)) + llvm_raise(llvm_bitreader_error_exn, Message); + + CAMLreturn((value) M); +} diff --git a/bindings/ocaml/bitreader/llvm_bitreader.ml b/bindings/ocaml/bitreader/llvm_bitreader.ml new file mode 100644 index 00000000..865208c1 --- /dev/null +++ b/bindings/ocaml/bitreader/llvm_bitreader.ml @@ -0,0 +1,20 @@ +(*===-- llvm_bitreader.ml - LLVM OCaml Interface ----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_bitreader_exns" +let _ = register_exns (Error "") + +external get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_get_module" + +external parse_bitcode : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_parse_bitcode" diff --git a/bindings/ocaml/bitreader/llvm_bitreader.mli b/bindings/ocaml/bitreader/llvm_bitreader.mli new file mode 100644 index 00000000..ff377b9b --- /dev/null +++ b/bindings/ocaml/bitreader/llvm_bitreader.mli @@ -0,0 +1,28 @@ +(*===-- llvm_bitreader.mli - LLVM OCaml Interface ---------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Bitcode reader. + + This interface provides an OCaml API for the LLVM bitcode reader, the + classes in the Bitreader library. *) + +exception Error of string + +(** [get_module context mb] reads the bitcode for a new module [m] from the + memory buffer [mb] in the context [context]. Returns [m] if successful, or + raises [Error msg] otherwise, where [msg] is a description of the error + encountered. See the function [llvm::getBitcodeModule]. *) +val get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + + +(** [parse_bitcode context mb] parses the bitcode for a new module [m] from the + memory buffer [mb] in the context [context]. Returns [m] if successful, or + raises [Error msg] otherwise, where [msg] is a description of the error + encountered. See the function [llvm::ParseBitcodeFile]. *) +val parse_bitcode : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule diff --git a/bindings/ocaml/bitwriter/Makefile b/bindings/ocaml/bitwriter/Makefile new file mode 100644 index 00000000..cec0a59c --- /dev/null +++ b/bindings/ocaml/bitwriter/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/bitwriter/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_bitwriter interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_bitwriter +UsedComponents := bitwriter +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/bitwriter/bitwriter_ocaml.c b/bindings/ocaml/bitwriter/bitwriter_ocaml.c new file mode 100644 index 00000000..a47f7003 --- /dev/null +++ b/bindings/ocaml/bitwriter/bitwriter_ocaml.c @@ -0,0 +1,45 @@ +/*===-- bitwriter_ocaml.c - LLVM OCaml Glue ---------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/BitWriter.h" +#include "llvm-c/Core.h" +#include "caml/alloc.h" +#include "caml/mlvalues.h" +#include "caml/memory.h" + +/*===-- Modules -----------------------------------------------------------===*/ + +/* Llvm.llmodule -> string -> bool */ +CAMLprim value llvm_write_bitcode_file(value M, value Path) { + int res = LLVMWriteBitcodeToFile((LLVMModuleRef) M, String_val(Path)); + return Val_bool(res == 0); +} + +/* ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool */ +CAMLprim value llvm_write_bitcode_to_fd(value U, value M, value FD) { + int Unbuffered; + int res; + + if (U == Val_int(0)) { + Unbuffered = 0; + } else { + Unbuffered = Bool_val(Field(U,0)); + } + + res = LLVMWriteBitcodeToFD((LLVMModuleRef) M, Int_val(FD), 0, Unbuffered); + return Val_bool(res == 0); +} diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.ml b/bindings/ocaml/bitwriter/llvm_bitwriter.ml new file mode 100644 index 00000000..fac85538 --- /dev/null +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.ml @@ -0,0 +1,25 @@ +(*===-- llvm_bitwriter.ml - LLVM OCaml Interface ----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------=== + * + * This interface provides an OCaml API for the LLVM intermediate + * representation, the classes in the VMCore library. + * + *===----------------------------------------------------------------------===*) + + +(* Writes the bitcode for module the given path. Returns true if successful. *) +external write_bitcode_file : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" + +external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule + -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +let output_bitcode ?unbuffered channel m = + write_bitcode_to_fd ?unbuffered m (Unix.descr_of_out_channel channel) diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.mli b/bindings/ocaml/bitwriter/llvm_bitwriter.mli new file mode 100644 index 00000000..bb3e3b89 --- /dev/null +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.mli @@ -0,0 +1,30 @@ +(*===-- llvm_bitwriter.mli - LLVM OCaml Interface ---------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Bitcode writer. + + This interface provides an OCaml API for the LLVM bitcode writer, the + classes in the Bitwriter library. *) + +(** [write_bitcode_file m path] writes the bitcode for module [m] to the file at + [path]. Returns [true] if successful, [false] otherwise. *) +external write_bitcode_file : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" + +(** [write_bitcode_to_fd ~unbuffered fd m] writes the bitcode for module + [m] to the channel [c]. If [unbuffered] is [true], after every write the fd + will be flushed. Returns [true] if successful, [false] otherwise. *) +external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule + -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +(** [output_bitcode ~unbuffered c m] writes the bitcode for module [m] + to the channel [c]. If [unbuffered] is [true], after every write the fd + will be flushed. Returns [true] if successful, [false] otherwise. *) +val output_bitcode : ?unbuffered:bool -> out_channel -> Llvm.llmodule -> bool diff --git a/bindings/ocaml/executionengine/Makefile b/bindings/ocaml/executionengine/Makefile new file mode 100644 index 00000000..5fa3f220 --- /dev/null +++ b/bindings/ocaml/executionengine/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/executionengine/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_executionengine interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_executionengine +UsedComponents := executionengine jit interpreter native +UsedOcamlInterfaces := llvm llvm_target + +include ../Makefile.ocaml diff --git a/bindings/ocaml/executionengine/executionengine_ocaml.c b/bindings/ocaml/executionengine/executionengine_ocaml.c new file mode 100644 index 00000000..4b44a910 --- /dev/null +++ b/bindings/ocaml/executionengine/executionengine_ocaml.c @@ -0,0 +1,341 @@ +/*===-- executionengine_ocaml.c - LLVM OCaml Glue ---------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/ExecutionEngine.h" +#include "llvm-c/Target.h" +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include +#include + +/* Force the LLVM interpreter and JIT to be linked in. */ +void llvm_initialize(void) { + LLVMLinkInInterpreter(); + LLVMLinkInJIT(); +} + +/* unit -> bool */ +CAMLprim value llvm_initialize_native_target(value Unit) { + return Val_bool(LLVMInitializeNativeTarget()); +} + +/* Can't use the recommended caml_named_value mechanism for backwards + compatibility reasons. This is largely equivalent. */ +static value llvm_ee_error_exn; + +CAMLprim value llvm_register_ee_exns(value Error) { + llvm_ee_error_exn = Field(Error, 0); + register_global_root(&llvm_ee_error_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + + +/*--... Operations on generic values .......................................--*/ + +#define Genericvalue_val(v) (*(LLVMGenericValueRef *)(Data_custom_val(v))) + +static void llvm_finalize_generic_value(value GenVal) { + LLVMDisposeGenericValue(Genericvalue_val(GenVal)); +} + +static struct custom_operations generic_value_ops = { + (char *) "LLVMGenericValue", + llvm_finalize_generic_value, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +static value alloc_generic_value(LLVMGenericValueRef Ref) { + value Val = alloc_custom(&generic_value_ops, sizeof(LLVMGenericValueRef), 0, 1); + Genericvalue_val(Val) = Ref; + return Val; +} + +/* Llvm.lltype -> float -> t */ +CAMLprim value llvm_genericvalue_of_float(LLVMTypeRef Ty, value N) { + CAMLparam1(N); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfFloat(Ty, Double_val(N)))); +} + +/* 'a -> t */ +CAMLprim value llvm_genericvalue_of_pointer(value V) { + CAMLparam1(V); + CAMLreturn(alloc_generic_value(LLVMCreateGenericValueOfPointer(Op_val(V)))); +} + +/* Llvm.lltype -> int -> t */ +CAMLprim value llvm_genericvalue_of_int(LLVMTypeRef Ty, value Int) { + return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int_val(Int), 1)); +} + +/* Llvm.lltype -> int32 -> t */ +CAMLprim value llvm_genericvalue_of_int32(LLVMTypeRef Ty, value Int32) { + CAMLparam1(Int32); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfInt(Ty, Int32_val(Int32), 1))); +} + +/* Llvm.lltype -> nativeint -> t */ +CAMLprim value llvm_genericvalue_of_nativeint(LLVMTypeRef Ty, value NatInt) { + CAMLparam1(NatInt); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfInt(Ty, Nativeint_val(NatInt), 1))); +} + +/* Llvm.lltype -> int64 -> t */ +CAMLprim value llvm_genericvalue_of_int64(LLVMTypeRef Ty, value Int64) { + CAMLparam1(Int64); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfInt(Ty, Int64_val(Int64), 1))); +} + +/* Llvm.lltype -> t -> float */ +CAMLprim value llvm_genericvalue_as_float(LLVMTypeRef Ty, value GenVal) { + CAMLparam1(GenVal); + CAMLreturn(copy_double( + LLVMGenericValueToFloat(Ty, Genericvalue_val(GenVal)))); +} + +/* t -> 'a */ +CAMLprim value llvm_genericvalue_as_pointer(value GenVal) { + return Val_op(LLVMGenericValueToPointer(Genericvalue_val(GenVal))); +} + +/* t -> int */ +CAMLprim value llvm_genericvalue_as_int(value GenVal) { + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) + && "Generic value too wide to treat as an int!"); + return Val_int(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1)); +} + +/* t -> int32 */ +CAMLprim value llvm_genericvalue_as_int32(value GenVal) { + CAMLparam1(GenVal); + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 32 + && "Generic value too wide to treat as an int32!"); + CAMLreturn(copy_int32(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); +} + +/* t -> int64 */ +CAMLprim value llvm_genericvalue_as_int64(value GenVal) { + CAMLparam1(GenVal); + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 64 + && "Generic value too wide to treat as an int64!"); + CAMLreturn(copy_int64(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); +} + +/* t -> nativeint */ +CAMLprim value llvm_genericvalue_as_nativeint(value GenVal) { + CAMLparam1(GenVal); + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) + && "Generic value too wide to treat as a nativeint!"); + CAMLreturn(copy_nativeint(LLVMGenericValueToInt(Genericvalue_val(GenVal),1))); +} + + +/*--... Operations on execution engines ....................................--*/ + +/* llmodule -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleRef M) { + LLVMExecutionEngineRef Interp; + char *Error; + if (LLVMCreateExecutionEngineForModule(&Interp, M, &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return Interp; +} + +/* llmodule -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef +llvm_ee_create_interpreter(LLVMModuleRef M) { + LLVMExecutionEngineRef Interp; + char *Error; + if (LLVMCreateInterpreterForModule(&Interp, M, &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return Interp; +} + +/* llmodule -> int -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef +llvm_ee_create_jit(LLVMModuleRef M, value OptLevel) { + LLVMExecutionEngineRef JIT; + char *Error; + if (LLVMCreateJITCompilerForModule(&JIT, M, Int_val(OptLevel), &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return JIT; +} + +/* ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_dispose(LLVMExecutionEngineRef EE) { + LLVMDisposeExecutionEngine(EE); + return Val_unit; +} + +/* llmodule -> ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_add_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { + LLVMAddModule(EE, M); + return Val_unit; +} + +/* llmodule -> ExecutionEngine.t -> llmodule */ +CAMLprim LLVMModuleRef llvm_ee_remove_module(LLVMModuleRef M, + LLVMExecutionEngineRef EE) { + LLVMModuleRef RemovedModule; + char *Error; + if (LLVMRemoveModule(EE, M, &RemovedModule, &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return RemovedModule; +} + +/* string -> ExecutionEngine.t -> llvalue option */ +CAMLprim value llvm_ee_find_function(value Name, LLVMExecutionEngineRef EE) { + CAMLparam1(Name); + CAMLlocal1(Option); + LLVMValueRef Found; + if (LLVMFindFunction(EE, String_val(Name), &Found)) + CAMLreturn(Val_unit); + Option = alloc(1, 0); + Field(Option, 0) = Val_op(Found); + CAMLreturn(Option); +} + +/* llvalue -> GenericValue.t array -> ExecutionEngine.t -> GenericValue.t */ +CAMLprim value llvm_ee_run_function(LLVMValueRef F, value Args, + LLVMExecutionEngineRef EE) { + unsigned NumArgs; + LLVMGenericValueRef Result, *GVArgs; + unsigned I; + + NumArgs = Wosize_val(Args); + GVArgs = (LLVMGenericValueRef*) malloc(NumArgs * sizeof(LLVMGenericValueRef)); + for (I = 0; I != NumArgs; ++I) + GVArgs[I] = Genericvalue_val(Field(Args, I)); + + Result = LLVMRunFunction(EE, F, NumArgs, GVArgs); + + free(GVArgs); + return alloc_generic_value(Result); +} + +/* ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_run_static_ctors(LLVMExecutionEngineRef EE) { + LLVMRunStaticConstructors(EE); + return Val_unit; +} + +/* ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) { + LLVMRunStaticDestructors(EE); + return Val_unit; +} + +/* llvalue -> string array -> (string * string) array -> ExecutionEngine.t -> + int */ +CAMLprim value llvm_ee_run_function_as_main(LLVMValueRef F, + value Args, value Env, + LLVMExecutionEngineRef EE) { + CAMLparam2(Args, Env); + int I, NumArgs, NumEnv, EnvSize, Result; + const char **CArgs, **CEnv; + char *CEnvBuf, *Pos; + + NumArgs = Wosize_val(Args); + NumEnv = Wosize_val(Env); + + /* Build the environment. */ + CArgs = (const char **) malloc(NumArgs * sizeof(char*)); + for (I = 0; I != NumArgs; ++I) + CArgs[I] = String_val(Field(Args, I)); + + /* Compute the size of the environment string buffer. */ + for (I = 0, EnvSize = 0; I != NumEnv; ++I) { + EnvSize += strlen(String_val(Field(Field(Env, I), 0))) + 1; + EnvSize += strlen(String_val(Field(Field(Env, I), 1))) + 1; + } + + /* Build the environment. */ + CEnv = (const char **) malloc((NumEnv + 1) * sizeof(char*)); + CEnvBuf = (char*) malloc(EnvSize); + Pos = CEnvBuf; + for (I = 0; I != NumEnv; ++I) { + char *Name = String_val(Field(Field(Env, I), 0)), + *Value = String_val(Field(Field(Env, I), 1)); + int NameLen = strlen(Name), + ValueLen = strlen(Value); + + CEnv[I] = Pos; + memcpy(Pos, Name, NameLen); + Pos += NameLen; + *Pos++ = '='; + memcpy(Pos, Value, ValueLen); + Pos += ValueLen; + *Pos++ = '\0'; + } + CEnv[NumEnv] = NULL; + + Result = LLVMRunFunctionAsMain(EE, F, NumArgs, CArgs, CEnv); + + free(CArgs); + free(CEnv); + free(CEnvBuf); + + CAMLreturn(Val_int(Result)); +} + +/* llvalue -> ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_free_machine_code(LLVMValueRef F, + LLVMExecutionEngineRef EE) { + LLVMFreeMachineCodeForFunction(EE, F); + return Val_unit; +} + +extern value llvm_alloc_data_layout(LLVMTargetDataRef TargetData); + +/* ExecutionEngine.t -> Llvm_target.DataLayout.t */ +CAMLprim value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) { + value DataLayout; + LLVMTargetDataRef OrigDataLayout; + OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); + + char* TargetDataCStr; + TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); + DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); + LLVMDisposeMessage(TargetDataCStr); + + return DataLayout; +} diff --git a/bindings/ocaml/executionengine/llvm_executionengine.ml b/bindings/ocaml/executionengine/llvm_executionengine.ml new file mode 100644 index 00000000..a738df76 --- /dev/null +++ b/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -0,0 +1,111 @@ +(*===-- llvm_executionengine.ml - LLVM OCaml Interface ----------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +exception Error of string + +external register_exns: exn -> unit + = "llvm_register_ee_exns" + + +module GenericValue = struct + type t + + external of_float: Llvm.lltype -> float -> t + = "llvm_genericvalue_of_float" + external of_pointer: 'a -> t + = "llvm_genericvalue_of_pointer" + external of_int32: Llvm.lltype -> int32 -> t + = "llvm_genericvalue_of_int32" + external of_int: Llvm.lltype -> int -> t + = "llvm_genericvalue_of_int" + external of_nativeint: Llvm.lltype -> nativeint -> t + = "llvm_genericvalue_of_nativeint" + external of_int64: Llvm.lltype -> int64 -> t + = "llvm_genericvalue_of_int64" + + external as_float: Llvm.lltype -> t -> float + = "llvm_genericvalue_as_float" + external as_pointer: t -> 'a + = "llvm_genericvalue_as_pointer" + external as_int32: t -> int32 + = "llvm_genericvalue_as_int32" + external as_int: t -> int + = "llvm_genericvalue_as_int" + external as_nativeint: t -> nativeint + = "llvm_genericvalue_as_nativeint" + external as_int64: t -> int64 + = "llvm_genericvalue_as_int64" +end + + +module ExecutionEngine = struct + type t + + (* FIXME: Ocaml is not running this setup code unless we use 'val' in the + interface, which causes the emission of a stub for each function; + using 'external' in the module allows direct calls into + ocaml_executionengine.c. This is hardly fatal, but it is unnecessary + overhead on top of the two stubs that are already invoked for each + call into LLVM. *) + let _ = register_exns (Error "") + + external create: Llvm.llmodule -> t + = "llvm_ee_create" + external create_interpreter: Llvm.llmodule -> t + = "llvm_ee_create_interpreter" + external create_jit: Llvm.llmodule -> int -> t + = "llvm_ee_create_jit" + external dispose: t -> unit + = "llvm_ee_dispose" + external add_module: Llvm.llmodule -> t -> unit + = "llvm_ee_add_module" + external remove_module: Llvm.llmodule -> t -> Llvm.llmodule + = "llvm_ee_remove_module" + external find_function: string -> t -> Llvm.llvalue option + = "llvm_ee_find_function" + external run_function: Llvm.llvalue -> GenericValue.t array -> t -> + GenericValue.t + = "llvm_ee_run_function" + external run_static_ctors: t -> unit + = "llvm_ee_run_static_ctors" + external run_static_dtors: t -> unit + = "llvm_ee_run_static_dtors" + external run_function_as_main: Llvm.llvalue -> string array -> + (string * string) array -> t -> int + = "llvm_ee_run_function_as_main" + external free_machine_code: Llvm.llvalue -> t -> unit + = "llvm_ee_free_machine_code" + + external data_layout : t -> Llvm_target.DataLayout.t + = "llvm_ee_get_data_layout" + + (* The following are not bound. Patches are welcome. + + add_global_mapping: llvalue -> llgenericvalue -> t -> unit + clear_all_global_mappings: t -> unit + update_global_mapping: llvalue -> llgenericvalue -> t -> unit + get_pointer_to_global_if_available: llvalue -> t -> llgenericvalue + get_pointer_to_global: llvalue -> t -> llgenericvalue + get_pointer_to_function: llvalue -> t -> llgenericvalue + get_pointer_to_function_or_stub: llvalue -> t -> llgenericvalue + get_global_value_at_address: llgenericvalue -> t -> llvalue option + store_value_to_memory: llgenericvalue -> llgenericvalue -> lltype -> unit + initialize_memory: llvalue -> llgenericvalue -> t -> unit + recompile_and_relink_function: llvalue -> t -> llgenericvalue + get_or_emit_global_variable: llvalue -> t -> llgenericvalue + disable_lazy_compilation: t -> unit + lazy_compilation_enabled: t -> bool + install_lazy_function_creator: (string -> llgenericvalue) -> t -> unit + + *) +end + +external initialize_native_target : unit -> bool + = "llvm_initialize_native_target" diff --git a/bindings/ocaml/executionengine/llvm_executionengine.mli b/bindings/ocaml/executionengine/llvm_executionengine.mli new file mode 100644 index 00000000..16f08930 --- /dev/null +++ b/bindings/ocaml/executionengine/llvm_executionengine.mli @@ -0,0 +1,154 @@ +(*===-- llvm_executionengine.mli - LLVM OCaml Interface ---------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** JIT Interpreter. + + This interface provides an OCaml API for LLVM execution engine (JIT/ + interpreter), the classes in the ExecutionEngine library. *) + +exception Error of string + +module GenericValue: sig + (** [GenericValue.t] is a boxed union type used to portably pass arguments to + and receive values from the execution engine. It supports only a limited + selection of types; for more complex argument types, it is necessary to + generate a stub function by hand or to pass parameters by reference. + See the struct [llvm::GenericValue]. *) + type t + + (** [of_float fpty n] boxes the float [n] in a float-valued generic value + according to the floating point type [fpty]. See the fields + [llvm::GenericValue::DoubleVal] and [llvm::GenericValue::FloatVal]. *) + val of_float : Llvm.lltype -> float -> t + + (** [of_pointer v] boxes the pointer value [v] in a generic value. See the + field [llvm::GenericValue::PointerVal]. *) + val of_pointer : 'a -> t + + (** [of_int32 n w] boxes the int32 [i] in a generic value with the bitwidth + [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_int32 : Llvm.lltype -> int32 -> t + + (** [of_int n w] boxes the int [i] in a generic value with the bitwidth + [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_int : Llvm.lltype -> int -> t + + (** [of_natint n w] boxes the native int [i] in a generic value with the + bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_nativeint : Llvm.lltype -> nativeint -> t + + (** [of_int64 n w] boxes the int64 [i] in a generic value with the bitwidth + [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_int64 : Llvm.lltype -> int64 -> t + + (** [as_float fpty gv] unboxes the floating point-valued generic value [gv] of + floating point type [fpty]. See the fields [llvm::GenericValue::DoubleVal] + and [llvm::GenericValue::FloatVal]. *) + val as_float : Llvm.lltype -> t -> float + + (** [as_pointer gv] unboxes the pointer-valued generic value [gv]. See the + field [llvm::GenericValue::PointerVal]. *) + val as_pointer : t -> 'a + + (** [as_int32 gv] unboxes the integer-valued generic value [gv] as an [int32]. + Is invalid if [gv] has a bitwidth greater than 32 bits. See the field + [llvm::GenericValue::IntVal]. *) + val as_int32 : t -> int32 + + (** [as_int gv] unboxes the integer-valued generic value [gv] as an [int]. + Is invalid if [gv] has a bitwidth greater than the host bit width (but the + most significant bit may be lost). See the field + [llvm::GenericValue::IntVal]. *) + val as_int : t -> int + + (** [as_natint gv] unboxes the integer-valued generic value [gv] as a + [nativeint]. Is invalid if [gv] has a bitwidth greater than + [nativeint]. See the field [llvm::GenericValue::IntVal]. *) + val as_nativeint : t -> nativeint + + (** [as_int64 gv] returns the integer-valued generic value [gv] as an [int64]. + Is invalid if [gv] has a bitwidth greater than [int64]. See the field + [llvm::GenericValue::IntVal]. *) + val as_int64 : t -> int64 +end + + +module ExecutionEngine: sig + (** An execution engine is either a JIT compiler or an interpreter, capable of + directly loading an LLVM module and executing its functions without first + invoking a static compiler and generating a native executable. *) + type t + + (** [create m] creates a new execution engine, taking ownership of the + module [m] if successful. Creates a JIT if possible, else falls back to an + interpreter. Raises [Error msg] if an error occurrs. The execution engine + is not garbage collected and must be destroyed with [dispose ee]. + See the function [llvm::EngineBuilder::create]. *) + val create : Llvm.llmodule -> t + + (** [create_interpreter m] creates a new interpreter, taking ownership of the + module [m] if successful. Raises [Error msg] if an error occurrs. The + execution engine is not garbage collected and must be destroyed with + [dispose ee]. + See the function [llvm::EngineBuilder::create]. *) + val create_interpreter : Llvm.llmodule -> t + + (** [create_jit m optlevel] creates a new JIT (just-in-time compiler), taking + ownership of the module [m] if successful with the desired optimization + level [optlevel]. Raises [Error msg] if an error occurrs. The execution + engine is not garbage collected and must be destroyed with [dispose ee]. + See the function [llvm::EngineBuilder::create]. *) + val create_jit : Llvm.llmodule -> int -> t + + (** [dispose ee] releases the memory used by the execution engine and must be + invoked to avoid memory leaks. *) + val dispose : t -> unit + + (** [add_module m ee] adds the module [m] to the execution engine [ee]. *) + val add_module : Llvm.llmodule -> t -> unit + + (** [remove_module m ee] removes the module [m] from the execution engine + [ee], disposing of [m] and the module referenced by [mp]. Raises + [Error msg] if an error occurs. *) + val remove_module : Llvm.llmodule -> t -> Llvm.llmodule + + (** [find_function n ee] finds the function named [n] defined in any of the + modules owned by the execution engine [ee]. Returns [None] if the function + is not found and [Some f] otherwise. *) + val find_function : string -> t -> Llvm.llvalue option + + (** [run_function f args ee] synchronously executes the function [f] with the + arguments [args], which must be compatible with the parameter types. *) + val run_function : Llvm.llvalue -> GenericValue.t array -> t -> + GenericValue.t + + (** [run_static_ctors ee] executes the static constructors of each module in + the execution engine [ee]. *) + val run_static_ctors : t -> unit + + (** [run_static_dtors ee] executes the static destructors of each module in + the execution engine [ee]. *) + val run_static_dtors : t -> unit + + (** [run_function_as_main f args env ee] executes the function [f] as a main + function, passing it [argv] and [argc] according to the string array + [args], and [envp] as specified by the array [env]. Returns the integer + return value of the function. *) + val run_function_as_main : Llvm.llvalue -> string array -> + (string * string) array -> t -> int + + (** [free_machine_code f ee] releases the memory in the execution engine [ee] + used to store the machine code for the function [f]. *) + val free_machine_code : Llvm.llvalue -> t -> unit + + (** [data_layout ee] is the data layout of the execution engine [ee]. *) + val data_layout : t -> Llvm_target.DataLayout.t +end + +val initialize_native_target : unit -> bool diff --git a/bindings/ocaml/irreader/Makefile b/bindings/ocaml/irreader/Makefile new file mode 100644 index 00000000..7665999b --- /dev/null +++ b/bindings/ocaml/irreader/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/irreader/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_irreader interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_irreader +UsedComponents := irreader +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/irreader/irreader_ocaml.c b/bindings/ocaml/irreader/irreader_ocaml.c new file mode 100644 index 00000000..30c10c7b --- /dev/null +++ b/bindings/ocaml/irreader/irreader_ocaml.c @@ -0,0 +1,59 @@ +/*===-- irreader_ocaml.c - LLVM OCaml Glue ----------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/IRReader.h" +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" + +/* Can't use the recommended caml_named_value mechanism for backwards + compatibility reasons. This is largely equivalent. */ +static value llvm_irreader_error_exn; + +CAMLprim value llvm_register_irreader_exns(value Error) { + llvm_irreader_error_exn = Field(Error, 0); + register_global_root(&llvm_irreader_error_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + + +/*===-- Modules -----------------------------------------------------------===*/ + +/* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ +CAMLprim value llvm_parse_ir(LLVMContextRef C, + LLVMMemoryBufferRef MemBuf) { + CAMLparam0(); + CAMLlocal2(Variant, MessageVal); + LLVMModuleRef M; + char *Message; + + if (LLVMParseIRInContext(C, MemBuf, &M, &Message)) + llvm_raise(llvm_irreader_error_exn, Message); + + CAMLreturn((value) M); +} diff --git a/bindings/ocaml/irreader/llvm_irreader.ml b/bindings/ocaml/irreader/llvm_irreader.ml new file mode 100644 index 00000000..455b1fae --- /dev/null +++ b/bindings/ocaml/irreader/llvm_irreader.ml @@ -0,0 +1,17 @@ +(*===-- llvm_irreader.ml - LLVM OCaml Interface ---------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_irreader_exns" +let _ = register_exns (Error "") + +external parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_parse_ir" diff --git a/bindings/ocaml/irreader/llvm_irreader.mli b/bindings/ocaml/irreader/llvm_irreader.mli new file mode 100644 index 00000000..2b114737 --- /dev/null +++ b/bindings/ocaml/irreader/llvm_irreader.mli @@ -0,0 +1,21 @@ +(*===-- llvm_irreader.mli - LLVM OCaml Interface --------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** IR reader. + + This interface provides an OCaml API for the LLVM assembly reader, the + classes in the IRReader library. *) + +exception Error of string + +(** [parse_ir context mb] parses the IR for a new module [m] from the + memory buffer [mb] in the context [context]. Returns [m] if successful, or + raises [Error msg] otherwise, where [msg] is a description of the error + encountered. See the function [llvm::ParseIR]. *) +val parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule diff --git a/bindings/ocaml/linker/Makefile b/bindings/ocaml/linker/Makefile new file mode 100644 index 00000000..ca1c96c9 --- /dev/null +++ b/bindings/ocaml/linker/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/linker/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_target interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_linker +UsedComponents := linker +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/linker/linker_ocaml.c b/bindings/ocaml/linker/linker_ocaml.c new file mode 100644 index 00000000..2491e3b8 --- /dev/null +++ b/bindings/ocaml/linker/linker_ocaml.c @@ -0,0 +1,54 @@ +/*===-- linker_ocaml.c - LLVM Ocaml Glue ------------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Linker.h" +#include "caml/alloc.h" +#include "caml/memory.h" +#include "caml/fail.h" + +static value llvm_linker_error_exn; + +CAMLprim value llvm_register_linker_exns(value Error) { + llvm_linker_error_exn = Field(Error, 0); + register_global_root(&llvm_linker_error_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + +/* llmodule -> llmodule -> Mode.t -> unit + raises Error msg on error */ +CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src, value Mode) { + char* Message; + + if (LLVMLinkModules(Dst, Src, Int_val(Mode), &Message)) + llvm_raise(llvm_linker_error_exn, Message); + + return Val_unit; +} diff --git a/bindings/ocaml/linker/llvm_linker.ml b/bindings/ocaml/linker/llvm_linker.ml new file mode 100644 index 00000000..2b73e2e9 --- /dev/null +++ b/bindings/ocaml/linker/llvm_linker.ml @@ -0,0 +1,22 @@ +(*===-- llvm_linker.ml - LLVM OCaml Interface ------------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_linker_exns" +let _ = register_exns (Error "") + +module Mode = struct + type t = + | DestroySource + | PreserveSource +end + +external link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit + = "llvm_link_modules" \ No newline at end of file diff --git a/bindings/ocaml/linker/llvm_linker.mli b/bindings/ocaml/linker/llvm_linker.mli new file mode 100644 index 00000000..4def7a8c --- /dev/null +++ b/bindings/ocaml/linker/llvm_linker.mli @@ -0,0 +1,26 @@ +(*===-- llvm_linker.mli - LLVM OCaml Interface -----------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Linker. + + This interface provides an OCaml API for LLVM bitcode linker, + the classes in the Linker library. *) + +exception Error of string + +(** Linking mode. *) +module Mode : sig + type t = + | DestroySource + | PreserveSource +end + +(** [link_modules dst src mode] links [src] into [dst], raising [Error] + if the linking fails. *) +val link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit \ No newline at end of file diff --git a/bindings/ocaml/llvm/META.llvm.in b/bindings/ocaml/llvm/META.llvm.in new file mode 100644 index 00000000..c241ea51 --- /dev/null +++ b/bindings/ocaml/llvm/META.llvm.in @@ -0,0 +1,95 @@ +name = "llvm" +version = "@PACKAGE_VERSION@" +description = "LLVM OCaml bindings" +archive(byte) = "llvm.cma" +archive(native) = "llvm.cmxa" +directory = "." +linkopts = "-ccopt -lstdc++" + +package "analysis" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Intermediate representation analysis for LLVM" + archive(byte) = "llvm_analysis.cma" + archive(native) = "llvm_analysis.cmxa" +) + +package "bitreader" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Bitcode reader for LLVM" + archive(byte) = "llvm_bitreader.cma" + archive(native) = "llvm_bitreader.cmxa" +) + +package "bitwriter" ( + requires = "llvm,unix" + version = "@PACKAGE_VERSION@" + description = "Bitcode writer for LLVM" + archive(byte) = "llvm_bitwriter.cma" + archive(native) = "llvm_bitwriter.cmxa" +) + +package "executionengine" ( + requires = "llvm,llvm.target" + version = "@PACKAGE_VERSION@" + description = "JIT and Interpreter for LLVM" + archive(byte) = "llvm_executionengine.cma" + archive(native) = "llvm_executionengine.cmxa" +) + +package "ipo" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "IPO Transforms for LLVM" + archive(byte) = "llvm_ipo.cma" + archive(native) = "llvm_ipo.cmxa" +) + +package "irreader" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "IR assembly reader for LLVM" + archive(byte) = "llvm_irreader.cma" + archive(native) = "llvm_irreader.cmxa" +) + +package "scalar_opts" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Scalar Transforms for LLVM" + archive(byte) = "llvm_scalar_opts.cma" + archive(native) = "llvm_scalar_opts.cmxa" +) + +package "vectorize" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Vector Transforms for LLVM" + archive(byte) = "llvm_vectorize.cma" + archive(native) = "llvm_vectorize.cmxa" +) + +package "passmgr_builder" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Pass Manager Builder for LLVM" + archive(byte) = "llvm_passmgr_builder.cma" + archive(native) = "llvm_passmgr_builder.cmxa" +) + +package "target" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Target Information for LLVM" + archive(byte) = "llvm_target.cma" + archive(native) = "llvm_target.cmxa" +) + +package "linker" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Intermediate Representation Linker for LLVM" + archive(byte) = "llvm_linker.cma" + archive(native) = "llvm_linker.cmxa" +) diff --git a/bindings/ocaml/llvm/Makefile b/bindings/ocaml/llvm/Makefile new file mode 100644 index 00000000..850f564a --- /dev/null +++ b/bindings/ocaml/llvm/Makefile @@ -0,0 +1,42 @@ +##===- bindings/ocaml/llvm/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm +UsedComponents := core +UsedOcamlLibs := llvm + +include ../Makefile.ocaml + +all-local:: copy-meta +install-local:: install-meta +uninstall-local:: uninstall-meta + +DestMETA := $(PROJ_libocamldir)/META.llvm + +# Easy way of generating META in the objdir +copy-meta: $(OcamlDir)/META.llvm + +$(OcamlDir)/META.llvm: META.llvm + $(Verb) $(CP) -f $< $@ + +install-meta:: $(OcamlDir)/META.llvm + $(Echo) "Install $(BuildMode) $(DestMETA)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(DataInstall) $< "$(DestMETA)" + +uninstall-meta:: + $(Echo) "Uninstalling $(DestMETA)" + -$(Verb) $(RM) -f "$(DestMETA)" + +.PHONY: copy-meta install-meta uninstall-meta diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml new file mode 100644 index 00000000..d36f360b --- /dev/null +++ b/bindings/ocaml/llvm/llvm.ml @@ -0,0 +1,1279 @@ +(*===-- llvm/llvm.ml - LLVM Ocaml Interface --------------------------------===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +type llcontext +type llmodule +type lltype +type llvalue +type lluse +type llbasicblock +type llbuilder +type llmemorybuffer + +module TypeKind = struct + type t = + | Void + | Half + | Float + | Double + | X86fp80 + | Fp128 + | Ppc_fp128 + | Label + | Integer + | Function + | Struct + | Array + | Pointer + | Vector + | Metadata + | X86_mmx +end + +module Linkage = struct + type t = + | External + | Available_externally + | Link_once + | Link_once_odr + | Link_once_odr_auto_hide + | Weak + | Weak_odr + | Appending + | Internal + | Private + | Dllimport + | Dllexport + | External_weak + | Ghost + | Common + | Linker_private + | Linker_private_weak +end + +module Visibility = struct + type t = + | Default + | Hidden + | Protected +end + +module CallConv = struct + let c = 0 + let fast = 8 + let cold = 9 + let x86_stdcall = 64 + let x86_fastcall = 65 +end + +module Attribute = struct + type t = + | Zext + | Sext + | Noreturn + | Inreg + | Structret + | Nounwind + | Noalias + | Byval + | Nest + | Readnone + | Readonly + | Noinline + | Alwaysinline + | Optsize + | Ssp + | Sspreq + | Alignment of int + | Nocapture + | Noredzone + | Noimplicitfloat + | Naked + | Inlinehint + | Stackalignment of int + | ReturnsTwice + | UWTable + | NonLazyBind +end + +module Icmp = struct + type t = + | Eq + | Ne + | Ugt + | Uge + | Ult + | Ule + | Sgt + | Sge + | Slt + | Sle +end + +module Fcmp = struct + type t = + | False + | Oeq + | Ogt + | Oge + | Olt + | Ole + | One + | Ord + | Uno + | Ueq + | Ugt + | Uge + | Ult + | Ule + | Une + | True +end + +module Opcode = struct + type t = + | Invalid (* not an instruction *) + (* Terminator Instructions *) + | Ret + | Br + | Switch + | IndirectBr + | Invoke + | Invalid2 + | Unreachable + (* Standard Binary Operators *) + | Add + | FAdd + | Sub + | FSub + | Mul + | FMul + | UDiv + | SDiv + | FDiv + | URem + | SRem + | FRem + (* Logical Operators *) + | Shl + | LShr + | AShr + | And + | Or + | Xor + (* Memory Operators *) + | Alloca + | Load + | Store + | GetElementPtr + (* Cast Operators *) + | Trunc + | ZExt + | SExt + | FPToUI + | FPToSI + | UIToFP + | SIToFP + | FPTrunc + | FPExt + | PtrToInt + | IntToPtr + | BitCast + (* Other Operators *) + | ICmp + | FCmp + | PHI + | Call + | Select + | UserOp1 + | UserOp2 + | VAArg + | ExtractElement + | InsertElement + | ShuffleVector + | ExtractValue + | InsertValue + | Fence + | AtomicCmpXchg + | AtomicRMW + | Resume + | LandingPad +end + +module LandingPadClauseTy = struct + type t = + | Catch + | Filter +end + +module ThreadLocalMode = struct + type t = + | None + | GeneralDynamic + | LocalDynamic + | InitialExec + | LocalExec +end + +module AtomicOrdering = struct + type t = + | NotAtomic + | Unordered + | Monotonic + | Invalid + | Acquire + | Release + | AcqiureRelease + | SequentiallyConsistent +end + +module AtomicRMWBinOp = struct + type t = + | Xchg + | Add + | Sub + | And + | Nand + | Or + | Xor + | Max + | Min + | UMax + | UMin +end + +module ValueKind = struct + type t = + | NullValue + | Argument + | BasicBlock + | InlineAsm + | MDNode + | MDString + | BlockAddress + | ConstantAggregateZero + | ConstantArray + | ConstantDataArray + | ConstantDataVector + | ConstantExpr + | ConstantFP + | ConstantInt + | ConstantPointerNull + | ConstantStruct + | ConstantVector + | Function + | GlobalAlias + | GlobalVariable + | UndefValue + | Instruction of Opcode.t +end + +exception IoError of string + +external register_exns : exn -> unit = "llvm_register_core_exns" +let _ = register_exns (IoError "") + +external install_fatal_error_handler : (string -> unit) -> unit + = "llvm_install_fatal_error_handler" +external reset_fatal_error_handler : unit -> unit + = "llvm_reset_fatal_error_handler" +external enable_pretty_stacktrace : unit -> unit + = "llvm_enable_pretty_stacktrace" + +type ('a, 'b) llpos = +| At_end of 'a +| Before of 'b + +type ('a, 'b) llrev_pos = +| At_start of 'a +| After of 'b + +(*===-- Contexts ----------------------------------------------------------===*) +external create_context : unit -> llcontext = "llvm_create_context" +external dispose_context : llcontext -> unit = "llvm_dispose_context" +external global_context : unit -> llcontext = "llvm_global_context" +external mdkind_id : llcontext -> string -> int = "llvm_mdkind_id" + +(*===-- Modules -----------------------------------------------------------===*) +external create_module : llcontext -> string -> llmodule = "llvm_create_module" +external dispose_module : llmodule -> unit = "llvm_dispose_module" +external target_triple: llmodule -> string + = "llvm_target_triple" +external set_target_triple: string -> llmodule -> unit + = "llvm_set_target_triple" +external data_layout: llmodule -> string + = "llvm_data_layout" +external set_data_layout: string -> llmodule -> unit + = "llvm_set_data_layout" +external dump_module : llmodule -> unit = "llvm_dump_module" +external print_module : string -> llmodule -> unit = "llvm_print_module" +external string_of_llmodule : llmodule -> string = "llvm_string_of_llmodule" +external set_module_inline_asm : llmodule -> string -> unit + = "llvm_set_module_inline_asm" +external module_context : llmodule -> llcontext = "LLVMGetModuleContext" + +(*===-- Types -------------------------------------------------------------===*) +external classify_type : lltype -> TypeKind.t = "llvm_classify_type" +external type_context : lltype -> llcontext = "llvm_type_context" +external type_is_sized : lltype -> bool = "llvm_type_is_sized" +external dump_type : lltype -> unit = "llvm_dump_type" +external string_of_lltype : lltype -> string = "llvm_string_of_lltype" + +(*--... Operations on integer types ........................................--*) +external i1_type : llcontext -> lltype = "llvm_i1_type" +external i8_type : llcontext -> lltype = "llvm_i8_type" +external i16_type : llcontext -> lltype = "llvm_i16_type" +external i32_type : llcontext -> lltype = "llvm_i32_type" +external i64_type : llcontext -> lltype = "llvm_i64_type" + +external integer_type : llcontext -> int -> lltype = "llvm_integer_type" +external integer_bitwidth : lltype -> int = "llvm_integer_bitwidth" + +(*--... Operations on real types ...........................................--*) +external float_type : llcontext -> lltype = "llvm_float_type" +external double_type : llcontext -> lltype = "llvm_double_type" +external x86fp80_type : llcontext -> lltype = "llvm_x86fp80_type" +external fp128_type : llcontext -> lltype = "llvm_fp128_type" +external ppc_fp128_type : llcontext -> lltype = "llvm_ppc_fp128_type" + +(*--... Operations on function types .......................................--*) +external function_type : lltype -> lltype array -> lltype = "llvm_function_type" +external var_arg_function_type : lltype -> lltype array -> lltype + = "llvm_var_arg_function_type" +external is_var_arg : lltype -> bool = "llvm_is_var_arg" +external return_type : lltype -> lltype = "LLVMGetReturnType" +external param_types : lltype -> lltype array = "llvm_param_types" + +(*--... Operations on struct types .........................................--*) +external struct_type : llcontext -> lltype array -> lltype = "llvm_struct_type" +external packed_struct_type : llcontext -> lltype array -> lltype + = "llvm_packed_struct_type" +external struct_name : lltype -> string option = "llvm_struct_name" +external named_struct_type : llcontext -> string -> lltype = + "llvm_named_struct_type" +external struct_set_body : lltype -> lltype array -> bool -> unit = + "llvm_struct_set_body" +external struct_element_types : lltype -> lltype array + = "llvm_struct_element_types" +external is_packed : lltype -> bool = "llvm_is_packed" +external is_opaque : lltype -> bool = "llvm_is_opaque" + +(*--... Operations on pointer, vector, and array types .....................--*) +external array_type : lltype -> int -> lltype = "llvm_array_type" +external pointer_type : lltype -> lltype = "llvm_pointer_type" +external qualified_pointer_type : lltype -> int -> lltype + = "llvm_qualified_pointer_type" +external vector_type : lltype -> int -> lltype = "llvm_vector_type" + +external element_type : lltype -> lltype = "LLVMGetElementType" +external array_length : lltype -> int = "llvm_array_length" +external address_space : lltype -> int = "llvm_address_space" +external vector_size : lltype -> int = "llvm_vector_size" + +(*--... Operations on other types ..........................................--*) +external void_type : llcontext -> lltype = "llvm_void_type" +external label_type : llcontext -> lltype = "llvm_label_type" +external x86_mmx_type : llcontext -> lltype = "llvm_x86_mmx_type" +external type_by_name : llmodule -> string -> lltype option = "llvm_type_by_name" + +external classify_value : llvalue -> ValueKind.t = "llvm_classify_value" +(*===-- Values ------------------------------------------------------------===*) +external type_of : llvalue -> lltype = "llvm_type_of" +external value_name : llvalue -> string = "llvm_value_name" +external set_value_name : string -> llvalue -> unit = "llvm_set_value_name" +external dump_value : llvalue -> unit = "llvm_dump_value" +external string_of_llvalue : llvalue -> string = "llvm_string_of_llvalue" +external replace_all_uses_with : llvalue -> llvalue -> unit + = "llvm_replace_all_uses_with" + +(*--... Operations on uses .................................................--*) +external use_begin : llvalue -> lluse option = "llvm_use_begin" +external use_succ : lluse -> lluse option = "llvm_use_succ" +external user : lluse -> llvalue = "llvm_user" +external used_value : lluse -> llvalue = "llvm_used_value" + +let iter_uses f v = + let rec aux = function + | None -> () + | Some u -> + f u; + aux (use_succ u) + in + aux (use_begin v) + +let fold_left_uses f init v = + let rec aux init u = + match u with + | None -> init + | Some u -> aux (f init u) (use_succ u) + in + aux init (use_begin v) + +let fold_right_uses f v init = + let rec aux u init = + match u with + | None -> init + | Some u -> f u (aux (use_succ u) init) + in + aux (use_begin v) init + + +(*--... Operations on users ................................................--*) +external operand : llvalue -> int -> llvalue = "llvm_operand" +external set_operand : llvalue -> int -> llvalue -> unit = "llvm_set_operand" +external num_operands : llvalue -> int = "llvm_num_operands" + +(*--... Operations on constants of (mostly) any type .......................--*) +external is_constant : llvalue -> bool = "llvm_is_constant" +external const_null : lltype -> llvalue = "LLVMConstNull" +external const_all_ones : (*int|vec*)lltype -> llvalue = "LLVMConstAllOnes" +external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull" +external undef : lltype -> llvalue = "LLVMGetUndef" +external is_null : llvalue -> bool = "llvm_is_null" +external is_undef : llvalue -> bool = "llvm_is_undef" +external constexpr_opcode : llvalue -> Opcode.t = "llvm_constexpr_get_opcode" + +(*--... Operations on instructions .........................................--*) +external has_metadata : llvalue -> bool = "llvm_has_metadata" +external metadata : llvalue -> int -> llvalue option = "llvm_metadata" +external set_metadata : llvalue -> int -> llvalue -> unit = "llvm_set_metadata" +external clear_metadata : llvalue -> int -> unit = "llvm_clear_metadata" + +(*--... Operations on metadata .......,.....................................--*) +external mdstring : llcontext -> string -> llvalue = "llvm_mdstring" +external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode" +external get_mdstring : llvalue -> string option = "llvm_get_mdstring" +external get_named_metadata : llmodule -> string -> llvalue array + = "llvm_get_namedmd" +external add_named_metadata_operand : llmodule -> string -> llvalue -> unit + = "llvm_append_namedmd" + +(*--... Operations on scalar constants .....................................--*) +external const_int : lltype -> int -> llvalue = "llvm_const_int" +external const_of_int64 : lltype -> Int64.t -> bool -> llvalue + = "llvm_const_of_int64" +external int64_of_const : llvalue -> Int64.t option + = "llvm_int64_of_const" +external const_int_of_string : lltype -> string -> int -> llvalue + = "llvm_const_int_of_string" +external const_float : lltype -> float -> llvalue = "llvm_const_float" +external const_float_of_string : lltype -> string -> llvalue + = "llvm_const_float_of_string" + +(*--... Operations on composite constants ..................................--*) +external const_string : llcontext -> string -> llvalue = "llvm_const_string" +external const_stringz : llcontext -> string -> llvalue = "llvm_const_stringz" +external const_array : lltype -> llvalue array -> llvalue = "llvm_const_array" +external const_struct : llcontext -> llvalue array -> llvalue + = "llvm_const_struct" +external const_named_struct : lltype -> llvalue array -> llvalue + = "llvm_const_named_struct" +external const_packed_struct : llcontext -> llvalue array -> llvalue + = "llvm_const_packed_struct" +external const_vector : llvalue array -> llvalue = "llvm_const_vector" + +(*--... Constant expressions ...............................................--*) +external align_of : lltype -> llvalue = "LLVMAlignOf" +external size_of : lltype -> llvalue = "LLVMSizeOf" +external const_neg : llvalue -> llvalue = "LLVMConstNeg" +external const_nsw_neg : llvalue -> llvalue = "LLVMConstNSWNeg" +external const_nuw_neg : llvalue -> llvalue = "LLVMConstNUWNeg" +external const_fneg : llvalue -> llvalue = "LLVMConstFNeg" +external const_not : llvalue -> llvalue = "LLVMConstNot" +external const_add : llvalue -> llvalue -> llvalue = "LLVMConstAdd" +external const_nsw_add : llvalue -> llvalue -> llvalue = "LLVMConstNSWAdd" +external const_nuw_add : llvalue -> llvalue -> llvalue = "LLVMConstNUWAdd" +external const_fadd : llvalue -> llvalue -> llvalue = "LLVMConstFAdd" +external const_sub : llvalue -> llvalue -> llvalue = "LLVMConstSub" +external const_nsw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNSWSub" +external const_nuw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNUWSub" +external const_fsub : llvalue -> llvalue -> llvalue = "LLVMConstFSub" +external const_mul : llvalue -> llvalue -> llvalue = "LLVMConstMul" +external const_nsw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNSWMul" +external const_nuw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNUWMul" +external const_fmul : llvalue -> llvalue -> llvalue = "LLVMConstFMul" +external const_udiv : llvalue -> llvalue -> llvalue = "LLVMConstUDiv" +external const_sdiv : llvalue -> llvalue -> llvalue = "LLVMConstSDiv" +external const_exact_sdiv : llvalue -> llvalue -> llvalue = "LLVMConstExactSDiv" +external const_fdiv : llvalue -> llvalue -> llvalue = "LLVMConstFDiv" +external const_urem : llvalue -> llvalue -> llvalue = "LLVMConstURem" +external const_srem : llvalue -> llvalue -> llvalue = "LLVMConstSRem" +external const_frem : llvalue -> llvalue -> llvalue = "LLVMConstFRem" +external const_and : llvalue -> llvalue -> llvalue = "LLVMConstAnd" +external const_or : llvalue -> llvalue -> llvalue = "LLVMConstOr" +external const_xor : llvalue -> llvalue -> llvalue = "LLVMConstXor" +external const_icmp : Icmp.t -> llvalue -> llvalue -> llvalue + = "llvm_const_icmp" +external const_fcmp : Fcmp.t -> llvalue -> llvalue -> llvalue + = "llvm_const_fcmp" +external const_shl : llvalue -> llvalue -> llvalue = "LLVMConstShl" +external const_lshr : llvalue -> llvalue -> llvalue = "LLVMConstLShr" +external const_ashr : llvalue -> llvalue -> llvalue = "LLVMConstAShr" +external const_gep : llvalue -> llvalue array -> llvalue = "llvm_const_gep" +external const_in_bounds_gep : llvalue -> llvalue array -> llvalue + = "llvm_const_in_bounds_gep" +external const_trunc : llvalue -> lltype -> llvalue = "LLVMConstTrunc" +external const_sext : llvalue -> lltype -> llvalue = "LLVMConstSExt" +external const_zext : llvalue -> lltype -> llvalue = "LLVMConstZExt" +external const_fptrunc : llvalue -> lltype -> llvalue = "LLVMConstFPTrunc" +external const_fpext : llvalue -> lltype -> llvalue = "LLVMConstFPExt" +external const_uitofp : llvalue -> lltype -> llvalue = "LLVMConstUIToFP" +external const_sitofp : llvalue -> lltype -> llvalue = "LLVMConstSIToFP" +external const_fptoui : llvalue -> lltype -> llvalue = "LLVMConstFPToUI" +external const_fptosi : llvalue -> lltype -> llvalue = "LLVMConstFPToSI" +external const_ptrtoint : llvalue -> lltype -> llvalue = "LLVMConstPtrToInt" +external const_inttoptr : llvalue -> lltype -> llvalue = "LLVMConstIntToPtr" +external const_bitcast : llvalue -> lltype -> llvalue = "LLVMConstBitCast" +external const_zext_or_bitcast : llvalue -> lltype -> llvalue + = "LLVMConstZExtOrBitCast" +external const_sext_or_bitcast : llvalue -> lltype -> llvalue + = "LLVMConstSExtOrBitCast" +external const_trunc_or_bitcast : llvalue -> lltype -> llvalue + = "LLVMConstTruncOrBitCast" +external const_pointercast : llvalue -> lltype -> llvalue + = "LLVMConstPointerCast" +external const_intcast : llvalue -> lltype -> is_signed:bool -> llvalue + = "llvm_const_intcast" +external const_fpcast : llvalue -> lltype -> llvalue = "LLVMConstFPCast" +external const_select : llvalue -> llvalue -> llvalue -> llvalue + = "LLVMConstSelect" +external const_extractelement : llvalue -> llvalue -> llvalue + = "LLVMConstExtractElement" +external const_insertelement : llvalue -> llvalue -> llvalue -> llvalue + = "LLVMConstInsertElement" +external const_shufflevector : llvalue -> llvalue -> llvalue -> llvalue + = "LLVMConstShuffleVector" +external const_extractvalue : llvalue -> int array -> llvalue + = "llvm_const_extractvalue" +external const_insertvalue : llvalue -> llvalue -> int array -> llvalue + = "llvm_const_insertvalue" +external const_inline_asm : lltype -> string -> string -> bool -> bool -> + llvalue + = "llvm_const_inline_asm" +external block_address : llvalue -> llbasicblock -> llvalue = "LLVMBlockAddress" + +(*--... Operations on global variables, functions, and aliases (globals) ...--*) +external global_parent : llvalue -> llmodule = "LLVMGetGlobalParent" +external is_declaration : llvalue -> bool = "llvm_is_declaration" +external linkage : llvalue -> Linkage.t = "llvm_linkage" +external set_linkage : Linkage.t -> llvalue -> unit = "llvm_set_linkage" +external section : llvalue -> string = "llvm_section" +external set_section : string -> llvalue -> unit = "llvm_set_section" +external visibility : llvalue -> Visibility.t = "llvm_visibility" +external set_visibility : Visibility.t -> llvalue -> unit = "llvm_set_visibility" +external alignment : llvalue -> int = "llvm_alignment" +external set_alignment : int -> llvalue -> unit = "llvm_set_alignment" +external is_global_constant : llvalue -> bool = "llvm_is_global_constant" +external set_global_constant : bool -> llvalue -> unit + = "llvm_set_global_constant" + +(*--... Operations on global variables .....................................--*) +external declare_global : lltype -> string -> llmodule -> llvalue + = "llvm_declare_global" +external declare_qualified_global : lltype -> string -> int -> llmodule -> + llvalue + = "llvm_declare_qualified_global" +external define_global : string -> llvalue -> llmodule -> llvalue + = "llvm_define_global" +external define_qualified_global : string -> llvalue -> int -> llmodule -> + llvalue + = "llvm_define_qualified_global" +external lookup_global : string -> llmodule -> llvalue option + = "llvm_lookup_global" +external delete_global : llvalue -> unit = "llvm_delete_global" +external global_initializer : llvalue -> llvalue = "LLVMGetInitializer" +external set_initializer : llvalue -> llvalue -> unit = "llvm_set_initializer" +external remove_initializer : llvalue -> unit = "llvm_remove_initializer" +external is_thread_local : llvalue -> bool = "llvm_is_thread_local" +external set_thread_local : bool -> llvalue -> unit = "llvm_set_thread_local" +external thread_local_mode : llvalue -> ThreadLocalMode.t + = "llvm_thread_local_mode" +external set_thread_local_mode : ThreadLocalMode.t -> llvalue -> unit + = "llvm_set_thread_local_mode" +external is_externally_initialized : llvalue -> bool + = "llvm_is_externally_initialized" +external set_externally_initialized : bool -> llvalue -> unit + = "llvm_set_externally_initialized" +external global_begin : llmodule -> (llmodule, llvalue) llpos + = "llvm_global_begin" +external global_succ : llvalue -> (llmodule, llvalue) llpos + = "llvm_global_succ" +external global_end : llmodule -> (llmodule, llvalue) llrev_pos + = "llvm_global_end" +external global_pred : llvalue -> (llmodule, llvalue) llrev_pos + = "llvm_global_pred" + +let rec iter_global_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid global variable range.") + | Before bb -> + f bb; + iter_global_range f (global_succ bb) e + +let iter_globals f m = + iter_global_range f (global_begin m) (At_end m) + +let rec fold_left_global_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid global variable range.") + | Before bb -> fold_left_global_range f (f init bb) (global_succ bb) e + +let fold_left_globals f init m = + fold_left_global_range f init (global_begin m) (At_end m) + +let rec rev_iter_global_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid global variable range.") + | After bb -> + f bb; + rev_iter_global_range f (global_pred bb) e + +let rev_iter_globals f m = + rev_iter_global_range f (global_end m) (At_start m) + +let rec fold_right_global_range f i e init = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid global variable range.") + | After bb -> fold_right_global_range f (global_pred bb) e (f bb init) + +let fold_right_globals f m init = + fold_right_global_range f (global_end m) (At_start m) init + +(*--... Operations on aliases ..............................................--*) +external add_alias : llmodule -> lltype -> llvalue -> string -> llvalue + = "llvm_add_alias" + +(*--... Operations on functions ............................................--*) +external declare_function : string -> lltype -> llmodule -> llvalue + = "llvm_declare_function" +external define_function : string -> lltype -> llmodule -> llvalue + = "llvm_define_function" +external lookup_function : string -> llmodule -> llvalue option + = "llvm_lookup_function" +external delete_function : llvalue -> unit = "llvm_delete_function" +external is_intrinsic : llvalue -> bool = "llvm_is_intrinsic" +external function_call_conv : llvalue -> int = "llvm_function_call_conv" +external set_function_call_conv : int -> llvalue -> unit + = "llvm_set_function_call_conv" +external gc : llvalue -> string option = "llvm_gc" +external set_gc : string option -> llvalue -> unit = "llvm_set_gc" +external function_begin : llmodule -> (llmodule, llvalue) llpos + = "llvm_function_begin" +external function_succ : llvalue -> (llmodule, llvalue) llpos + = "llvm_function_succ" +external function_end : llmodule -> (llmodule, llvalue) llrev_pos + = "llvm_function_end" +external function_pred : llvalue -> (llmodule, llvalue) llrev_pos + = "llvm_function_pred" + +let rec iter_function_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid function range.") + | Before fn -> + f fn; + iter_function_range f (function_succ fn) e + +let iter_functions f m = + iter_function_range f (function_begin m) (At_end m) + +let rec fold_left_function_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid function range.") + | Before fn -> fold_left_function_range f (f init fn) (function_succ fn) e + +let fold_left_functions f init m = + fold_left_function_range f init (function_begin m) (At_end m) + +let rec rev_iter_function_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid function range.") + | After fn -> + f fn; + rev_iter_function_range f (function_pred fn) e + +let rev_iter_functions f m = + rev_iter_function_range f (function_end m) (At_start m) + +let rec fold_right_function_range f i e init = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid function range.") + | After fn -> fold_right_function_range f (function_pred fn) e (f fn init) + +let fold_right_functions f m init = + fold_right_function_range f (function_end m) (At_start m) init + +external llvm_add_function_attr : llvalue -> int32 -> unit + = "llvm_add_function_attr" +external llvm_remove_function_attr : llvalue -> int32 -> unit + = "llvm_remove_function_attr" +external llvm_function_attr : llvalue -> int32 = "llvm_function_attr" + +let pack_attr (attr:Attribute.t) : int32 = + match attr with + Attribute.Zext -> Int32.shift_left 1l 0 + | Attribute.Sext -> Int32.shift_left 1l 1 + | Attribute.Noreturn -> Int32.shift_left 1l 2 + | Attribute.Inreg -> Int32.shift_left 1l 3 + | Attribute.Structret -> Int32.shift_left 1l 4 + | Attribute.Nounwind -> Int32.shift_left 1l 5 + | Attribute.Noalias -> Int32.shift_left 1l 6 + | Attribute.Byval -> Int32.shift_left 1l 7 + | Attribute.Nest -> Int32.shift_left 1l 8 + | Attribute.Readnone -> Int32.shift_left 1l 9 + | Attribute.Readonly -> Int32.shift_left 1l 10 + | Attribute.Noinline -> Int32.shift_left 1l 11 + | Attribute.Alwaysinline -> Int32.shift_left 1l 12 + | Attribute.Optsize -> Int32.shift_left 1l 13 + | Attribute.Ssp -> Int32.shift_left 1l 14 + | Attribute.Sspreq -> Int32.shift_left 1l 15 + | Attribute.Alignment n -> Int32.shift_left (Int32.of_int n) 16 + | Attribute.Nocapture -> Int32.shift_left 1l 21 + | Attribute.Noredzone -> Int32.shift_left 1l 22 + | Attribute.Noimplicitfloat -> Int32.shift_left 1l 23 + | Attribute.Naked -> Int32.shift_left 1l 24 + | Attribute.Inlinehint -> Int32.shift_left 1l 25 + | Attribute.Stackalignment n -> Int32.shift_left (Int32.of_int n) 26 + | Attribute.ReturnsTwice -> Int32.shift_left 1l 29 + | Attribute.UWTable -> Int32.shift_left 1l 30 + | Attribute.NonLazyBind -> Int32.shift_left 1l 31 + +let unpack_attr (a : int32) : Attribute.t list = + let l = ref [] in + let check attr = + Int32.logand (pack_attr attr) a in + let checkattr attr = + if (check attr) <> 0l then begin + l := attr :: !l + end + in + checkattr Attribute.Zext; + checkattr Attribute.Sext; + checkattr Attribute.Noreturn; + checkattr Attribute.Inreg; + checkattr Attribute.Structret; + checkattr Attribute.Nounwind; + checkattr Attribute.Noalias; + checkattr Attribute.Byval; + checkattr Attribute.Nest; + checkattr Attribute.Readnone; + checkattr Attribute.Readonly; + checkattr Attribute.Noinline; + checkattr Attribute.Alwaysinline; + checkattr Attribute.Optsize; + checkattr Attribute.Ssp; + checkattr Attribute.Sspreq; + let align = Int32.logand (Int32.shift_right_logical a 16) 31l in + if align <> 0l then + l := Attribute.Alignment (Int32.to_int align) :: !l; + checkattr Attribute.Nocapture; + checkattr Attribute.Noredzone; + checkattr Attribute.Noimplicitfloat; + checkattr Attribute.Naked; + checkattr Attribute.Inlinehint; + let stackalign = Int32.logand (Int32.shift_right_logical a 26) 7l in + if stackalign <> 0l then + l := Attribute.Stackalignment (Int32.to_int stackalign) :: !l; + checkattr Attribute.ReturnsTwice; + checkattr Attribute.UWTable; + checkattr Attribute.NonLazyBind; + !l;; + +let add_function_attr llval attr = + llvm_add_function_attr llval (pack_attr attr) + +external add_target_dependent_function_attr + : llvalue -> string -> string -> unit + = "llvm_add_target_dependent_function_attr" + +let remove_function_attr llval attr = + llvm_remove_function_attr llval (pack_attr attr) + +let function_attr f = unpack_attr (llvm_function_attr f) + +(*--... Operations on params ...............................................--*) +external params : llvalue -> llvalue array = "llvm_params" +external param : llvalue -> int -> llvalue = "llvm_param" +external llvm_param_attr : llvalue -> int32 = "llvm_param_attr" +let param_attr p = unpack_attr (llvm_param_attr p) +external param_parent : llvalue -> llvalue = "LLVMGetParamParent" +external param_begin : llvalue -> (llvalue, llvalue) llpos = "llvm_param_begin" +external param_succ : llvalue -> (llvalue, llvalue) llpos = "llvm_param_succ" +external param_end : llvalue -> (llvalue, llvalue) llrev_pos = "llvm_param_end" +external param_pred : llvalue -> (llvalue, llvalue) llrev_pos ="llvm_param_pred" + +let rec iter_param_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid parameter range.") + | Before p -> + f p; + iter_param_range f (param_succ p) e + +let iter_params f fn = + iter_param_range f (param_begin fn) (At_end fn) + +let rec fold_left_param_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid parameter range.") + | Before p -> fold_left_param_range f (f init p) (param_succ p) e + +let fold_left_params f init fn = + fold_left_param_range f init (param_begin fn) (At_end fn) + +let rec rev_iter_param_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid parameter range.") + | After p -> + f p; + rev_iter_param_range f (param_pred p) e + +let rev_iter_params f fn = + rev_iter_param_range f (param_end fn) (At_start fn) + +let rec fold_right_param_range f init i e = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid parameter range.") + | After p -> fold_right_param_range f (f p init) (param_pred p) e + +let fold_right_params f fn init = + fold_right_param_range f init (param_end fn) (At_start fn) + +external llvm_add_param_attr : llvalue -> int32 -> unit + = "llvm_add_param_attr" +external llvm_remove_param_attr : llvalue -> int32 -> unit + = "llvm_remove_param_attr" + +let add_param_attr llval attr = + llvm_add_param_attr llval (pack_attr attr) + +let remove_param_attr llval attr = + llvm_remove_param_attr llval (pack_attr attr) + +external set_param_alignment : llvalue -> int -> unit + = "llvm_set_param_alignment" + +(*--... Operations on basic blocks .........................................--*) +external value_of_block : llbasicblock -> llvalue = "LLVMBasicBlockAsValue" +external value_is_block : llvalue -> bool = "llvm_value_is_block" +external block_of_value : llvalue -> llbasicblock = "LLVMValueAsBasicBlock" +external block_parent : llbasicblock -> llvalue = "LLVMGetBasicBlockParent" +external basic_blocks : llvalue -> llbasicblock array = "llvm_basic_blocks" +external entry_block : llvalue -> llbasicblock = "LLVMGetEntryBasicBlock" +external delete_block : llbasicblock -> unit = "llvm_delete_block" +external remove_block : llbasicblock -> unit = "llvm_remove_block" +external move_block_before : llbasicblock -> llbasicblock -> unit + = "llvm_move_block_before" +external move_block_after : llbasicblock -> llbasicblock -> unit + = "llvm_move_block_after" +external append_block : llcontext -> string -> llvalue -> llbasicblock + = "llvm_append_block" +external insert_block : llcontext -> string -> llbasicblock -> llbasicblock + = "llvm_insert_block" +external block_begin : llvalue -> (llvalue, llbasicblock) llpos + = "llvm_block_begin" +external block_succ : llbasicblock -> (llvalue, llbasicblock) llpos + = "llvm_block_succ" +external block_end : llvalue -> (llvalue, llbasicblock) llrev_pos + = "llvm_block_end" +external block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos + = "llvm_block_pred" +external block_terminator : llbasicblock -> llvalue option = + "llvm_block_terminator" + +let rec iter_block_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid block range.") + | Before bb -> + f bb; + iter_block_range f (block_succ bb) e + +let iter_blocks f fn = + iter_block_range f (block_begin fn) (At_end fn) + +let rec fold_left_block_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid block range.") + | Before bb -> fold_left_block_range f (f init bb) (block_succ bb) e + +let fold_left_blocks f init fn = + fold_left_block_range f init (block_begin fn) (At_end fn) + +let rec rev_iter_block_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid block range.") + | After bb -> + f bb; + rev_iter_block_range f (block_pred bb) e + +let rev_iter_blocks f fn = + rev_iter_block_range f (block_end fn) (At_start fn) + +let rec fold_right_block_range f init i e = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid block range.") + | After bb -> fold_right_block_range f (f bb init) (block_pred bb) e + +let fold_right_blocks f fn init = + fold_right_block_range f init (block_end fn) (At_start fn) + +(*--... Operations on instructions .........................................--*) +external instr_parent : llvalue -> llbasicblock = "LLVMGetInstructionParent" +external instr_begin : llbasicblock -> (llbasicblock, llvalue) llpos + = "llvm_instr_begin" +external instr_succ : llvalue -> (llbasicblock, llvalue) llpos + = "llvm_instr_succ" +external instr_end : llbasicblock -> (llbasicblock, llvalue) llrev_pos + = "llvm_instr_end" +external instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos + = "llvm_instr_pred" + +external instr_opcode : llvalue -> Opcode.t = "llvm_instr_get_opcode" +external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate" + +let rec iter_instrs_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid instruction range.") + | Before i -> + f i; + iter_instrs_range f (instr_succ i) e + +let iter_instrs f bb = + iter_instrs_range f (instr_begin bb) (At_end bb) + +let rec fold_left_instrs_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid instruction range.") + | Before i -> fold_left_instrs_range f (f init i) (instr_succ i) e + +let fold_left_instrs f init bb = + fold_left_instrs_range f init (instr_begin bb) (At_end bb) + +let rec rev_iter_instrs_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid instruction range.") + | After i -> + f i; + rev_iter_instrs_range f (instr_pred i) e + +let rev_iter_instrs f bb = + rev_iter_instrs_range f (instr_end bb) (At_start bb) + +let rec fold_right_instr_range f i e init = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid instruction range.") + | After i -> fold_right_instr_range f (instr_pred i) e (f i init) + +let fold_right_instrs f bb init = + fold_right_instr_range f (instr_end bb) (At_start bb) init + + +(*--... Operations on call sites ...........................................--*) +external instruction_call_conv: llvalue -> int + = "llvm_instruction_call_conv" +external set_instruction_call_conv: int -> llvalue -> unit + = "llvm_set_instruction_call_conv" + +external llvm_add_instruction_param_attr : llvalue -> int -> int32 -> unit + = "llvm_add_instruction_param_attr" +external llvm_remove_instruction_param_attr : llvalue -> int -> int32 -> unit + = "llvm_remove_instruction_param_attr" + +let add_instruction_param_attr llval i attr = + llvm_add_instruction_param_attr llval i (pack_attr attr) + +let remove_instruction_param_attr llval i attr = + llvm_remove_instruction_param_attr llval i (pack_attr attr) + +(*--... Operations on call instructions (only) .............................--*) +external is_tail_call : llvalue -> bool = "llvm_is_tail_call" +external set_tail_call : bool -> llvalue -> unit = "llvm_set_tail_call" + +(*--... Operations on load/store instructions (only) .......................--*) +external is_volatile : llvalue -> bool = "llvm_is_volatile" +external set_volatile : bool -> llvalue -> unit = "llvm_set_volatile" + +(*--... Operations on phi nodes ............................................--*) +external add_incoming : (llvalue * llbasicblock) -> llvalue -> unit + = "llvm_add_incoming" +external incoming : llvalue -> (llvalue * llbasicblock) list = "llvm_incoming" + +external delete_instruction : llvalue -> unit = "llvm_delete_instruction" + +(*===-- Instruction builders ----------------------------------------------===*) +external builder : llcontext -> llbuilder = "llvm_builder" +external position_builder : (llbasicblock, llvalue) llpos -> llbuilder -> unit + = "llvm_position_builder" +external insertion_block : llbuilder -> llbasicblock = "llvm_insertion_block" +external insert_into_builder : llvalue -> string -> llbuilder -> unit + = "llvm_insert_into_builder" + +let builder_at context ip = + let b = builder context in + position_builder ip b; + b + +let builder_before context i = builder_at context (Before i) +let builder_at_end context bb = builder_at context (At_end bb) + +let position_before i = position_builder (Before i) +let position_at_end bb = position_builder (At_end bb) + + +(*--... Metadata ...........................................................--*) +external set_current_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_current_debug_location" +external clear_current_debug_location : llbuilder -> unit + = "llvm_clear_current_debug_location" +external current_debug_location : llbuilder -> llvalue option + = "llvm_current_debug_location" +external set_inst_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_inst_debug_location" + + +(*--... Terminators ........................................................--*) +external build_ret_void : llbuilder -> llvalue = "llvm_build_ret_void" +external build_ret : llvalue -> llbuilder -> llvalue = "llvm_build_ret" +external build_aggregate_ret : llvalue array -> llbuilder -> llvalue + = "llvm_build_aggregate_ret" +external build_br : llbasicblock -> llbuilder -> llvalue = "llvm_build_br" +external build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder -> + llvalue = "llvm_build_cond_br" +external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue + = "llvm_build_switch" +external build_malloc : lltype -> string -> llbuilder -> llvalue = + "llvm_build_malloc" +external build_array_malloc : lltype -> llvalue -> string -> llbuilder -> + llvalue = "llvm_build_array_malloc" +external build_free : llvalue -> llbuilder -> llvalue = "llvm_build_free" +external add_case : llvalue -> llvalue -> llbasicblock -> unit + = "llvm_add_case" +external switch_default_dest : llvalue -> llbasicblock = + "LLVMGetSwitchDefaultDest" +external build_indirect_br : llvalue -> int -> llbuilder -> llvalue + = "llvm_build_indirect_br" +external add_destination : llvalue -> llbasicblock -> unit + = "llvm_add_destination" +external build_invoke : llvalue -> llvalue array -> llbasicblock -> + llbasicblock -> string -> llbuilder -> llvalue + = "llvm_build_invoke_bc" "llvm_build_invoke_nat" +external build_landingpad : lltype -> llvalue -> int -> string -> llbuilder -> + llvalue = "llvm_build_landingpad" +external set_cleanup : llvalue -> bool -> unit = "llvm_set_cleanup" +external add_clause : llvalue -> llvalue -> unit = "llvm_add_clause" +external build_resume : llvalue -> llbuilder -> llvalue = "llvm_build_resume" +external build_unreachable : llbuilder -> llvalue = "llvm_build_unreachable" + +(*--... Arithmetic .........................................................--*) +external build_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_add" +external build_nsw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_add" +external build_nuw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_add" +external build_fadd : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fadd" +external build_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_sub" +external build_nsw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_sub" +external build_nuw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_sub" +external build_fsub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fsub" +external build_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_mul" +external build_nsw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_mul" +external build_nuw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_mul" +external build_fmul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fmul" +external build_udiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_udiv" +external build_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_sdiv" +external build_exact_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_exact_sdiv" +external build_fdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fdiv" +external build_urem : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_urem" +external build_srem : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_srem" +external build_frem : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_frem" +external build_shl : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_shl" +external build_lshr : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_lshr" +external build_ashr : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_ashr" +external build_and : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_and" +external build_or : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_or" +external build_xor : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_xor" +external build_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_neg" +external build_nsw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_neg" +external build_nuw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_neg" +external build_fneg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fneg" +external build_not : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_not" + +(*--... Memory .............................................................--*) +external build_alloca : lltype -> string -> llbuilder -> llvalue + = "llvm_build_alloca" +external build_array_alloca : lltype -> llvalue -> string -> llbuilder -> + llvalue = "llvm_build_array_alloca" +external build_load : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_load" +external build_store : llvalue -> llvalue -> llbuilder -> llvalue + = "llvm_build_store" +external build_atomicrmw : AtomicRMWBinOp.t -> llvalue -> llvalue -> + AtomicOrdering.t -> bool -> string -> llbuilder -> + llvalue + = "llvm_build_atomicrmw_bytecode" + "llvm_build_atomicrmw_native" +external build_gep : llvalue -> llvalue array -> string -> llbuilder -> llvalue + = "llvm_build_gep" +external build_in_bounds_gep : llvalue -> llvalue array -> string -> + llbuilder -> llvalue = "llvm_build_in_bounds_gep" +external build_struct_gep : llvalue -> int -> string -> llbuilder -> llvalue + = "llvm_build_struct_gep" + +external build_global_string : string -> string -> llbuilder -> llvalue + = "llvm_build_global_string" +external build_global_stringptr : string -> string -> llbuilder -> llvalue + = "llvm_build_global_stringptr" + +(*--... Casts ..............................................................--*) +external build_trunc : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_trunc" +external build_zext : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_zext" +external build_sext : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_sext" +external build_fptoui : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fptoui" +external build_fptosi : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fptosi" +external build_uitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_uitofp" +external build_sitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_sitofp" +external build_fptrunc : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fptrunc" +external build_fpext : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fpext" +external build_ptrtoint : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_prttoint" +external build_inttoptr : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_inttoptr" +external build_bitcast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_bitcast" +external build_zext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue = "llvm_build_zext_or_bitcast" +external build_sext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue = "llvm_build_sext_or_bitcast" +external build_trunc_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue = "llvm_build_trunc_or_bitcast" +external build_pointercast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_pointercast" +external build_intcast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_intcast" +external build_fpcast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fpcast" + +(*--... Comparisons ........................................................--*) +external build_icmp : Icmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_icmp" +external build_fcmp : Fcmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_fcmp" + +(*--... Miscellaneous instructions .........................................--*) +external build_phi : (llvalue * llbasicblock) list -> string -> llbuilder -> + llvalue = "llvm_build_phi" +external build_call : llvalue -> llvalue array -> string -> llbuilder -> llvalue + = "llvm_build_call" +external build_select : llvalue -> llvalue -> llvalue -> string -> llbuilder -> + llvalue = "llvm_build_select" +external build_va_arg : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_va_arg" +external build_extractelement : llvalue -> llvalue -> string -> llbuilder -> + llvalue = "llvm_build_extractelement" +external build_insertelement : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_insertelement" +external build_shufflevector : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_shufflevector" +external build_extractvalue : llvalue -> int -> string -> llbuilder -> llvalue + = "llvm_build_extractvalue" +external build_insertvalue : llvalue -> llvalue -> int -> string -> llbuilder -> + llvalue = "llvm_build_insertvalue" + +external build_is_null : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_is_null" +external build_is_not_null : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_is_not_null" +external build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_ptrdiff" + + +(*===-- Memory buffers ----------------------------------------------------===*) + +module MemoryBuffer = struct + external of_file : string -> llmemorybuffer = "llvm_memorybuffer_of_file" + external of_stdin : unit -> llmemorybuffer = "llvm_memorybuffer_of_stdin" + external of_string : ?name:string -> string -> llmemorybuffer + = "llvm_memorybuffer_of_string" + external as_string : llmemorybuffer -> string = "llvm_memorybuffer_as_string" + external dispose : llmemorybuffer -> unit = "llvm_memorybuffer_dispose" +end + + +(*===-- Pass Manager ------------------------------------------------------===*) + +module PassManager = struct + type 'a t + type any = [ `Module | `Function ] + external create : unit -> [ `Module ] t = "llvm_passmanager_create" + external create_function : llmodule -> [ `Function ] t + = "LLVMCreateFunctionPassManager" + external run_module : llmodule -> [ `Module ] t -> bool + = "llvm_passmanager_run_module" + external initialize : [ `Function ] t -> bool = "llvm_passmanager_initialize" + external run_function : llvalue -> [ `Function ] t -> bool + = "llvm_passmanager_run_function" + external finalize : [ `Function ] t -> bool = "llvm_passmanager_finalize" + external dispose : [< any ] t -> unit = "llvm_passmanager_dispose" +end diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli new file mode 100644 index 00000000..e9961217 --- /dev/null +++ b/bindings/ocaml/llvm/llvm.mli @@ -0,0 +1,2465 @@ +(*===-- llvm/llvm.mli - LLVM OCaml Interface ------------------------------===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Core API. + + This interface provides an OCaml API for the LLVM intermediate + representation, the classes in the VMCore library. *) + + +(** {6 Abstract types} + + These abstract types correlate directly to the LLVM VMCore classes. *) + +(** The top-level container for all LLVM global data. See the + [llvm::LLVMContext] class. *) +type llcontext + +(** The top-level container for all other LLVM Intermediate Representation (IR) + objects. See the [llvm::Module] class. *) +type llmodule + +(** Each value in the LLVM IR has a type, an instance of [lltype]. See the + [llvm::Type] class. *) +type lltype + +(** Any value in the LLVM IR. Functions, instructions, global variables, + constants, and much more are all [llvalues]. See the [llvm::Value] class. + This type covers a wide range of subclasses. *) +type llvalue + +(** Used to store users and usees of values. See the [llvm::Use] class. *) +type lluse + +(** A basic block in LLVM IR. See the [llvm::BasicBlock] class. *) +type llbasicblock + +(** Used to generate instructions in the LLVM IR. See the [llvm::LLVMBuilder] + class. *) +type llbuilder + +(** Used to efficiently handle large buffers of read-only binary data. + See the [llvm::MemoryBuffer] class. *) +type llmemorybuffer + +(** The kind of an [lltype], the result of [classify_type ty]. See the + [llvm::Type::TypeID] enumeration. *) +module TypeKind : sig + type t = + Void + | Half + | Float + | Double + | X86fp80 + | Fp128 + | Ppc_fp128 + | Label + | Integer + | Function + | Struct + | Array + | Pointer + | Vector + | Metadata + | X86_mmx +end + +(** The linkage of a global value, accessed with {!linkage} and + {!set_linkage}. See [llvm::GlobalValue::LinkageTypes]. *) +module Linkage : sig + type t = + External + | Available_externally + | Link_once + | Link_once_odr + | Link_once_odr_auto_hide + | Weak + | Weak_odr + | Appending + | Internal + | Private + | Dllimport + | Dllexport + | External_weak + | Ghost + | Common + | Linker_private + | Linker_private_weak +end + +(** The linker visibility of a global value, accessed with {!visibility} and + {!set_visibility}. See [llvm::GlobalValue::VisibilityTypes]. *) +module Visibility : sig + type t = + Default + | Hidden + | Protected +end + +(** The following calling convention values may be accessed with + {!function_call_conv} and {!set_function_call_conv}. Calling + conventions are open-ended. *) +module CallConv : sig + val c : int (** [c] is the C calling convention. *) + val fast : int (** [fast] is the calling convention to allow LLVM + maximum optimization opportunities. Use only with + internal linkage. *) + val cold : int (** [cold] is the calling convention for + callee-save. *) + val x86_stdcall : int (** [x86_stdcall] is the familiar stdcall calling + convention from C. *) + val x86_fastcall : int (** [x86_fastcall] is the familiar fastcall calling + convention from C. *) +end + +(** The attribute kind of a function parameter, result or the function itself. + See [llvm::Attribute::AttrKind]. *) +module Attribute : sig + type t = + | Zext + | Sext + | Noreturn + | Inreg + | Structret + | Nounwind + | Noalias + | Byval + | Nest + | Readnone + | Readonly + | Noinline + | Alwaysinline + | Optsize + | Ssp + | Sspreq + | Alignment of int + | Nocapture + | Noredzone + | Noimplicitfloat + | Naked + | Inlinehint + | Stackalignment of int + | ReturnsTwice + | UWTable + | NonLazyBind +end + +(** The predicate for an integer comparison ([icmp]) instruction. + See the [llvm::ICmpInst::Predicate] enumeration. *) +module Icmp : sig + type t = + | Eq + | Ne + | Ugt + | Uge + | Ult + | Ule + | Sgt + | Sge + | Slt + | Sle +end + +(** The predicate for a floating-point comparison ([fcmp]) instruction. + See the [llvm::FCmpInst::Predicate] enumeration. *) +module Fcmp : sig + type t = + | False + | Oeq + | Ogt + | Oge + | Olt + | Ole + | One + | Ord + | Uno + | Ueq + | Ugt + | Uge + | Ult + | Ule + | Une + | True +end + +(** The opcodes for LLVM instructions and constant expressions. *) +module Opcode : sig + type t = + | Invalid (* not an instruction *) + (* Terminator Instructions *) + | Ret + | Br + | Switch + | IndirectBr + | Invoke + | Invalid2 + | Unreachable + (* Standard Binary Operators *) + | Add + | FAdd + | Sub + | FSub + | Mul + | FMul + | UDiv + | SDiv + | FDiv + | URem + | SRem + | FRem + (* Logical Operators *) + | Shl + | LShr + | AShr + | And + | Or + | Xor + (* Memory Operators *) + | Alloca + | Load + | Store + | GetElementPtr + (* Cast Operators *) + | Trunc + | ZExt + | SExt + | FPToUI + | FPToSI + | UIToFP + | SIToFP + | FPTrunc + | FPExt + | PtrToInt + | IntToPtr + | BitCast + (* Other Operators *) + | ICmp + | FCmp + | PHI + | Call + | Select + | UserOp1 + | UserOp2 + | VAArg + | ExtractElement + | InsertElement + | ShuffleVector + | ExtractValue + | InsertValue + | Fence + | AtomicCmpXchg + | AtomicRMW + | Resume + | LandingPad +end + +(** The type of a clause of a [landingpad] instruction. + See [llvm::LandingPadInst::ClauseType]. *) +module LandingPadClauseTy : sig + type t = + | Catch + | Filter +end + +(** The thread local mode of a global value, accessed with {!thread_local_mode} + and {!set_thread_local_mode}. + See [llvm::GlobalVariable::ThreadLocalMode]. *) +module ThreadLocalMode : sig + type t = + | None + | GeneralDynamic + | LocalDynamic + | InitialExec + | LocalExec +end + +(** The ordering of an atomic [load], [store], [cmpxchg], [atomicrmw] or + [fence] instruction. See [llvm::AtomicOrdering]. *) +module AtomicOrdering : sig + type t = + | NotAtomic + | Unordered + | Monotonic + | Invalid (* removed due to API changes *) + | Acquire + | Release + | AcqiureRelease + | SequentiallyConsistent +end + +(** The opcode of an [atomicrmw] instruction. + See [llvm::AtomicRMWInst::BinOp]. *) +module AtomicRMWBinOp : sig + type t = + | Xchg + | Add + | Sub + | And + | Nand + | Or + | Xor + | Max + | Min + | UMax + | UMin +end + +(** The kind of an [llvalue], the result of [classify_value v]. + See the various [LLVMIsA*] functions. *) +module ValueKind : sig + type t = + | NullValue + | Argument + | BasicBlock + | InlineAsm + | MDNode + | MDString + | BlockAddress + | ConstantAggregateZero + | ConstantArray + | ConstantDataArray + | ConstantDataVector + | ConstantExpr + | ConstantFP + | ConstantInt + | ConstantPointerNull + | ConstantStruct + | ConstantVector + | Function + | GlobalAlias + | GlobalVariable + | UndefValue + | Instruction of Opcode.t +end + + +(** {6 Iteration} *) + +(** [Before b] and [At_end a] specify positions from the start of the ['b] list + of [a]. [llpos] is used to specify positions in and for forward iteration + through the various value lists maintained by the LLVM IR. *) +type ('a, 'b) llpos = +| At_end of 'a +| Before of 'b + +(** [After b] and [At_start a] specify positions from the end of the ['b] list + of [a]. [llrev_pos] is used for reverse iteration through the various value + lists maintained by the LLVM IR. *) +type ('a, 'b) llrev_pos = +| At_start of 'a +| After of 'b + + +(** {6 Exceptions} *) + +exception IoError of string + + +(** {6 Global configuration} *) + +(** [enable_pretty_stacktraces ()] enables LLVM's built-in stack trace code. + This intercepts the OS's crash signals and prints which component of LLVM + you were in at the time of the crash. *) +val enable_pretty_stacktrace : unit -> unit + +(** [install_fatal_error_handler f] installs [f] as LLVM's fatal error handler. + The handler will receive the reason for termination as a string. After + the handler has been executed, LLVM calls [exit(1)]. *) +val install_fatal_error_handler : (string -> unit) -> unit + +(** [reset_fatal_error_handler ()] resets LLVM's fatal error handler. *) +val reset_fatal_error_handler : unit -> unit + +(** {6 Contexts} *) + +(** [create_context ()] creates a context for storing the "global" state in + LLVM. See the constructor [llvm::LLVMContext]. *) +val create_context : unit -> llcontext + +(** [destroy_context ()] destroys a context. See the destructor + [llvm::LLVMContext::~LLVMContext]. *) +val dispose_context : llcontext -> unit + +(** See the function [llvm::getGlobalContext]. *) +val global_context : unit -> llcontext + +(** [mdkind_id context name] returns the MDKind ID that corresponds to the + name [name] in the context [context]. See the function + [llvm::LLVMContext::getMDKindID]. *) +val mdkind_id : llcontext -> string -> int + + +(** {6 Modules} *) + +(** [create_module context id] creates a module with the supplied module ID in + the context [context]. Modules are not garbage collected; it is mandatory + to call {!dispose_module} to free memory. See the constructor + [llvm::Module::Module]. *) +val create_module : llcontext -> string -> llmodule + +(** [dispose_module m] destroys a module [m] and all of the IR objects it + contained. All references to subordinate objects are invalidated; + referencing them will invoke undefined behavior. See the destructor + [llvm::Module::~Module]. *) +val dispose_module : llmodule -> unit + +(** [target_triple m] is the target specifier for the module [m], something like + [i686-apple-darwin8]. See the method [llvm::Module::getTargetTriple]. *) +val target_triple: llmodule -> string + +(** [target_triple triple m] changes the target specifier for the module [m] to + the string [triple]. See the method [llvm::Module::setTargetTriple]. *) +val set_target_triple: string -> llmodule -> unit + +(** [data_layout m] is the data layout specifier for the module [m], something + like [e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-...-a0:0:64-f80:128:128]. See the + method [llvm::Module::getDataLayout]. *) +val data_layout: llmodule -> string + +(** [set_data_layout s m] changes the data layout specifier for the module [m] + to the string [s]. See the method [llvm::Module::setDataLayout]. *) +val set_data_layout: string -> llmodule -> unit + +(** [dump_module m] prints the .ll representation of the module [m] to standard + error. See the method [llvm::Module::dump]. *) +val dump_module : llmodule -> unit + +(** [print_module f m] prints the .ll representation of the module [m] + to file [f]. See the method [llvm::Module::print]. *) +val print_module : string -> llmodule -> unit + +(** [string_of_llmodule m] returns the .ll representation of the module [m] + as a string. See the method [llvm::Module::print]. *) +val string_of_llmodule : llmodule -> string + +(** [set_module_inline_asm m asm] sets the inline assembler for the module. See + the method [llvm::Module::setModuleInlineAsm]. *) +val set_module_inline_asm : llmodule -> string -> unit + +(** [module_context m] returns the context of the specified module. + See the method [llvm::Module::getContext] *) +val module_context : llmodule -> llcontext + + +(** {6 Types} *) + +(** [classify_type ty] returns the {!TypeKind.t} corresponding to the type [ty]. + See the method [llvm::Type::getTypeID]. *) +val classify_type : lltype -> TypeKind.t + +(** [type_is_sized ty] returns whether the type has a size or not. + If it doesn't then it is not safe to call the [DataLayout::] methods on it. + *) +val type_is_sized : lltype -> bool + +(** [type_context ty] returns the {!llcontext} corresponding to the type [ty]. + See the method [llvm::Type::getContext]. *) +val type_context : lltype -> llcontext + +(** [dump_type ty] prints the .ll representation of the type [ty] to standard + error. See the method [llvm::Type::dump]. *) +val dump_type : lltype -> unit + +(** [string_of_lltype ty] returns a string describing the type [ty]. *) +val string_of_lltype : lltype -> string + + +(** {7 Operations on integer types} *) + +(** [i1_type c] returns an integer type of bitwidth 1 in the context [c]. See + [llvm::Type::Int1Ty]. *) +val i1_type : llcontext -> lltype + +(** [i8_type c] returns an integer type of bitwidth 8 in the context [c]. See + [llvm::Type::Int8Ty]. *) +val i8_type : llcontext -> lltype + +(** [i16_type c] returns an integer type of bitwidth 16 in the context [c]. See + [llvm::Type::Int16Ty]. *) +val i16_type : llcontext -> lltype + +(** [i32_type c] returns an integer type of bitwidth 32 in the context [c]. See + [llvm::Type::Int32Ty]. *) +val i32_type : llcontext -> lltype + +(** [i64_type c] returns an integer type of bitwidth 64 in the context [c]. See + [llvm::Type::Int64Ty]. *) +val i64_type : llcontext -> lltype + +(** [integer_type c n] returns an integer type of bitwidth [n] in the context + [c]. See the method [llvm::IntegerType::get]. *) +val integer_type : llcontext -> int -> lltype + +(** [integer_bitwidth c ty] returns the number of bits in the integer type [ty] + in the context [c]. See the method [llvm::IntegerType::getBitWidth]. *) +val integer_bitwidth : lltype -> int + + +(** {7 Operations on real types} *) + +(** [float_type c] returns the IEEE 32-bit floating point type in the context + [c]. See [llvm::Type::FloatTy]. *) +val float_type : llcontext -> lltype + +(** [double_type c] returns the IEEE 64-bit floating point type in the context + [c]. See [llvm::Type::DoubleTy]. *) +val double_type : llcontext -> lltype + +(** [x86fp80_type c] returns the x87 80-bit floating point type in the context + [c]. See [llvm::Type::X86_FP80Ty]. *) +val x86fp80_type : llcontext -> lltype + +(** [fp128_type c] returns the IEEE 128-bit floating point type in the context + [c]. See [llvm::Type::FP128Ty]. *) +val fp128_type : llcontext -> lltype + +(** [ppc_fp128_type c] returns the PowerPC 128-bit floating point type in the + context [c]. See [llvm::Type::PPC_FP128Ty]. *) +val ppc_fp128_type : llcontext -> lltype + + +(** {7 Operations on function types} *) + +(** [function_type ret_ty param_tys] returns the function type returning + [ret_ty] and taking [param_tys] as parameters. + See the method [llvm::FunctionType::get]. *) +val function_type : lltype -> lltype array -> lltype + +(** [var_arg_function_type ret_ty param_tys] is just like + [function_type ret_ty param_tys] except that it returns the function type + which also takes a variable number of arguments. + See the method [llvm::FunctionType::get]. *) +val var_arg_function_type : lltype -> lltype array -> lltype + +(** [is_var_arg fty] returns [true] if [fty] is a varargs function type, [false] + otherwise. See the method [llvm::FunctionType::isVarArg]. *) +val is_var_arg : lltype -> bool + +(** [return_type fty] gets the return type of the function type [fty]. + See the method [llvm::FunctionType::getReturnType]. *) +val return_type : lltype -> lltype + +(** [param_types fty] gets the parameter types of the function type [fty]. + See the method [llvm::FunctionType::getParamType]. *) +val param_types : lltype -> lltype array + + +(** {7 Operations on struct types} *) + +(** [struct_type context tys] returns the structure type in the context + [context] containing in the types in the array [tys]. See the method + [llvm::StructType::get]. *) +val struct_type : llcontext -> lltype array -> lltype + +(** [packed_struct_type context ys] returns the packed structure type in the + context [context] containing in the types in the array [tys]. See the method + [llvm::StructType::get]. *) +val packed_struct_type : llcontext -> lltype array -> lltype + +(** [struct_name ty] returns the name of the named structure type [ty], + or None if the structure type is not named *) +val struct_name : lltype -> string option + +(** [named_struct_type context name] returns the named structure type [name] + in the context [context]. + See the method [llvm::StructType::get]. *) +val named_struct_type : llcontext -> string -> lltype + +(** [struct_set_body ty elts ispacked] sets the body of the named struct [ty] + to the [elts] elements. + See the moethd [llvm::StructType::setBody]. *) +val struct_set_body : lltype -> lltype array -> bool -> unit + +(** [struct_element_types sty] returns the constituent types of the struct type + [sty]. See the method [llvm::StructType::getElementType]. *) +val struct_element_types : lltype -> lltype array + +(** [is_packed sty] returns [true] if the structure type [sty] is packed, + [false] otherwise. See the method [llvm::StructType::isPacked]. *) +val is_packed : lltype -> bool + +(** [is_opaque sty] returns [true] if the structure type [sty] is opaque. + [false] otherwise. See the method [llvm::StructType::isOpaque]. *) +val is_opaque : lltype -> bool + + +(** {7 Operations on pointer, vector, and array types} *) + +(** [array_type ty n] returns the array type containing [n] elements of type + [ty]. See the method [llvm::ArrayType::get]. *) +val array_type : lltype -> int -> lltype + +(** [pointer_type ty] returns the pointer type referencing objects of type + [ty] in the default address space (0). + See the method [llvm::PointerType::getUnqual]. *) +val pointer_type : lltype -> lltype + +(** [qualified_pointer_type ty as] returns the pointer type referencing objects + of type [ty] in address space [as]. + See the method [llvm::PointerType::get]. *) +val qualified_pointer_type : lltype -> int -> lltype + +(** [vector_type ty n] returns the array type containing [n] elements of the + primitive type [ty]. See the method [llvm::ArrayType::get]. *) +val vector_type : lltype -> int -> lltype + +(** [element_type ty] returns the element type of the pointer, vector, or array + type [ty]. See the method [llvm::SequentialType::get]. *) +val element_type : lltype -> lltype + +(** [element_type aty] returns the element count of the array type [aty]. + See the method [llvm::ArrayType::getNumElements]. *) +val array_length : lltype -> int + +(** [address_space pty] returns the address space qualifier of the pointer type + [pty]. See the method [llvm::PointerType::getAddressSpace]. *) +val address_space : lltype -> int + +(** [element_type ty] returns the element count of the vector type [ty]. + See the method [llvm::VectorType::getNumElements]. *) +val vector_size : lltype -> int + + +(** {7 Operations on other types} *) + +(** [void_type c] creates a type of a function which does not return any + value in the context [c]. See [llvm::Type::VoidTy]. *) +val void_type : llcontext -> lltype + +(** [label_type c] creates a type of a basic block in the context [c]. See + [llvm::Type::LabelTy]. *) +val label_type : llcontext -> lltype + +(** [x86_mmx_type c] returns the x86 64-bit MMX register type in the + context [c]. See [llvm::Type::X86_MMXTy]. *) +val x86_mmx_type : llcontext -> lltype + +(** [type_by_name m name] returns the specified type from the current module + if it exists. + See the method [llvm::Module::getTypeByName] *) +val type_by_name : llmodule -> string -> lltype option + + +(* {6 Values} *) + +(** [type_of v] returns the type of the value [v]. + See the method [llvm::Value::getType]. *) +val type_of : llvalue -> lltype + +(** [classify_value v] returns the kind of the value [v]. *) +val classify_value : llvalue -> ValueKind.t + +(** [value_name v] returns the name of the value [v]. For global values, this is + the symbol name. For instructions and basic blocks, it is the SSA register + name. It is meaningless for constants. + See the method [llvm::Value::getName]. *) +val value_name : llvalue -> string + +(** [set_value_name n v] sets the name of the value [v] to [n]. See the method + [llvm::Value::setName]. *) +val set_value_name : string -> llvalue -> unit + +(** [dump_value v] prints the .ll representation of the value [v] to standard + error. See the method [llvm::Value::dump]. *) +val dump_value : llvalue -> unit + +(** [string_of_llvalue v] returns a string describing the value [v]. *) +val string_of_llvalue : llvalue -> string + +(** [replace_all_uses_with old new] replaces all uses of the value [old] + with the value [new]. See the method [llvm::Value::replaceAllUsesWith]. *) +val replace_all_uses_with : llvalue -> llvalue -> unit + + +(* {6 Uses} *) + +(** [use_begin v] returns the first position in the use list for the value [v]. + [use_begin] and [use_succ] can e used to iterate over the use list in order. + See the method [llvm::Value::use_begin]. *) +val use_begin : llvalue -> lluse option + +(** [use_succ u] returns the use list position succeeding [u]. + See the method [llvm::use_value_iterator::operator++]. *) +val use_succ : lluse -> lluse option + +(** [user u] returns the user of the use [u]. + See the method [llvm::Use::getUser]. *) +val user : lluse -> llvalue + +(** [used_value u] returns the usee of the use [u]. + See the method [llvm::Use::getUsedValue]. *) +val used_value : lluse -> llvalue + +(** [iter_uses f v] applies function [f] to each of the users of the value [v] + in order. Tail recursive. *) +val iter_uses : (lluse -> unit) -> llvalue -> unit + +(** [fold_left_uses f init v] is [f (... (f init u1) ...) uN] where + [u1,...,uN] are the users of the value [v]. Tail recursive. *) +val fold_left_uses : ('a -> lluse -> 'a) -> 'a -> llvalue -> 'a + +(** [fold_right_uses f v init] is [f u1 (... (f uN init) ...)] where + [u1,...,uN] are the users of the value [v]. Not tail recursive. *) +val fold_right_uses : (lluse -> 'a -> 'a) -> llvalue -> 'a -> 'a + + +(* {6 Users} *) + +(** [operand v i] returns the operand at index [i] for the value [v]. See the + method [llvm::User::getOperand]. *) +val operand : llvalue -> int -> llvalue + +(** [set_operand v i o] sets the operand of the value [v] at the index [i] to + the value [o]. + See the method [llvm::User::setOperand]. *) +val set_operand : llvalue -> int -> llvalue -> unit + +(** [num_operands v] returns the number of operands for the value [v]. + See the method [llvm::User::getNumOperands]. *) +val num_operands : llvalue -> int + + +(** {7 Operations on constants of (mostly) any type} *) + +(** [is_constant v] returns [true] if the value [v] is a constant, [false] + otherwise. Similar to [llvm::isa]. *) +val is_constant : llvalue -> bool + +(** [const_null ty] returns the constant null (zero) of the type [ty]. + See the method [llvm::Constant::getNullValue]. *) +val const_null : lltype -> llvalue + +(** [const_all_ones ty] returns the constant '-1' of the integer or vector type + [ty]. See the method [llvm::Constant::getAllOnesValue]. *) +val const_all_ones : (*int|vec*)lltype -> llvalue + +(** [const_pointer_null ty] returns the constant null (zero) pointer of the type + [ty]. See the method [llvm::ConstantPointerNull::get]. *) +val const_pointer_null : lltype -> llvalue + +(** [undef ty] returns the undefined value of the type [ty]. + See the method [llvm::UndefValue::get]. *) +val undef : lltype -> llvalue + +(** [is_null v] returns [true] if the value [v] is the null (zero) value. + See the method [llvm::Constant::isNullValue]. *) +val is_null : llvalue -> bool + +(** [is_undef v] returns [true] if the value [v] is an undefined value, [false] + otherwise. Similar to [llvm::isa]. *) +val is_undef : llvalue -> bool + +(** [constexpr_opcode v] returns an [Opcode.t] corresponding to constexpr + value [v], or [Opcode.Invalid] if [v] is not a constexpr. *) +val constexpr_opcode : llvalue -> Opcode.t + + +(** {7 Operations on instructions} *) + +(** [has_metadata i] returns whether or not the instruction [i] has any + metadata attached to it. See the function + [llvm::Instruction::hasMetadata]. *) +val has_metadata : llvalue -> bool + +(** [metadata i kind] optionally returns the metadata associated with the + kind [kind] in the instruction [i] See the function + [llvm::Instruction::getMetadata]. *) +val metadata : llvalue -> int -> llvalue option + +(** [set_metadata i kind md] sets the metadata [md] of kind [kind] in the + instruction [i]. See the function [llvm::Instruction::setMetadata]. *) +val set_metadata : llvalue -> int -> llvalue -> unit + +(** [clear_metadata i kind] clears the metadata of kind [kind] in the + instruction [i]. See the function [llvm::Instruction::setMetadata]. *) +val clear_metadata : llvalue -> int -> unit + + +(** {7 Operations on metadata} *) + +(** [mdstring c s] returns the MDString of the string [s] in the context [c]. + See the method [llvm::MDNode::get]. *) +val mdstring : llcontext -> string -> llvalue + +(** [mdnode c elts] returns the MDNode containing the values [elts] in the + context [c]. + See the method [llvm::MDNode::get]. *) +val mdnode : llcontext -> llvalue array -> llvalue + +(** [get_mdstring v] returns the MDString. + See the method [llvm::MDString::getString] *) +val get_mdstring : llvalue -> string option + +(** [get_named_metadata m name] returns all the MDNodes belonging to the named + metadata (if any). + See the method [llvm::NamedMDNode::getOperand]. *) +val get_named_metadata : llmodule -> string -> llvalue array + +(** [add_named_metadata_operand m name v] adds [v] as the last operand of + metadata named [name] in module [m]. If the metadata does not exist, + it is created. + See the methods [llvm::Module::getNamedMetadata()] and + [llvm::MDNode::addOperand()]. *) +val add_named_metadata_operand : llmodule -> string -> llvalue -> unit + + +(** {7 Operations on scalar constants} *) + +(** [const_int ty i] returns the integer constant of type [ty] and value [i]. + See the method [llvm::ConstantInt::get]. *) +val const_int : lltype -> int -> llvalue + +(** [const_of_int64 ty i] returns the integer constant of type [ty] and value + [i]. See the method [llvm::ConstantInt::get]. *) +val const_of_int64 : lltype -> Int64.t -> bool -> llvalue + +(** [int64_of_const c] returns the int64 value of the [c] constant integer. + None is returned if this is not an integer constant, or bitwidth exceeds 64. + See the method [llvm::ConstantInt::getSExtValue].*) +val int64_of_const : llvalue -> Int64.t option + +(** [const_int_of_string ty s r] returns the integer constant of type [ty] and + value [s], with the radix [r]. See the method [llvm::ConstantInt::get]. *) +val const_int_of_string : lltype -> string -> int -> llvalue + +(** [const_float ty n] returns the floating point constant of type [ty] and + value [n]. See the method [llvm::ConstantFP::get]. *) +val const_float : lltype -> float -> llvalue + +(** [const_float_of_string ty s] returns the floating point constant of type + [ty] and value [n]. See the method [llvm::ConstantFP::get]. *) +val const_float_of_string : lltype -> string -> llvalue + + +(** {7 Operations on composite constants} *) + +(** [const_string c s] returns the constant [i8] array with the values of the + characters in the string [s] in the context [c]. The array is not + null-terminated (but see {!const_stringz}). This value can in turn be used + as the initializer for a global variable. See the method + [llvm::ConstantArray::get]. *) +val const_string : llcontext -> string -> llvalue + +(** [const_stringz c s] returns the constant [i8] array with the values of the + characters in the string [s] and a null terminator in the context [c]. This + value can in turn be used as the initializer for a global variable. + See the method [llvm::ConstantArray::get]. *) +val const_stringz : llcontext -> string -> llvalue + +(** [const_array ty elts] returns the constant array of type + [array_type ty (Array.length elts)] and containing the values [elts]. + This value can in turn be used as the initializer for a global variable. + See the method [llvm::ConstantArray::get]. *) +val const_array : lltype -> llvalue array -> llvalue + +(** [const_struct context elts] returns the structured constant of type + [struct_type (Array.map type_of elts)] and containing the values [elts] + in the context [context]. This value can in turn be used as the initializer + for a global variable. See the method [llvm::ConstantStruct::getAnon]. *) +val const_struct : llcontext -> llvalue array -> llvalue + +(** [const_named_struct namedty elts] returns the structured constant of type + [namedty] (which must be a named structure type) and containing the values [elts]. + This value can in turn be used as the initializer + for a global variable. See the method [llvm::ConstantStruct::get]. *) +val const_named_struct : lltype -> llvalue array -> llvalue + +(** [const_packed_struct context elts] returns the structured constant of + type {!packed_struct_type} [(Array.map type_of elts)] and containing the + values [elts] in the context [context]. This value can in turn be used as + the initializer for a global variable. See the method + [llvm::ConstantStruct::get]. *) +val const_packed_struct : llcontext -> llvalue array -> llvalue + +(** [const_vector elts] returns the vector constant of type + [vector_type (type_of elts.(0)) (Array.length elts)] and containing the + values [elts]. See the method [llvm::ConstantVector::get]. *) +val const_vector : llvalue array -> llvalue + + +(** {7 Constant expressions} *) + +(** [align_of ty] returns the alignof constant for the type [ty]. This is + equivalent to [const_ptrtoint (const_gep (const_null (pointer_type {i8,ty})) + (const_int i32_type 0) (const_int i32_type 1)) i32_type], but considerably + more readable. See the method [llvm::ConstantExpr::getAlignOf]. *) +val align_of : lltype -> llvalue + +(** [size_of ty] returns the sizeof constant for the type [ty]. This is + equivalent to [const_ptrtoint (const_gep (const_null (pointer_type ty)) + (const_int i32_type 1)) i64_type], but considerably more readable. + See the method [llvm::ConstantExpr::getSizeOf]. *) +val size_of : lltype -> llvalue + +(** [const_neg c] returns the arithmetic negation of the constant [c]. + See the method [llvm::ConstantExpr::getNeg]. *) +val const_neg : llvalue -> llvalue + +(** [const_nsw_neg c] returns the arithmetic negation of the constant [c] with + no signed wrapping. The result is undefined if the negation overflows. + See the method [llvm::ConstantExpr::getNSWNeg]. *) +val const_nsw_neg : llvalue -> llvalue + +(** [const_nuw_neg c] returns the arithmetic negation of the constant [c] with + no unsigned wrapping. The result is undefined if the negation overflows. + See the method [llvm::ConstantExpr::getNUWNeg]. *) +val const_nuw_neg : llvalue -> llvalue + +(** [const_fneg c] returns the arithmetic negation of the constant float [c]. + See the method [llvm::ConstantExpr::getFNeg]. *) +val const_fneg : llvalue -> llvalue + +(** [const_not c] returns the bitwise inverse of the constant [c]. + See the method [llvm::ConstantExpr::getNot]. *) +val const_not : llvalue -> llvalue + +(** [const_add c1 c2] returns the constant sum of two constants. + See the method [llvm::ConstantExpr::getAdd]. *) +val const_add : llvalue -> llvalue -> llvalue + +(** [const_nsw_add c1 c2] returns the constant sum of two constants with no + signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWAdd]. *) +val const_nsw_add : llvalue -> llvalue -> llvalue + +(** [const_nuw_add c1 c2] returns the constant sum of two constants with no + unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWAdd]. *) +val const_nuw_add : llvalue -> llvalue -> llvalue + +(** [const_fadd c1 c2] returns the constant sum of two constant floats. + See the method [llvm::ConstantExpr::getFAdd]. *) +val const_fadd : llvalue -> llvalue -> llvalue + +(** [const_sub c1 c2] returns the constant difference, [c1 - c2], of two + constants. See the method [llvm::ConstantExpr::getSub]. *) +val const_sub : llvalue -> llvalue -> llvalue + +(** [const_nsw_sub c1 c2] returns the constant difference of two constants with + no signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWSub]. *) +val const_nsw_sub : llvalue -> llvalue -> llvalue + +(** [const_nuw_sub c1 c2] returns the constant difference of two constants with + no unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWSub]. *) +val const_nuw_sub : llvalue -> llvalue -> llvalue + +(** [const_fsub c1 c2] returns the constant difference, [c1 - c2], of two + constant floats. See the method [llvm::ConstantExpr::getFSub]. *) +val const_fsub : llvalue -> llvalue -> llvalue + +(** [const_mul c1 c2] returns the constant product of two constants. + See the method [llvm::ConstantExpr::getMul]. *) +val const_mul : llvalue -> llvalue -> llvalue + +(** [const_nsw_mul c1 c2] returns the constant product of two constants with + no signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWMul]. *) +val const_nsw_mul : llvalue -> llvalue -> llvalue + +(** [const_nuw_mul c1 c2] returns the constant product of two constants with + no unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWMul]. *) +val const_nuw_mul : llvalue -> llvalue -> llvalue + +(** [const_fmul c1 c2] returns the constant product of two constants floats. + See the method [llvm::ConstantExpr::getFMul]. *) +val const_fmul : llvalue -> llvalue -> llvalue + +(** [const_udiv c1 c2] returns the constant quotient [c1 / c2] of two unsigned + integer constants. + See the method [llvm::ConstantExpr::getUDiv]. *) +val const_udiv : llvalue -> llvalue -> llvalue + +(** [const_sdiv c1 c2] returns the constant quotient [c1 / c2] of two signed + integer constants. + See the method [llvm::ConstantExpr::getSDiv]. *) +val const_sdiv : llvalue -> llvalue -> llvalue + +(** [const_exact_sdiv c1 c2] returns the constant quotient [c1 / c2] of two + signed integer constants. The result is undefined if the result is rounded + or overflows. See the method [llvm::ConstantExpr::getExactSDiv]. *) +val const_exact_sdiv : llvalue -> llvalue -> llvalue + +(** [const_fdiv c1 c2] returns the constant quotient [c1 / c2] of two floating + point constants. + See the method [llvm::ConstantExpr::getFDiv]. *) +val const_fdiv : llvalue -> llvalue -> llvalue + +(** [const_urem c1 c2] returns the constant remainder [c1 MOD c2] of two + unsigned integer constants. + See the method [llvm::ConstantExpr::getURem]. *) +val const_urem : llvalue -> llvalue -> llvalue + +(** [const_srem c1 c2] returns the constant remainder [c1 MOD c2] of two + signed integer constants. + See the method [llvm::ConstantExpr::getSRem]. *) +val const_srem : llvalue -> llvalue -> llvalue + +(** [const_frem c1 c2] returns the constant remainder [c1 MOD c2] of two + signed floating point constants. + See the method [llvm::ConstantExpr::getFRem]. *) +val const_frem : llvalue -> llvalue -> llvalue + +(** [const_and c1 c2] returns the constant bitwise [AND] of two integer + constants. + See the method [llvm::ConstantExpr::getAnd]. *) +val const_and : llvalue -> llvalue -> llvalue + +(** [const_or c1 c2] returns the constant bitwise [OR] of two integer + constants. + See the method [llvm::ConstantExpr::getOr]. *) +val const_or : llvalue -> llvalue -> llvalue + +(** [const_xor c1 c2] returns the constant bitwise [XOR] of two integer + constants. + See the method [llvm::ConstantExpr::getXor]. *) +val const_xor : llvalue -> llvalue -> llvalue + +(** [const_icmp pred c1 c2] returns the constant comparison of two integer + constants, [c1 pred c2]. + See the method [llvm::ConstantExpr::getICmp]. *) +val const_icmp : Icmp.t -> llvalue -> llvalue -> llvalue + +(** [const_fcmp pred c1 c2] returns the constant comparison of two floating + point constants, [c1 pred c2]. + See the method [llvm::ConstantExpr::getFCmp]. *) +val const_fcmp : Fcmp.t -> llvalue -> llvalue -> llvalue + +(** [const_shl c1 c2] returns the constant integer [c1] left-shifted by the + constant integer [c2]. + See the method [llvm::ConstantExpr::getShl]. *) +val const_shl : llvalue -> llvalue -> llvalue + +(** [const_lshr c1 c2] returns the constant integer [c1] right-shifted by the + constant integer [c2] with zero extension. + See the method [llvm::ConstantExpr::getLShr]. *) +val const_lshr : llvalue -> llvalue -> llvalue + +(** [const_ashr c1 c2] returns the constant integer [c1] right-shifted by the + constant integer [c2] with sign extension. + See the method [llvm::ConstantExpr::getAShr]. *) +val const_ashr : llvalue -> llvalue -> llvalue + +(** [const_gep pc indices] returns the constant [getElementPtr] of [p1] with the + constant integers indices from the array [indices]. + See the method [llvm::ConstantExpr::getGetElementPtr]. *) +val const_gep : llvalue -> llvalue array -> llvalue + +(** [const_in_bounds_gep pc indices] returns the constant [getElementPtr] of [p1] + with the constant integers indices from the array [indices]. + See the method [llvm::ConstantExpr::getInBoundsGetElementPtr]. *) +val const_in_bounds_gep : llvalue -> llvalue array -> llvalue + +(** [const_trunc c ty] returns the constant truncation of integer constant [c] + to the smaller integer type [ty]. + See the method [llvm::ConstantExpr::getTrunc]. *) +val const_trunc : llvalue -> lltype -> llvalue + +(** [const_sext c ty] returns the constant sign extension of integer constant + [c] to the larger integer type [ty]. + See the method [llvm::ConstantExpr::getSExt]. *) +val const_sext : llvalue -> lltype -> llvalue + +(** [const_zext c ty] returns the constant zero extension of integer constant + [c] to the larger integer type [ty]. + See the method [llvm::ConstantExpr::getZExt]. *) +val const_zext : llvalue -> lltype -> llvalue + +(** [const_fptrunc c ty] returns the constant truncation of floating point + constant [c] to the smaller floating point type [ty]. + See the method [llvm::ConstantExpr::getFPTrunc]. *) +val const_fptrunc : llvalue -> lltype -> llvalue + +(** [const_fpext c ty] returns the constant extension of floating point constant + [c] to the larger floating point type [ty]. + See the method [llvm::ConstantExpr::getFPExt]. *) +val const_fpext : llvalue -> lltype -> llvalue + +(** [const_uitofp c ty] returns the constant floating point conversion of + unsigned integer constant [c] to the floating point type [ty]. + See the method [llvm::ConstantExpr::getUIToFP]. *) +val const_uitofp : llvalue -> lltype -> llvalue + +(** [const_sitofp c ty] returns the constant floating point conversion of + signed integer constant [c] to the floating point type [ty]. + See the method [llvm::ConstantExpr::getSIToFP]. *) +val const_sitofp : llvalue -> lltype -> llvalue + +(** [const_fptoui c ty] returns the constant unsigned integer conversion of + floating point constant [c] to integer type [ty]. + See the method [llvm::ConstantExpr::getFPToUI]. *) +val const_fptoui : llvalue -> lltype -> llvalue + +(** [const_fptoui c ty] returns the constant unsigned integer conversion of + floating point constant [c] to integer type [ty]. + See the method [llvm::ConstantExpr::getFPToSI]. *) +val const_fptosi : llvalue -> lltype -> llvalue + +(** [const_ptrtoint c ty] returns the constant integer conversion of + pointer constant [c] to integer type [ty]. + See the method [llvm::ConstantExpr::getPtrToInt]. *) +val const_ptrtoint : llvalue -> lltype -> llvalue + +(** [const_inttoptr c ty] returns the constant pointer conversion of + integer constant [c] to pointer type [ty]. + See the method [llvm::ConstantExpr::getIntToPtr]. *) +val const_inttoptr : llvalue -> lltype -> llvalue + +(** [const_bitcast c ty] returns the constant bitwise conversion of constant [c] + to type [ty] of equal size. + See the method [llvm::ConstantExpr::getBitCast]. *) +val const_bitcast : llvalue -> lltype -> llvalue + +(** [const_zext_or_bitcast c ty] returns a constant zext or bitwise cast + conversion of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getZExtOrBitCast]. *) +val const_zext_or_bitcast : llvalue -> lltype -> llvalue + +(** [const_sext_or_bitcast c ty] returns a constant sext or bitwise cast + conversion of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getSExtOrBitCast]. *) +val const_sext_or_bitcast : llvalue -> lltype -> llvalue + +(** [const_trunc_or_bitcast c ty] returns a constant trunc or bitwise cast + conversion of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getTruncOrBitCast]. *) +val const_trunc_or_bitcast : llvalue -> lltype -> llvalue + +(** [const_pointercast c ty] returns a constant bitcast or a pointer-to-int + cast conversion of constant [c] to type [ty] of equal size. + See the method [llvm::ConstantExpr::getPointerCast]. *) +val const_pointercast : llvalue -> lltype -> llvalue + +(** [const_intcast c ty ~is_signed] returns a constant sext/zext, bitcast, + or trunc for integer -> integer casts of constant [c] to type [ty]. + When converting a narrower value to a wider one, whether sext or zext + will be used is controlled by [is_signed]. + See the method [llvm::ConstantExpr::getIntegerCast]. *) +val const_intcast : llvalue -> lltype -> is_signed:bool -> llvalue + +(** [const_fpcast c ty] returns a constant fpext, bitcast, or fptrunc for fp -> + fp casts of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getFPCast]. *) +val const_fpcast : llvalue -> lltype -> llvalue + +(** [const_select cond t f] returns the constant conditional which returns value + [t] if the boolean constant [cond] is true and the value [f] otherwise. + See the method [llvm::ConstantExpr::getSelect]. *) +val const_select : llvalue -> llvalue -> llvalue -> llvalue + +(** [const_extractelement vec i] returns the constant [i]th element of + constant vector [vec]. [i] must be a constant [i32] value unsigned less than + the size of the vector. + See the method [llvm::ConstantExpr::getExtractElement]. *) +val const_extractelement : llvalue -> llvalue -> llvalue + +(** [const_insertelement vec v i] returns the constant vector with the same + elements as constant vector [v] but the [i]th element replaced by the + constant [v]. [v] must be a constant value with the type of the vector + elements. [i] must be a constant [i32] value unsigned less than the size + of the vector. + See the method [llvm::ConstantExpr::getInsertElement]. *) +val const_insertelement : llvalue -> llvalue -> llvalue -> llvalue + +(** [const_shufflevector a b mask] returns a constant [shufflevector]. + See the LLVM Language Reference for details on the [shufflevector] + instruction. + See the method [llvm::ConstantExpr::getShuffleVector]. *) +val const_shufflevector : llvalue -> llvalue -> llvalue -> llvalue + +(** [const_extractvalue agg idxs] returns the constant [idxs]th value of + constant aggregate [agg]. Each [idxs] must be less than the size of the + aggregate. See the method [llvm::ConstantExpr::getExtractValue]. *) +val const_extractvalue : llvalue -> int array -> llvalue + +(** [const_insertvalue agg val idxs] inserts the value [val] in the specified + indexs [idxs] in the aggegate [agg]. Each [idxs] must be less than the size + of the aggregate. See the method [llvm::ConstantExpr::getInsertValue]. *) +val const_insertvalue : llvalue -> llvalue -> int array -> llvalue + +(** [const_inline_asm ty asm con side align] inserts a inline assembly string. + See the method [llvm::InlineAsm::get]. *) +val const_inline_asm : lltype -> string -> string -> bool -> bool -> llvalue + +(** [block_address f bb] returns the address of the basic block [bb] in the + function [f]. See the method [llvm::BasicBlock::get]. *) +val block_address : llvalue -> llbasicblock -> llvalue + + +(** {7 Operations on global variables, functions, and aliases (globals)} *) + +(** [global_parent g] is the enclosing module of the global value [g]. + See the method [llvm::GlobalValue::getParent]. *) +val global_parent : llvalue -> llmodule + +(** [is_declaration g] returns [true] if the global value [g] is a declaration + only. Returns [false] otherwise. + See the method [llvm::GlobalValue::isDeclaration]. *) +val is_declaration : llvalue -> bool + +(** [linkage g] returns the linkage of the global value [g]. + See the method [llvm::GlobalValue::getLinkage]. *) +val linkage : llvalue -> Linkage.t + +(** [set_linkage l g] sets the linkage of the global value [g] to [l]. + See the method [llvm::GlobalValue::setLinkage]. *) +val set_linkage : Linkage.t -> llvalue -> unit + +(** [section g] returns the linker section of the global value [g]. + See the method [llvm::GlobalValue::getSection]. *) +val section : llvalue -> string + +(** [set_section s g] sets the linker section of the global value [g] to [s]. + See the method [llvm::GlobalValue::setSection]. *) +val set_section : string -> llvalue -> unit + +(** [visibility g] returns the linker visibility of the global value [g]. + See the method [llvm::GlobalValue::getVisibility]. *) +val visibility : llvalue -> Visibility.t + +(** [set_visibility v g] sets the linker visibility of the global value [g] to + [v]. See the method [llvm::GlobalValue::setVisibility]. *) +val set_visibility : Visibility.t -> llvalue -> unit + +(** [alignment g] returns the required alignment of the global value [g]. + See the method [llvm::GlobalValue::getAlignment]. *) +val alignment : llvalue -> int + +(** [set_alignment n g] sets the required alignment of the global value [g] to + [n] bytes. See the method [llvm::GlobalValue::setAlignment]. *) +val set_alignment : int -> llvalue -> unit + + +(** {7 Operations on global variables} *) + +(** [declare_global ty name m] returns a new global variable of type [ty] and + with name [name] in module [m] in the default address space (0). If such a + global variable already exists, it is returned. If the type of the existing + global differs, then a bitcast to [ty] is returned. *) +val declare_global : lltype -> string -> llmodule -> llvalue + +(** [declare_qualified_global ty name addrspace m] returns a new global variable + of type [ty] and with name [name] in module [m] in the address space + [addrspace]. If such a global variable already exists, it is returned. If + the type of the existing global differs, then a bitcast to [ty] is + returned. *) +val declare_qualified_global : lltype -> string -> int -> llmodule -> llvalue + +(** [define_global name init m] returns a new global with name [name] and + initializer [init] in module [m] in the default address space (0). If the + named global already exists, it is renamed. + See the constructor of [llvm::GlobalVariable]. *) +val define_global : string -> llvalue -> llmodule -> llvalue + +(** [define_qualified_global name init addrspace m] returns a new global with + name [name] and initializer [init] in module [m] in the address space + [addrspace]. If the named global already exists, it is renamed. + See the constructor of [llvm::GlobalVariable]. *) +val define_qualified_global : string -> llvalue -> int -> llmodule -> llvalue + +(** [lookup_global name m] returns [Some g] if a global variable with name + [name] exists in module [m]. If no such global exists, returns [None]. + See the [llvm::GlobalVariable] constructor. *) +val lookup_global : string -> llmodule -> llvalue option + +(** [delete_global gv] destroys the global variable [gv]. + See the method [llvm::GlobalVariable::eraseFromParent]. *) +val delete_global : llvalue -> unit + +(** [global_begin m] returns the first position in the global variable list of + the module [m]. [global_begin] and [global_succ] can be used to iterate + over the global list in order. + See the method [llvm::Module::global_begin]. *) +val global_begin : llmodule -> (llmodule, llvalue) llpos + +(** [global_succ gv] returns the global variable list position succeeding + [Before gv]. + See the method [llvm::Module::global_iterator::operator++]. *) +val global_succ : llvalue -> (llmodule, llvalue) llpos + +(** [iter_globals f m] applies function [f] to each of the global variables of + module [m] in order. Tail recursive. *) +val iter_globals : (llvalue -> unit) -> llmodule -> unit + +(** [fold_left_globals f init m] is [f (... (f init g1) ...) gN] where + [g1,...,gN] are the global variables of module [m]. Tail recursive. *) +val fold_left_globals : ('a -> llvalue -> 'a) -> 'a -> llmodule -> 'a + +(** [global_end m] returns the last position in the global variable list of the + module [m]. [global_end] and [global_pred] can be used to iterate over the + global list in reverse. + See the method [llvm::Module::global_end]. *) +val global_end : llmodule -> (llmodule, llvalue) llrev_pos + +(** [global_pred gv] returns the global variable list position preceding + [After gv]. + See the method [llvm::Module::global_iterator::operator--]. *) +val global_pred : llvalue -> (llmodule, llvalue) llrev_pos + +(** [rev_iter_globals f m] applies function [f] to each of the global variables + of module [m] in reverse order. Tail recursive. *) +val rev_iter_globals : (llvalue -> unit) -> llmodule -> unit + +(** [fold_right_globals f m init] is [f g1 (... (f gN init) ...)] where + [g1,...,gN] are the global variables of module [m]. Tail recursive. *) +val fold_right_globals : (llvalue -> 'a -> 'a) -> llmodule -> 'a -> 'a + +(** [is_global_constant gv] returns [true] if the global variabile [gv] is a + constant. Returns [false] otherwise. + See the method [llvm::GlobalVariable::isConstant]. *) +val is_global_constant : llvalue -> bool + +(** [set_global_constant c gv] sets the global variable [gv] to be a constant if + [c] is [true] and not if [c] is [false]. + See the method [llvm::GlobalVariable::setConstant]. *) +val set_global_constant : bool -> llvalue -> unit + +(** [global_initializer gv] returns the initializer for the global variable + [gv]. See the method [llvm::GlobalVariable::getInitializer]. *) +val global_initializer : llvalue -> llvalue + +(** [set_initializer c gv] sets the initializer for the global variable + [gv] to the constant [c]. + See the method [llvm::GlobalVariable::setInitializer]. *) +val set_initializer : llvalue -> llvalue -> unit + +(** [remove_initializer gv] unsets the initializer for the global variable + [gv]. + See the method [llvm::GlobalVariable::setInitializer]. *) +val remove_initializer : llvalue -> unit + +(** [is_thread_local gv] returns [true] if the global variable [gv] is + thread-local and [false] otherwise. + See the method [llvm::GlobalVariable::isThreadLocal]. *) +val is_thread_local : llvalue -> bool + +(** [set_thread_local c gv] sets the global variable [gv] to be thread local if + [c] is [true] and not otherwise. + See the method [llvm::GlobalVariable::setThreadLocal]. *) +val set_thread_local : bool -> llvalue -> unit + +(** [is_thread_local gv] returns the thread local mode of the global + variable [gv]. + See the method [llvm::GlobalVariable::getThreadLocalMode]. *) +val thread_local_mode : llvalue -> ThreadLocalMode.t + +(** [set_thread_local c gv] sets the thread local mode of the global + variable [gv]. + See the method [llvm::GlobalVariable::setThreadLocalMode]. *) +val set_thread_local_mode : ThreadLocalMode.t -> llvalue -> unit + +(** [is_externally_initialized gv] returns [true] if the global + variable [gv] is externally initialized and [false] otherwise. + See the method [llvm::GlobalVariable::isExternallyInitialized]. *) +val is_externally_initialized : llvalue -> bool + +(** [set_externally_initialized c gv] sets the global variable [gv] to be + externally initialized if [c] is [true] and not otherwise. + See the method [llvm::GlobalVariable::setExternallyInitialized]. *) +val set_externally_initialized : bool -> llvalue -> unit + + +(** {7 Operations on aliases} *) + +(** [add_alias m t a n] inserts an alias in the module [m] with the type [t] and + the aliasee [a] with the name [n]. + See the constructor for [llvm::GlobalAlias]. *) +val add_alias : llmodule -> lltype -> llvalue -> string -> llvalue + + +(** {7 Operations on functions} *) + +(** [declare_function name ty m] returns a new function of type [ty] and + with name [name] in module [m]. If such a function already exists, + it is returned. If the type of the existing function differs, then a bitcast + to [ty] is returned. *) +val declare_function : string -> lltype -> llmodule -> llvalue + +(** [define_function name ty m] creates a new function with name [name] and + type [ty] in module [m]. If the named function already exists, it is + renamed. An entry basic block is created in the function. + See the constructor of [llvm::GlobalVariable]. *) +val define_function : string -> lltype -> llmodule -> llvalue + +(** [lookup_function name m] returns [Some f] if a function with name + [name] exists in module [m]. If no such function exists, returns [None]. + See the method [llvm::Module] constructor. *) +val lookup_function : string -> llmodule -> llvalue option + +(** [delete_function f] destroys the function [f]. + See the method [llvm::Function::eraseFromParent]. *) +val delete_function : llvalue -> unit + +(** [function_begin m] returns the first position in the function list of the + module [m]. [function_begin] and [function_succ] can be used to iterate over + the function list in order. + See the method [llvm::Module::begin]. *) +val function_begin : llmodule -> (llmodule, llvalue) llpos + +(** [function_succ gv] returns the function list position succeeding + [Before gv]. + See the method [llvm::Module::iterator::operator++]. *) +val function_succ : llvalue -> (llmodule, llvalue) llpos + +(** [iter_functions f m] applies function [f] to each of the functions of module + [m] in order. Tail recursive. *) +val iter_functions : (llvalue -> unit) -> llmodule -> unit + +(** [fold_left_function f init m] is [f (... (f init f1) ...) fN] where + [f1,...,fN] are the functions of module [m]. Tail recursive. *) +val fold_left_functions : ('a -> llvalue -> 'a) -> 'a -> llmodule -> 'a + +(** [function_end m] returns the last position in the function list of + the module [m]. [function_end] and [function_pred] can be used to iterate + over the function list in reverse. + See the method [llvm::Module::end]. *) +val function_end : llmodule -> (llmodule, llvalue) llrev_pos + +(** [function_pred gv] returns the function list position preceding [After gv]. + See the method [llvm::Module::iterator::operator--]. *) +val function_pred : llvalue -> (llmodule, llvalue) llrev_pos + +(** [rev_iter_functions f fn] applies function [f] to each of the functions of + module [m] in reverse order. Tail recursive. *) +val rev_iter_functions : (llvalue -> unit) -> llmodule -> unit + +(** [fold_right_functions f m init] is [f (... (f init fN) ...) f1] where + [f1,...,fN] are the functions of module [m]. Tail recursive. *) +val fold_right_functions : (llvalue -> 'a -> 'a) -> llmodule -> 'a -> 'a + +(** [is_intrinsic f] returns true if the function [f] is an intrinsic. + See the method [llvm::Function::isIntrinsic]. *) +val is_intrinsic : llvalue -> bool + +(** [function_call_conv f] returns the calling convention of the function [f]. + See the method [llvm::Function::getCallingConv]. *) +val function_call_conv : llvalue -> int + +(** [set_function_call_conv cc f] sets the calling convention of the function + [f] to the calling convention numbered [cc]. + See the method [llvm::Function::setCallingConv]. *) +val set_function_call_conv : int -> llvalue -> unit + +(** [gc f] returns [Some name] if the function [f] has a garbage + collection algorithm specified and [None] otherwise. + See the method [llvm::Function::getGC]. *) +val gc : llvalue -> string option + +(** [set_gc gc f] sets the collection algorithm for the function [f] to + [gc]. See the method [llvm::Function::setGC]. *) +val set_gc : string option -> llvalue -> unit + +(** [add_function_attr f a] adds attribute [a] to the return type of function + [f]. *) +val add_function_attr : llvalue -> Attribute.t -> unit + +(** [add_target_dependent_function_attr f a] adds target-dependent attribute + [a] to function [f]. *) +val add_target_dependent_function_attr : llvalue -> string -> string -> unit + +(** [function_attr f] returns the function attribute for the function [f]. + See the method [llvm::Function::getAttributes] *) +val function_attr : llvalue -> Attribute.t list + +(** [remove_function_attr f a] removes attribute [a] from the return type of + function [f]. *) +val remove_function_attr : llvalue -> Attribute.t -> unit + + +(** {7 Operations on params} *) + +(** [params f] returns the parameters of function [f]. + See the method [llvm::Function::getArgumentList]. *) +val params : llvalue -> llvalue array + +(** [param f n] returns the [n]th parameter of function [f]. + See the method [llvm::Function::getArgumentList]. *) +val param : llvalue -> int -> llvalue + +(** [param_attr p] returns the attributes of parameter [p]. + See the methods [llvm::Function::getAttributes] and + [llvm::Attributes::getParamAttributes] *) +val param_attr : llvalue -> Attribute.t list + +(** [param_parent p] returns the parent function that owns the parameter. + See the method [llvm::Argument::getParent]. *) +val param_parent : llvalue -> llvalue + +(** [param_begin f] returns the first position in the parameter list of the + function [f]. [param_begin] and [param_succ] can be used to iterate over + the parameter list in order. + See the method [llvm::Function::arg_begin]. *) +val param_begin : llvalue -> (llvalue, llvalue) llpos + +(** [param_succ bb] returns the parameter list position succeeding + [Before bb]. + See the method [llvm::Function::arg_iterator::operator++]. *) +val param_succ : llvalue -> (llvalue, llvalue) llpos + +(** [iter_params f fn] applies function [f] to each of the parameters + of function [fn] in order. Tail recursive. *) +val iter_params : (llvalue -> unit) -> llvalue -> unit + +(** [fold_left_params f init fn] is [f (... (f init b1) ...) bN] where + [b1,...,bN] are the parameters of function [fn]. Tail recursive. *) +val fold_left_params : ('a -> llvalue -> 'a) -> 'a -> llvalue -> 'a + +(** [param_end f] returns the last position in the parameter list of + the function [f]. [param_end] and [param_pred] can be used to iterate + over the parameter list in reverse. + See the method [llvm::Function::arg_end]. *) +val param_end : llvalue -> (llvalue, llvalue) llrev_pos + +(** [param_pred gv] returns the function list position preceding [After gv]. + See the method [llvm::Function::arg_iterator::operator--]. *) +val param_pred : llvalue -> (llvalue, llvalue) llrev_pos + +(** [rev_iter_params f fn] applies function [f] to each of the parameters + of function [fn] in reverse order. Tail recursive. *) +val rev_iter_params : (llvalue -> unit) -> llvalue -> unit + +(** [fold_right_params f fn init] is [f (... (f init bN) ...) b1] where + [b1,...,bN] are the parameters of function [fn]. Tail recursive. *) +val fold_right_params : (llvalue -> 'a -> 'a) -> llvalue -> 'a -> 'a + +(** [add_param p a] adds attribute [a] to parameter [p]. *) +val add_param_attr : llvalue -> Attribute.t -> unit + +(** [remove_param_attr p a] removes attribute [a] from parameter [p]. *) +val remove_param_attr : llvalue -> Attribute.t -> unit + +(** [set_param_alignment p a] set the alignment of parameter [p] to [a]. *) +val set_param_alignment : llvalue -> int -> unit + + +(** {7 Operations on basic blocks} *) + +(** [basic_blocks fn] returns the basic blocks of the function [f]. + See the method [llvm::Function::getBasicBlockList]. *) +val basic_blocks : llvalue -> llbasicblock array + +(** [entry_block fn] returns the entry basic block of the function [f]. + See the method [llvm::Function::getEntryBlock]. *) +val entry_block : llvalue -> llbasicblock + +(** [delete_block bb] deletes the basic block [bb]. + See the method [llvm::BasicBlock::eraseFromParent]. *) +val delete_block : llbasicblock -> unit + +(** [remove_block bb] removes the basic block [bb] from its parent function. + See the method [llvm::BasicBlock::removeFromParent]. *) +val remove_block : llbasicblock -> unit + +(** [move_block_before pos bb] moves the basic block [bb] before [pos]. + See the method [llvm::BasicBlock::moveBefore]. *) +val move_block_before : llbasicblock -> llbasicblock -> unit + +(** [move_block_after pos bb] moves the basic block [bb] after [pos]. + See the method [llvm::BasicBlock::moveAfter]. *) +val move_block_after : llbasicblock -> llbasicblock -> unit + +(** [append_block c name f] creates a new basic block named [name] at the end of + function [f] in the context [c]. + See the constructor of [llvm::BasicBlock]. *) +val append_block : llcontext -> string -> llvalue -> llbasicblock + +(** [insert_block c name bb] creates a new basic block named [name] before the + basic block [bb] in the context [c]. + See the constructor of [llvm::BasicBlock]. *) +val insert_block : llcontext -> string -> llbasicblock -> llbasicblock + +(** [block_parent bb] returns the parent function that owns the basic block. + See the method [llvm::BasicBlock::getParent]. *) +val block_parent : llbasicblock -> llvalue + +(** [block_begin f] returns the first position in the basic block list of the + function [f]. [block_begin] and [block_succ] can be used to iterate over + the basic block list in order. + See the method [llvm::Function::begin]. *) +val block_begin : llvalue -> (llvalue, llbasicblock) llpos + +(** [block_succ bb] returns the basic block list position succeeding + [Before bb]. + See the method [llvm::Function::iterator::operator++]. *) +val block_succ : llbasicblock -> (llvalue, llbasicblock) llpos + +(** [iter_blocks f fn] applies function [f] to each of the basic blocks + of function [fn] in order. Tail recursive. *) +val iter_blocks : (llbasicblock -> unit) -> llvalue -> unit + +(** [fold_left_blocks f init fn] is [f (... (f init b1) ...) bN] where + [b1,...,bN] are the basic blocks of function [fn]. Tail recursive. *) +val fold_left_blocks : ('a -> llbasicblock -> 'a) -> 'a -> llvalue -> 'a + +(** [block_end f] returns the last position in the basic block list of + the function [f]. [block_end] and [block_pred] can be used to iterate + over the basic block list in reverse. + See the method [llvm::Function::end]. *) +val block_end : llvalue -> (llvalue, llbasicblock) llrev_pos + +(** [block_pred bb] returns the basic block list position preceding [After bb]. + See the method [llvm::Function::iterator::operator--]. *) +val block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos + +(** [block_terminator bb] returns the terminator of the basic block [bb]. *) +val block_terminator : llbasicblock -> llvalue option + +(** [rev_iter_blocks f fn] applies function [f] to each of the basic blocks + of function [fn] in reverse order. Tail recursive. *) +val rev_iter_blocks : (llbasicblock -> unit) -> llvalue -> unit + +(** [fold_right_blocks f fn init] is [f (... (f init bN) ...) b1] where + [b1,...,bN] are the basic blocks of function [fn]. Tail recursive. *) +val fold_right_blocks : (llbasicblock -> 'a -> 'a) -> llvalue -> 'a -> 'a + +(** [value_of_block bb] losslessly casts [bb] to an [llvalue]. *) +val value_of_block : llbasicblock -> llvalue + +(** [value_is_block v] returns [true] if the value [v] is a basic block and + [false] otherwise. + Similar to [llvm::isa]. *) +val value_is_block : llvalue -> bool + +(** [block_of_value v] losslessly casts [v] to an [llbasicblock]. *) +val block_of_value : llvalue -> llbasicblock + + +(** {7 Operations on instructions} *) + +(** [instr_parent i] is the enclosing basic block of the instruction [i]. + See the method [llvm::Instruction::getParent]. *) +val instr_parent : llvalue -> llbasicblock + +(** [delete_instruction i] deletes the instruction [i]. + * See the method [llvm::Instruction::eraseFromParent]. *) +val delete_instruction : llvalue -> unit + +(** [instr_begin bb] returns the first position in the instruction list of the + basic block [bb]. [instr_begin] and [instr_succ] can be used to iterate over + the instruction list in order. + See the method [llvm::BasicBlock::begin]. *) +val instr_begin : llbasicblock -> (llbasicblock, llvalue) llpos + +(** [instr_succ i] returns the instruction list position succeeding [Before i]. + See the method [llvm::BasicBlock::iterator::operator++]. *) +val instr_succ : llvalue -> (llbasicblock, llvalue) llpos + +(** [iter_instrs f bb] applies function [f] to each of the instructions of basic + block [bb] in order. Tail recursive. *) +val iter_instrs: (llvalue -> unit) -> llbasicblock -> unit + +(** [fold_left_instrs f init bb] is [f (... (f init g1) ...) gN] where + [g1,...,gN] are the instructions of basic block [bb]. Tail recursive. *) +val fold_left_instrs: ('a -> llvalue -> 'a) -> 'a -> llbasicblock -> 'a + +(** [instr_end bb] returns the last position in the instruction list of the + basic block [bb]. [instr_end] and [instr_pred] can be used to iterate over + the instruction list in reverse. + See the method [llvm::BasicBlock::end]. *) +val instr_end : llbasicblock -> (llbasicblock, llvalue) llrev_pos + +(** [instr_pred i] returns the instruction list position preceding [After i]. + See the method [llvm::BasicBlock::iterator::operator--]. *) +val instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos + +(** [fold_right_instrs f bb init] is [f (... (f init fN) ...) f1] where + [f1,...,fN] are the instructions of basic block [bb]. Tail recursive. *) +val fold_right_instrs: (llvalue -> 'a -> 'a) -> llbasicblock -> 'a -> 'a + +(** [inst_opcode i] returns the [Opcode.t] corresponding to instruction [i], + or [Opcode.Invalid] if [i] is not an instruction. *) +val instr_opcode : llvalue -> Opcode.t + +(** [icmp_predicate i] returns the [Icmp.t] corresponding to an [icmp] + instruction [i]. *) +val icmp_predicate : llvalue -> Icmp.t option + + +(** {7 Operations on call sites} *) + +(** [instruction_call_conv ci] is the calling convention for the call or invoke + instruction [ci], which may be one of the values from the module + {!CallConv}. See the method [llvm::CallInst::getCallingConv] and + [llvm::InvokeInst::getCallingConv]. *) +val instruction_call_conv: llvalue -> int + +(** [set_instruction_call_conv cc ci] sets the calling convention for the call + or invoke instruction [ci] to the integer [cc], which can be one of the + values from the module {!CallConv}. + See the method [llvm::CallInst::setCallingConv] + and [llvm::InvokeInst::setCallingConv]. *) +val set_instruction_call_conv: int -> llvalue -> unit + +(** [add_instruction_param_attr ci i a] adds attribute [a] to the [i]th + parameter of the call or invoke instruction [ci]. [i]=0 denotes the return + value. *) +val add_instruction_param_attr : llvalue -> int -> Attribute.t -> unit + +(** [remove_instruction_param_attr ci i a] removes attribute [a] from the + [i]th parameter of the call or invoke instruction [ci]. [i]=0 denotes the + return value. *) +val remove_instruction_param_attr : llvalue -> int -> Attribute.t -> unit + + +(** {7 Operations on call instructions (only)} *) + +(** [is_tail_call ci] is [true] if the call instruction [ci] is flagged as + eligible for tail call optimization, [false] otherwise. + See the method [llvm::CallInst::isTailCall]. *) +val is_tail_call : llvalue -> bool + +(** [set_tail_call tc ci] flags the call instruction [ci] as eligible for tail + call optimization if [tc] is [true], clears otherwise. + See the method [llvm::CallInst::setTailCall]. *) +val set_tail_call : bool -> llvalue -> unit + + +(** {7 Operations on load/store instructions (only)} *) + +(** [is_volatile i] is [true] if the load or store instruction [i] is marked + as volatile. + See the methods [llvm::LoadInst::isVolatile] and + [llvm::StoreInst::isVolatile]. *) +val is_volatile : llvalue -> bool + +(** [set_volatile v i] marks the load or store instruction [i] as volatile + if [v] is [true], unmarks otherwise. + See the methods [llvm::LoadInst::setVolatile] and + [llvm::StoreInst::setVolatile]. *) +val set_volatile : bool -> llvalue -> unit + + +(** {7 Operations on phi nodes} *) + +(** [add_incoming (v, bb) pn] adds the value [v] to the phi node [pn] for use + with branches from [bb]. See the method [llvm::PHINode::addIncoming]. *) +val add_incoming : (llvalue * llbasicblock) -> llvalue -> unit + +(** [incoming pn] returns the list of value-block pairs for phi node [pn]. + See the method [llvm::PHINode::getIncomingValue]. *) +val incoming : llvalue -> (llvalue * llbasicblock) list + + + +(** {6 Instruction builders} *) + +(** [builder context] creates an instruction builder with no position in + the context [context]. It is invalid to use this builder until its position + is set with {!position_before} or {!position_at_end}. See the constructor + for [llvm::LLVMBuilder]. *) +val builder : llcontext -> llbuilder + +(** [builder_at ip] creates an instruction builder positioned at [ip]. + See the constructor for [llvm::LLVMBuilder]. *) +val builder_at : llcontext -> (llbasicblock, llvalue) llpos -> llbuilder + +(** [builder_before ins] creates an instruction builder positioned before the + instruction [isn]. See the constructor for [llvm::LLVMBuilder]. *) +val builder_before : llcontext -> llvalue -> llbuilder + +(** [builder_at_end bb] creates an instruction builder positioned at the end of + the basic block [bb]. See the constructor for [llvm::LLVMBuilder]. *) +val builder_at_end : llcontext -> llbasicblock -> llbuilder + +(** [position_builder ip bb] moves the instruction builder [bb] to the position + [ip]. + See the constructor for [llvm::LLVMBuilder]. *) +val position_builder : (llbasicblock, llvalue) llpos -> llbuilder -> unit + +(** [position_before ins b] moves the instruction builder [b] to before the + instruction [isn]. See the method [llvm::LLVMBuilder::SetInsertPoint]. *) +val position_before : llvalue -> llbuilder -> unit + +(** [position_at_end bb b] moves the instruction builder [b] to the end of the + basic block [bb]. See the method [llvm::LLVMBuilder::SetInsertPoint]. *) +val position_at_end : llbasicblock -> llbuilder -> unit + +(** [insertion_block b] returns the basic block that the builder [b] is + positioned to insert into. Raises [Not_Found] if the instruction builder is + uninitialized. + See the method [llvm::LLVMBuilder::GetInsertBlock]. *) +val insertion_block : llbuilder -> llbasicblock + +(** [insert_into_builder i name b] inserts the specified instruction [i] at the + position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::Insert]. *) +val insert_into_builder : llvalue -> string -> llbuilder -> unit + + +(** {7 Metadata} *) + +(** [set_current_debug_location b md] sets the current debug location [md] in + the builder [b]. + See the method [llvm::IRBuilder::SetDebugLocation]. *) +val set_current_debug_location : llbuilder -> llvalue -> unit + +(** [clear_current_debug_location b] clears the current debug location in the + builder [b]. *) +val clear_current_debug_location : llbuilder -> unit + +(** [current_debug_location b] returns the current debug location, or None + if none is currently set. + See the method [llvm::IRBuilder::GetDebugLocation]. *) +val current_debug_location : llbuilder -> llvalue option + +(** [set_inst_debug_location b i] sets the current debug location of the builder + [b] to the instruction [i]. + See the method [llvm::IRBuilder::SetInstDebugLocation]. *) +val set_inst_debug_location : llbuilder -> llvalue -> unit + + +(** {7 Terminators} *) + +(** [build_ret_void b] creates a + [ret void] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateRetVoid]. *) +val build_ret_void : llbuilder -> llvalue + +(** [build_ret v b] creates a + [ret %v] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateRet]. *) +val build_ret : llvalue -> llbuilder -> llvalue + +(** [build_aggregate_ret vs b] creates a + [ret {...} { %v1, %v2, ... } ] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAggregateRet]. *) +val build_aggregate_ret : llvalue array -> llbuilder -> llvalue + +(** [build_br bb b] creates a + [br %bb] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateBr]. *) +val build_br : llbasicblock -> llbuilder -> llvalue + +(** [build_cond_br cond tbb fbb b] creates a + [br %cond, %tbb, %fbb] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateCondBr]. *) +val build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder -> + llvalue + +(** [build_switch case elsebb count b] creates an empty + [switch %case, %elsebb] + instruction at the position specified by the instruction builder [b] with + space reserved for [count] cases. + See the method [llvm::LLVMBuilder::CreateSwitch]. *) +val build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue + +(** [build_malloc ty name b] creates an [malloc] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::CallInst::CreateMalloc]. *) +val build_malloc : lltype -> string -> llbuilder -> llvalue + +(** [build_array_malloc ty val name b] creates an [array malloc] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::CallInst::CreateArrayMalloc]. *) +val build_array_malloc : lltype -> llvalue -> string -> llbuilder -> llvalue + +(** [build_free p b] creates a [free] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFree]. *) +val build_free : llvalue -> llbuilder -> llvalue + +(** [add_case sw onval bb] causes switch instruction [sw] to branch to [bb] + when its input matches the constant [onval]. + See the method [llvm::SwitchInst::addCase]. **) +val add_case : llvalue -> llvalue -> llbasicblock -> unit + +(** [switch_default_dest sw] returns the default destination of the [switch] + instruction. + See the method [llvm:;SwitchInst::getDefaultDest]. **) +val switch_default_dest : llvalue -> llbasicblock + +(** [build_indirect_br addr count b] creates a + [indirectbr %addr] + instruction at the position specified by the instruction builder [b] with + space reserved for [count] destinations. + See the method [llvm::LLVMBuilder::CreateIndirectBr]. *) +val build_indirect_br : llvalue -> int -> llbuilder -> llvalue + +(** [add_destination br bb] adds the basic block [bb] as a possible branch + location for the indirectbr instruction [br]. + See the method [llvm::IndirectBrInst::addDestination]. **) +val add_destination : llvalue -> llbasicblock -> unit + +(** [build_invoke fn args tobb unwindbb name b] creates an + [%name = invoke %fn(args) to %tobb unwind %unwindbb] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInvoke]. *) +val build_invoke : llvalue -> llvalue array -> llbasicblock -> + llbasicblock -> string -> llbuilder -> llvalue + +(** [build_landingpad ty persfn numclauses name b] creates an + [landingpad] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateLandingPad]. *) +val build_landingpad : lltype -> llvalue -> int -> string -> llbuilder -> + llvalue + +(** [set_cleanup lp] sets the cleanup flag in the [landingpad]instruction. + See the method [llvm::LandingPadInst::setCleanup]. *) +val set_cleanup : llvalue -> bool -> unit + +(** [add_clause lp clause] adds the clause to the [landingpad]instruction. + See the method [llvm::LandingPadInst::addClause]. *) +val add_clause : llvalue -> llvalue -> unit + +(** [build_resume exn b] builds a [resume exn] instruction + at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateResume] *) +val build_resume : llvalue -> llbuilder -> llvalue + +(** [build_unreachable b] creates an + [unreachable] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateUnwind]. *) +val build_unreachable : llbuilder -> llvalue + + +(** {7 Arithmetic} *) + +(** [build_add x y name b] creates a + [%name = add %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAdd]. *) +val build_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_nsw_add x y name b] creates a + [%name = nsw add %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWAdd]. *) +val build_nsw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_nuw_add x y name b] creates a + [%name = nuw add %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWAdd]. *) +val build_nuw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_fadd x y name b] creates a + [%name = fadd %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFAdd]. *) +val build_fadd : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_sub x y name b] creates a + [%name = sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSub]. *) +val build_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_nsw_sub x y name b] creates a + [%name = nsw sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWSub]. *) +val build_nsw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_nuw_sub x y name b] creates a + [%name = nuw sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWSub]. *) +val build_nuw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_fsub x y name b] creates a + [%name = fsub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFSub]. *) +val build_fsub : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_mul x y name b] creates a + [%name = mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateMul]. *) +val build_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_nsw_mul x y name b] creates a + [%name = nsw mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWMul]. *) +val build_nsw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_nuw_mul x y name b] creates a + [%name = nuw mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWMul]. *) +val build_nuw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_fmul x y name b] creates a + [%name = fmul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFMul]. *) +val build_fmul : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_udiv x y name b] creates a + [%name = udiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateUDiv]. *) +val build_udiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_sdiv x y name b] creates a + [%name = sdiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSDiv]. *) +val build_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_exact_sdiv x y name b] creates a + [%name = exact sdiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateExactSDiv]. *) +val build_exact_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_fdiv x y name b] creates a + [%name = fdiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFDiv]. *) +val build_fdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_urem x y name b] creates a + [%name = urem %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateURem]. *) +val build_urem : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_SRem x y name b] creates a + [%name = srem %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSRem]. *) +val build_srem : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_frem x y name b] creates a + [%name = frem %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFRem]. *) +val build_frem : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_shl x y name b] creates a + [%name = shl %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateShl]. *) +val build_shl : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_lshr x y name b] creates a + [%name = lshr %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateLShr]. *) +val build_lshr : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_ashr x y name b] creates a + [%name = ashr %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAShr]. *) +val build_ashr : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_and x y name b] creates a + [%name = and %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAnd]. *) +val build_and : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_or x y name b] creates a + [%name = or %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateOr]. *) +val build_or : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_xor x y name b] creates a + [%name = xor %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateXor]. *) +val build_xor : llvalue -> llvalue -> string -> llbuilder -> llvalue + +(** [build_neg x name b] creates a + [%name = sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +val build_neg : llvalue -> string -> llbuilder -> llvalue + +(** [build_nsw_neg x name b] creates a + [%name = nsw sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +val build_nsw_neg : llvalue -> string -> llbuilder -> llvalue + +(** [build_nuw_neg x name b] creates a + [%name = nuw sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +val build_nuw_neg : llvalue -> string -> llbuilder -> llvalue + +(** [build_fneg x name b] creates a + [%name = fsub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateFNeg]. *) +val build_fneg : llvalue -> string -> llbuilder -> llvalue + +(** [build_xor x name b] creates a + [%name = xor %x, -1] + instruction at the position specified by the instruction builder [b]. + [-1] is the correct "all ones" value for the type of [x]. + See the method [llvm::LLVMBuilder::CreateXor]. *) +val build_not : llvalue -> string -> llbuilder -> llvalue + + +(** {7 Memory} *) + +(** [build_alloca ty name b] creates a + [%name = alloca %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAlloca]. *) +val build_alloca : lltype -> string -> llbuilder -> llvalue + +(** [build_array_alloca ty n name b] creates a + [%name = alloca %ty, %n] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAlloca]. *) +val build_array_alloca : lltype -> llvalue -> string -> llbuilder -> + llvalue + +(** [build_load v name b] creates a + [%name = load %v] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateLoad]. *) +val build_load : llvalue -> string -> llbuilder -> llvalue + +(** [build_store v p b] creates a + [store %v, %p] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateStore]. *) +val build_store : llvalue -> llvalue -> llbuilder -> llvalue + +(** [build_atomicrmw op ptr val o st b] creates an [atomicrmw] instruction with + operation [op] performed on pointer [ptr] and value [val] with ordering [o] + and singlethread flag set to [st] at the position specified by + the instruction builder [b]. + See the method [llvm::IRBuilder::CreateAtomicRMW]. *) +val build_atomicrmw : AtomicRMWBinOp.t -> llvalue -> llvalue -> + AtomicOrdering.t -> bool -> string -> llbuilder -> llvalue + +(** [build_gep p indices name b] creates a + [%name = getelementptr %p, indices...] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateGetElementPtr]. *) +val build_gep : llvalue -> llvalue array -> string -> llbuilder -> llvalue + +(** [build_in_bounds_gep p indices name b] creates a + [%name = gelementptr inbounds %p, indices...] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInBoundsGetElementPtr]. *) +val build_in_bounds_gep : llvalue -> llvalue array -> string -> llbuilder -> + llvalue + +(** [build_struct_gep p idx name b] creates a + [%name = getelementptr %p, 0, idx] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateStructGetElementPtr]. *) +val build_struct_gep : llvalue -> int -> string -> llbuilder -> + llvalue + +(** [build_global_string str name b] creates a series of instructions that adds + a global string at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateGlobalString]. *) +val build_global_string : string -> string -> llbuilder -> llvalue + +(** [build_global_stringptr str name b] creates a series of instructions that + adds a global string pointer at the position specified by the instruction + builder [b]. + See the method [llvm::LLVMBuilder::CreateGlobalStringPtr]. *) +val build_global_stringptr : string -> string -> llbuilder -> llvalue + + +(** {7 Casts} *) + +(** [build_trunc v ty name b] creates a + [%name = trunc %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateTrunc]. *) +val build_trunc : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_zext v ty name b] creates a + [%name = zext %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateZExt]. *) +val build_zext : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_sext v ty name b] creates a + [%name = sext %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSExt]. *) +val build_sext : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_fptoui v ty name b] creates a + [%name = fptoui %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPToUI]. *) +val build_fptoui : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_fptosi v ty name b] creates a + [%name = fptosi %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPToSI]. *) +val build_fptosi : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_uitofp v ty name b] creates a + [%name = uitofp %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateUIToFP]. *) +val build_uitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_sitofp v ty name b] creates a + [%name = sitofp %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSIToFP]. *) +val build_sitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_fptrunc v ty name b] creates a + [%name = fptrunc %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPTrunc]. *) +val build_fptrunc : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_fpext v ty name b] creates a + [%name = fpext %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPExt]. *) +val build_fpext : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_ptrtoint v ty name b] creates a + [%name = prtotint %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreatePtrToInt]. *) +val build_ptrtoint : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_inttoptr v ty name b] creates a + [%name = inttoptr %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIntToPtr]. *) +val build_inttoptr : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_bitcast v ty name b] creates a + [%name = bitcast %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateBitCast]. *) +val build_bitcast : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_zext_or_bitcast v ty name b] creates a zext or bitcast + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateZExtOrBitCast]. *) +val build_zext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue + +(** [build_sext_or_bitcast v ty name b] creates a sext or bitcast + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSExtOrBitCast]. *) +val build_sext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue + +(** [build_trunc_or_bitcast v ty name b] creates a trunc or bitcast + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateZExtOrBitCast]. *) +val build_trunc_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue + +(** [build_pointercast v ty name b] creates a bitcast or pointer-to-int + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreatePointerCast]. *) +val build_pointercast : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_intcast v ty name b] creates a zext, bitcast, or trunc + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIntCast]. *) +val build_intcast : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_fpcast v ty name b] creates a fpext, bitcast, or fptrunc + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPCast]. *) +val build_fpcast : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** {7 Comparisons} *) + +(** [build_icmp pred x y name b] creates a + [%name = icmp %pred %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateICmp]. *) +val build_icmp : Icmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + +(** [build_fcmp pred x y name b] creates a + [%name = fcmp %pred %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFCmp]. *) +val build_fcmp : Fcmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + + +(** {7 Miscellaneous instructions} *) + +(** [build_phi incoming name b] creates a + [%name = phi %incoming] + instruction at the position specified by the instruction builder [b]. + [incoming] is a list of [(llvalue, llbasicblock)] tuples. + See the method [llvm::LLVMBuilder::CreatePHI]. *) +val build_phi : (llvalue * llbasicblock) list -> string -> llbuilder -> + llvalue + +(** [build_call fn args name b] creates a + [%name = call %fn(args...)] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateCall]. *) +val build_call : llvalue -> llvalue array -> string -> llbuilder -> llvalue + +(** [build_select cond thenv elsev name b] creates a + [%name = select %cond, %thenv, %elsev] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSelect]. *) +val build_select : llvalue -> llvalue -> llvalue -> string -> llbuilder -> + llvalue + +(** [build_va_arg valist argty name b] creates a + [%name = va_arg %valist, %argty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateVAArg]. *) +val build_va_arg : llvalue -> lltype -> string -> llbuilder -> llvalue + +(** [build_extractelement vec i name b] creates a + [%name = extractelement %vec, %i] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateExtractElement]. *) +val build_extractelement : llvalue -> llvalue -> string -> llbuilder -> + llvalue + +(** [build_insertelement vec elt i name b] creates a + [%name = insertelement %vec, %elt, %i] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInsertElement]. *) +val build_insertelement : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + +(** [build_shufflevector veca vecb mask name b] creates a + [%name = shufflevector %veca, %vecb, %mask] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateShuffleVector]. *) +val build_shufflevector : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + +(** [build_insertvalue agg idx name b] creates a + [%name = extractvalue %agg, %idx] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateExtractValue]. *) +val build_extractvalue : llvalue -> int -> string -> llbuilder -> llvalue + + +(** [build_insertvalue agg val idx name b] creates a + [%name = insertvalue %agg, %val, %idx] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInsertValue]. *) +val build_insertvalue : llvalue -> llvalue -> int -> string -> llbuilder -> + llvalue + +(** [build_is_null val name b] creates a + [%name = icmp eq %val, null] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIsNull]. *) +val build_is_null : llvalue -> string -> llbuilder -> llvalue + +(** [build_is_not_null val name b] creates a + [%name = icmp ne %val, null] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIsNotNull]. *) +val build_is_not_null : llvalue -> string -> llbuilder -> llvalue + +(** [build_ptrdiff lhs rhs name b] creates a series of instructions that measure + the difference between two pointer values at the position specified by the + instruction builder [b]. + See the method [llvm::LLVMBuilder::CreatePtrDiff]. *) +val build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** {6 Memory buffers} *) + +module MemoryBuffer : sig + (** [of_file p] is the memory buffer containing the contents of the file at + path [p]. If the file could not be read, then [IoError msg] is + raised. *) + val of_file : string -> llmemorybuffer + + (** [of_stdin ()] is the memory buffer containing the contents of standard input. + If standard input is empty, then [IoError msg] is raised. *) + val of_stdin : unit -> llmemorybuffer + + (** [of_string ~name s] is the memory buffer containing the contents of string [s]. + The name of memory buffer is set to [name] if it is provided. *) + val of_string : ?name:string -> string -> llmemorybuffer + + (** [as_string mb] is the string containing the contents of memory buffer [mb]. *) + val as_string : llmemorybuffer -> string + + (** Disposes of a memory buffer. *) + val dispose : llmemorybuffer -> unit +end + + +(** {6 Pass Managers} *) + +module PassManager : sig + (** *) + type 'a t + type any = [ `Module | `Function ] + + (** [PassManager.create ()] constructs a new whole-module pass pipeline. This + type of pipeline is suitable for link-time optimization and whole-module + transformations. + See the constructor of [llvm::PassManager]. *) + val create : unit -> [ `Module ] t + + (** [PassManager.create_function m] constructs a new function-by-function + pass pipeline over the module [m]. It does not take ownership of [m]. + This type of pipeline is suitable for code generation and JIT compilation + tasks. + See the constructor of [llvm::FunctionPassManager]. *) + val create_function : llmodule -> [ `Function ] t + + (** [run_module m pm] initializes, executes on the module [m], and finalizes + all of the passes scheduled in the pass manager [pm]. Returns [true] if + any of the passes modified the module, [false] otherwise. + See the [llvm::PassManager::run] method. *) + val run_module : llmodule -> [ `Module ] t -> bool + + (** [initialize fpm] initializes all of the function passes scheduled in the + function pass manager [fpm]. Returns [true] if any of the passes modified + the module, [false] otherwise. + See the [llvm::FunctionPassManager::doInitialization] method. *) + val initialize : [ `Function ] t -> bool + + (** [run_function f fpm] executes all of the function passes scheduled in the + function pass manager [fpm] over the function [f]. Returns [true] if any + of the passes modified [f], [false] otherwise. + See the [llvm::FunctionPassManager::run] method. *) + val run_function : llvalue -> [ `Function ] t -> bool + + (** [finalize fpm] finalizes all of the function passes scheduled in in the + function pass manager [fpm]. Returns [true] if any of the passes + modified the module, [false] otherwise. + See the [llvm::FunctionPassManager::doFinalization] method. *) + val finalize : [ `Function ] t -> bool + + (** Frees the memory of a pass pipeline. For function pipelines, does not free + the module. + See the destructor of [llvm::BasePassManager]. *) + val dispose : [< any ] t -> unit +end diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c new file mode 100644 index 00000000..d5ebdcd3 --- /dev/null +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -0,0 +1,2235 @@ +/*===-- llvm_ocaml.c - LLVM OCaml Glue --------------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Core.h" +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/memory.h" +#include "caml/fail.h" +#include "caml/callback.h" +#include +#include +#include + + +/* Can't use the recommended caml_named_value mechanism for backwards + compatibility reasons. This is largely equivalent. */ +static value llvm_ioerror_exn; + +CAMLprim value llvm_register_core_exns(value IoError) { + llvm_ioerror_exn = Field(IoError, 0); + register_global_root(&llvm_ioerror_exn); + + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + +static value llvm_fatal_error_handler; + +static void llvm_fatal_error_trampoline(const char *Reason) { + callback(llvm_fatal_error_handler, copy_string(Reason)); +} + +CAMLprim value llvm_install_fatal_error_handler(value Handler) { + LLVMInstallFatalErrorHandler(llvm_fatal_error_trampoline); + llvm_fatal_error_handler = Handler; + caml_register_global_root(&llvm_fatal_error_handler); + return Val_unit; +} + +CAMLprim value llvm_reset_fatal_error_handler(value Unit) { + caml_remove_global_root(&llvm_fatal_error_handler); + LLVMResetFatalErrorHandler(); + return Val_unit; +} + +CAMLprim value llvm_enable_pretty_stacktrace(value Unit) { + LLVMEnablePrettyStackTrace(); + return Val_unit; +} + +static value alloc_variant(int tag, void *Value) { + value Iter = alloc_small(1, tag); + Field(Iter, 0) = Val_op(Value); + return Iter; +} + +/* Macro to convert the C first/next/last/prev idiom to the Ocaml llpos/ + llrev_pos idiom. */ +#define DEFINE_ITERATORS(camlname, cname, pty, cty, pfun) \ + /* llmodule -> ('a, 'b) llpos */ \ + CAMLprim value llvm_##camlname##_begin(pty Mom) { \ + cty First = LLVMGetFirst##cname(Mom); \ + if (First) \ + return alloc_variant(1, First); \ + return alloc_variant(0, Mom); \ + } \ + \ + /* llvalue -> ('a, 'b) llpos */ \ + CAMLprim value llvm_##camlname##_succ(cty Kid) { \ + cty Next = LLVMGetNext##cname(Kid); \ + if (Next) \ + return alloc_variant(1, Next); \ + return alloc_variant(0, pfun(Kid)); \ + } \ + \ + /* llmodule -> ('a, 'b) llrev_pos */ \ + CAMLprim value llvm_##camlname##_end(pty Mom) { \ + cty Last = LLVMGetLast##cname(Mom); \ + if (Last) \ + return alloc_variant(1, Last); \ + return alloc_variant(0, Mom); \ + } \ + \ + /* llvalue -> ('a, 'b) llrev_pos */ \ + CAMLprim value llvm_##camlname##_pred(cty Kid) { \ + cty Prev = LLVMGetPrevious##cname(Kid); \ + if (Prev) \ + return alloc_variant(1, Prev); \ + return alloc_variant(0, pfun(Kid)); \ + } + + +/*===-- Contexts ----------------------------------------------------------===*/ + +/* unit -> llcontext */ +CAMLprim LLVMContextRef llvm_create_context(value Unit) { + return LLVMContextCreate(); +} + +/* llcontext -> unit */ +CAMLprim value llvm_dispose_context(LLVMContextRef C) { + LLVMContextDispose(C); + return Val_unit; +} + +/* unit -> llcontext */ +CAMLprim LLVMContextRef llvm_global_context(value Unit) { + return LLVMGetGlobalContext(); +} + +/* llcontext -> string -> int */ +CAMLprim value llvm_mdkind_id(LLVMContextRef C, value Name) { + unsigned MDKindID = LLVMGetMDKindIDInContext(C, String_val(Name), + caml_string_length(Name)); + return Val_int(MDKindID); +} + +/*===-- Modules -----------------------------------------------------------===*/ + +/* llcontext -> string -> llmodule */ +CAMLprim LLVMModuleRef llvm_create_module(LLVMContextRef C, value ModuleID) { + return LLVMModuleCreateWithNameInContext(String_val(ModuleID), C); +} + +/* llmodule -> unit */ +CAMLprim value llvm_dispose_module(LLVMModuleRef M) { + LLVMDisposeModule(M); + return Val_unit; +} + +/* llmodule -> string */ +CAMLprim value llvm_target_triple(LLVMModuleRef M) { + return copy_string(LLVMGetTarget(M)); +} + +/* string -> llmodule -> unit */ +CAMLprim value llvm_set_target_triple(value Trip, LLVMModuleRef M) { + LLVMSetTarget(M, String_val(Trip)); + return Val_unit; +} + +/* llmodule -> string */ +CAMLprim value llvm_data_layout(LLVMModuleRef M) { + return copy_string(LLVMGetDataLayout(M)); +} + +/* string -> llmodule -> unit */ +CAMLprim value llvm_set_data_layout(value Layout, LLVMModuleRef M) { + LLVMSetDataLayout(M, String_val(Layout)); + return Val_unit; +} + +/* llmodule -> unit */ +CAMLprim value llvm_dump_module(LLVMModuleRef M) { + LLVMDumpModule(M); + return Val_unit; +} + +/* string -> llmodule -> unit */ +CAMLprim value llvm_print_module(value Filename, LLVMModuleRef M) { + char* Message; + if(LLVMPrintModuleToFile(M, String_val(Filename), &Message)) { + llvm_raise(llvm_ioerror_exn, Message); + } + + return Val_unit; +} + +/* llmodule -> string */ +CAMLprim value llvm_string_of_llmodule(LLVMModuleRef M) { + char* ModuleCStr; + ModuleCStr = LLVMPrintModuleToString(M); + + value ModuleStr = caml_copy_string(ModuleCStr); + LLVMDisposeMessage(ModuleCStr); + + return ModuleStr; +} + +/* llmodule -> string -> unit */ +CAMLprim value llvm_set_module_inline_asm(LLVMModuleRef M, value Asm) { + LLVMSetModuleInlineAsm(M, String_val(Asm)); + return Val_unit; +} + +/*===-- Types -------------------------------------------------------------===*/ + +/* lltype -> TypeKind.t */ +CAMLprim value llvm_classify_type(LLVMTypeRef Ty) { + return Val_int(LLVMGetTypeKind(Ty)); +} + +CAMLprim value llvm_type_is_sized(LLVMTypeRef Ty) { + return Val_bool(LLVMTypeIsSized(Ty)); +} + +/* lltype -> llcontext */ +CAMLprim LLVMContextRef llvm_type_context(LLVMTypeRef Ty) { + return LLVMGetTypeContext(Ty); +} + +/* lltype -> unit */ +CAMLprim value llvm_dump_type(LLVMTypeRef Val) { + LLVMDumpType(Val); + return Val_unit; +} + +/* lltype -> string */ +CAMLprim value llvm_string_of_lltype(LLVMTypeRef M) { + char* TypeCStr; + TypeCStr = LLVMPrintTypeToString(M); + + value TypeStr = caml_copy_string(TypeCStr); + LLVMDisposeMessage(TypeCStr); + + return TypeStr; +} + +/*--... Operations on integer types ........................................--*/ + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i1_type (LLVMContextRef Context) { + return LLVMInt1TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i8_type (LLVMContextRef Context) { + return LLVMInt8TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i16_type (LLVMContextRef Context) { + return LLVMInt16TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i32_type (LLVMContextRef Context) { + return LLVMInt32TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i64_type (LLVMContextRef Context) { + return LLVMInt64TypeInContext(Context); +} + +/* llcontext -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_integer_type(LLVMContextRef Context, value Width) { + return LLVMIntTypeInContext(Context, Int_val(Width)); +} + +/* lltype -> int */ +CAMLprim value llvm_integer_bitwidth(LLVMTypeRef IntegerTy) { + return Val_int(LLVMGetIntTypeWidth(IntegerTy)); +} + +/*--... Operations on real types ...........................................--*/ + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_float_type(LLVMContextRef Context) { + return LLVMFloatTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_double_type(LLVMContextRef Context) { + return LLVMDoubleTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_x86fp80_type(LLVMContextRef Context) { + return LLVMX86FP80TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_fp128_type(LLVMContextRef Context) { + return LLVMFP128TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_ppc_fp128_type(LLVMContextRef Context) { + return LLVMPPCFP128TypeInContext(Context); +} + +/*--... Operations on function types .......................................--*/ + +/* lltype -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_function_type(LLVMTypeRef RetTy, value ParamTys) { + return LLVMFunctionType(RetTy, (LLVMTypeRef *) ParamTys, + Wosize_val(ParamTys), 0); +} + +/* lltype -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_var_arg_function_type(LLVMTypeRef RetTy, + value ParamTys) { + return LLVMFunctionType(RetTy, (LLVMTypeRef *) ParamTys, + Wosize_val(ParamTys), 1); +} + +/* lltype -> bool */ +CAMLprim value llvm_is_var_arg(LLVMTypeRef FunTy) { + return Val_bool(LLVMIsFunctionVarArg(FunTy)); +} + +/* lltype -> lltype array */ +CAMLprim value llvm_param_types(LLVMTypeRef FunTy) { + value Tys = alloc(LLVMCountParamTypes(FunTy), 0); + LLVMGetParamTypes(FunTy, (LLVMTypeRef *) Tys); + return Tys; +} + +/*--... Operations on struct types .........................................--*/ + +/* llcontext -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_struct_type(LLVMContextRef C, value ElementTypes) { + return LLVMStructTypeInContext(C, (LLVMTypeRef *) ElementTypes, + Wosize_val(ElementTypes), 0); +} + +/* llcontext -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_packed_struct_type(LLVMContextRef C, + value ElementTypes) { + return LLVMStructTypeInContext(C, (LLVMTypeRef *) ElementTypes, + Wosize_val(ElementTypes), 1); +} + +/* llcontext -> string -> lltype */ +CAMLprim LLVMTypeRef llvm_named_struct_type(LLVMContextRef C, + value Name) { + return LLVMStructCreateNamed(C, String_val(Name)); +} + +CAMLprim value llvm_struct_set_body(LLVMTypeRef Ty, + value ElementTypes, + value Packed) { + LLVMStructSetBody(Ty, (LLVMTypeRef *) ElementTypes, + Wosize_val(ElementTypes), Bool_val(Packed)); + return Val_unit; +} + +/* lltype -> string option */ +CAMLprim value llvm_struct_name(LLVMTypeRef Ty) +{ + CAMLparam0(); + const char *C = LLVMGetStructName(Ty); + if (C) { + CAMLlocal1(result); + result = caml_alloc_small(1, 0); + Store_field(result, 0, caml_copy_string(C)); + CAMLreturn(result); + } + CAMLreturn(Val_int(0)); +} + +/* lltype -> lltype array */ +CAMLprim value llvm_struct_element_types(LLVMTypeRef StructTy) { + value Tys = alloc(LLVMCountStructElementTypes(StructTy), 0); + LLVMGetStructElementTypes(StructTy, (LLVMTypeRef *) Tys); + return Tys; +} + +/* lltype -> bool */ +CAMLprim value llvm_is_packed(LLVMTypeRef StructTy) { + return Val_bool(LLVMIsPackedStruct(StructTy)); +} + +/* lltype -> bool */ +CAMLprim value llvm_is_opaque(LLVMTypeRef StructTy) { + return Val_bool(LLVMIsOpaqueStruct(StructTy)); +} + +/*--... Operations on array, pointer, and vector types .....................--*/ + +/* lltype -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_array_type(LLVMTypeRef ElementTy, value Count) { + return LLVMArrayType(ElementTy, Int_val(Count)); +} + +/* lltype -> lltype */ +CAMLprim LLVMTypeRef llvm_pointer_type(LLVMTypeRef ElementTy) { + return LLVMPointerType(ElementTy, 0); +} + +/* lltype -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_qualified_pointer_type(LLVMTypeRef ElementTy, + value AddressSpace) { + return LLVMPointerType(ElementTy, Int_val(AddressSpace)); +} + +/* lltype -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_vector_type(LLVMTypeRef ElementTy, value Count) { + return LLVMVectorType(ElementTy, Int_val(Count)); +} + +/* lltype -> int */ +CAMLprim value llvm_array_length(LLVMTypeRef ArrayTy) { + return Val_int(LLVMGetArrayLength(ArrayTy)); +} + +/* lltype -> int */ +CAMLprim value llvm_address_space(LLVMTypeRef PtrTy) { + return Val_int(LLVMGetPointerAddressSpace(PtrTy)); +} + +/* lltype -> int */ +CAMLprim value llvm_vector_size(LLVMTypeRef VectorTy) { + return Val_int(LLVMGetVectorSize(VectorTy)); +} + +/*--... Operations on other types ..........................................--*/ + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_void_type (LLVMContextRef Context) { + return LLVMVoidTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_label_type(LLVMContextRef Context) { + return LLVMLabelTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_x86_mmx_type(LLVMContextRef Context) { + return LLVMX86MMXTypeInContext(Context); +} + +CAMLprim value llvm_type_by_name(LLVMModuleRef M, value Name) +{ + CAMLparam1(Name); + LLVMTypeRef Ty = LLVMGetTypeByName(M, String_val(Name)); + if (Ty) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) Ty; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/*===-- VALUES ------------------------------------------------------------===*/ + +/* llvalue -> lltype */ +CAMLprim LLVMTypeRef llvm_type_of(LLVMValueRef Val) { + return LLVMTypeOf(Val); +} + +/* keep in sync with ValueKind.t */ +enum ValueKind { + NullValue=0, + Argument, + BasicBlock, + InlineAsm, + MDNode, + MDString, + BlockAddress, + ConstantAggregateZero, + ConstantArray, + ConstantDataArray, + ConstantDataVector, + ConstantExpr, + ConstantFP, + ConstantInt, + ConstantPointerNull, + ConstantStruct, + ConstantVector, + Function, + GlobalAlias, + GlobalVariable, + UndefValue, + Instruction +}; + +/* llvalue -> ValueKind.t */ +#define DEFINE_CASE(Val, Kind) \ + do {if (LLVMIsA##Kind(Val)) CAMLreturn(Val_int(Kind));} while(0) + +CAMLprim value llvm_classify_value(LLVMValueRef Val) { + CAMLparam0(); + if (!Val) + CAMLreturn(Val_int(NullValue)); + if (LLVMIsAConstant(Val)) { + DEFINE_CASE(Val, BlockAddress); + DEFINE_CASE(Val, ConstantAggregateZero); + DEFINE_CASE(Val, ConstantArray); + DEFINE_CASE(Val, ConstantDataArray); + DEFINE_CASE(Val, ConstantDataVector); + DEFINE_CASE(Val, ConstantExpr); + DEFINE_CASE(Val, ConstantFP); + DEFINE_CASE(Val, ConstantInt); + DEFINE_CASE(Val, ConstantPointerNull); + DEFINE_CASE(Val, ConstantStruct); + DEFINE_CASE(Val, ConstantVector); + } + if (LLVMIsAInstruction(Val)) { + CAMLlocal1(result); + result = caml_alloc_small(1, 0); + Store_field(result, 0, Val_int(LLVMGetInstructionOpcode(Val))); + CAMLreturn(result); + } + if (LLVMIsAGlobalValue(Val)) { + DEFINE_CASE(Val, Function); + DEFINE_CASE(Val, GlobalAlias); + DEFINE_CASE(Val, GlobalVariable); + } + DEFINE_CASE(Val, Argument); + DEFINE_CASE(Val, BasicBlock); + DEFINE_CASE(Val, InlineAsm); + DEFINE_CASE(Val, MDNode); + DEFINE_CASE(Val, MDString); + DEFINE_CASE(Val, UndefValue); + failwith("Unknown Value class"); +} + +/* llvalue -> string */ +CAMLprim value llvm_value_name(LLVMValueRef Val) { + return copy_string(LLVMGetValueName(Val)); +} + +/* string -> llvalue -> unit */ +CAMLprim value llvm_set_value_name(value Name, LLVMValueRef Val) { + LLVMSetValueName(Val, String_val(Name)); + return Val_unit; +} + +/* llvalue -> unit */ +CAMLprim value llvm_dump_value(LLVMValueRef Val) { + LLVMDumpValue(Val); + return Val_unit; +} + +/* llvalue -> string */ +CAMLprim value llvm_string_of_llvalue(LLVMValueRef M) { + char* ValueCStr; + ValueCStr = LLVMPrintValueToString(M); + + value ValueStr = caml_copy_string(ValueCStr); + LLVMDisposeMessage(ValueCStr); + + return ValueStr; +} + +/* llvalue -> llvalue -> unit */ +CAMLprim value llvm_replace_all_uses_with(LLVMValueRef OldVal, + LLVMValueRef NewVal) { + LLVMReplaceAllUsesWith(OldVal, NewVal); + return Val_unit; +} + +/*--... Operations on users ................................................--*/ + +/* llvalue -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_operand(LLVMValueRef V, value I) { + return LLVMGetOperand(V, Int_val(I)); +} + +/* llvalue -> int -> llvalue -> unit */ +CAMLprim value llvm_set_operand(LLVMValueRef U, value I, LLVMValueRef V) { + LLVMSetOperand(U, Int_val(I), V); + return Val_unit; +} + +/* llvalue -> int */ +CAMLprim value llvm_num_operands(LLVMValueRef V) { + return Val_int(LLVMGetNumOperands(V)); +} + +/*--... Operations on constants of (mostly) any type .......................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_constant(LLVMValueRef Val) { + return Val_bool(LLVMIsConstant(Val)); +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_null(LLVMValueRef Val) { + return Val_bool(LLVMIsNull(Val)); +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_undef(LLVMValueRef Val) { + return Val_bool(LLVMIsUndef(Val)); +} + +/* llvalue -> Opcode.t */ +CAMLprim value llvm_constexpr_get_opcode(LLVMValueRef Val) { + return LLVMIsAConstantExpr(Val) ? + Val_int(LLVMGetConstOpcode(Val)) : Val_int(0); +} + +/*--... Operations on instructions .........................................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_has_metadata(LLVMValueRef Val) { + return Val_bool(LLVMHasMetadata(Val)); +} + +/* llvalue -> int -> llvalue option */ +CAMLprim value llvm_metadata(LLVMValueRef Val, value MDKindID) { + CAMLparam1(MDKindID); + LLVMValueRef MD; + if ((MD = LLVMGetMetadata(Val, Int_val(MDKindID)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) MD; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llvalue -> int -> llvalue -> unit */ +CAMLprim value llvm_set_metadata(LLVMValueRef Val, value MDKindID, + LLVMValueRef MD) { + LLVMSetMetadata(Val, Int_val(MDKindID), MD); + return Val_unit; +} + +/* llvalue -> int -> unit */ +CAMLprim value llvm_clear_metadata(LLVMValueRef Val, value MDKindID) { + LLVMSetMetadata(Val, Int_val(MDKindID), NULL); + return Val_unit; +} + + +/*--... Operations on metadata .............................................--*/ + +/* llcontext -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_mdstring(LLVMContextRef C, value S) { + return LLVMMDStringInContext(C, String_val(S), caml_string_length(S)); +} + +/* llcontext -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) { + return LLVMMDNodeInContext(C, (LLVMValueRef*) Op_val(ElementVals), + Wosize_val(ElementVals)); +} + +/* llvalue -> string option */ +CAMLprim value llvm_get_mdstring(LLVMValueRef V) { + CAMLparam0(); + const char *S; + unsigned Len; + + if ((S = LLVMGetMDString(V, &Len))) { + CAMLlocal2(Option, Str); + + Str = caml_alloc_string(Len); + memcpy(String_val(Str), S, Len); + Option = alloc(1,0); + Store_field(Option, 0, Str); + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llmodule -> string -> llvalue array */ +CAMLprim value llvm_get_namedmd(LLVMModuleRef M, value Name) +{ + CAMLparam1(Name); + CAMLlocal1(Nodes); + Nodes = alloc(LLVMGetNamedMetadataNumOperands(M, String_val(Name)), 0); + LLVMGetNamedMetadataOperands(M, String_val(Name), (LLVMValueRef *) Nodes); + CAMLreturn(Nodes); +} + +/* llmodule -> string -> llvalue -> unit */ +CAMLprim value llvm_append_namedmd(LLVMModuleRef M, value Name, LLVMValueRef Val) { + LLVMAddNamedMetadataOperand(M, String_val(Name), Val); + return Val_unit; +} + +/*--... Operations on scalar constants .....................................--*/ + +/* lltype -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_const_int(LLVMTypeRef IntTy, value N) { + return LLVMConstInt(IntTy, (long long) Int_val(N), 1); +} + +/* lltype -> Int64.t -> bool -> llvalue */ +CAMLprim LLVMValueRef llvm_const_of_int64(LLVMTypeRef IntTy, value N, + value SExt) { + return LLVMConstInt(IntTy, Int64_val(N), Bool_val(SExt)); +} + +/* llvalue -> Int64.t */ +CAMLprim value llvm_int64_of_const(LLVMValueRef Const) +{ + CAMLparam0(); + if (LLVMIsAConstantInt(Const) && + LLVMGetIntTypeWidth(LLVMTypeOf(Const)) <= 64) { + value Option = alloc(1, 0); + Field(Option, 0) = caml_copy_int64(LLVMConstIntGetSExtValue(Const)); + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* lltype -> string -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_const_int_of_string(LLVMTypeRef IntTy, value S, + value Radix) { + return LLVMConstIntOfStringAndSize(IntTy, String_val(S), caml_string_length(S), + Int_val(Radix)); +} + +/* lltype -> float -> llvalue */ +CAMLprim LLVMValueRef llvm_const_float(LLVMTypeRef RealTy, value N) { + return LLVMConstReal(RealTy, Double_val(N)); +} + +/* lltype -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_const_float_of_string(LLVMTypeRef RealTy, value S) { + return LLVMConstRealOfStringAndSize(RealTy, String_val(S), + caml_string_length(S)); +} + +/*--... Operations on composite constants ..................................--*/ + +/* llcontext -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_const_string(LLVMContextRef Context, value Str, + value NullTerminate) { + return LLVMConstStringInContext(Context, String_val(Str), string_length(Str), + 1); +} + +/* llcontext -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_const_stringz(LLVMContextRef Context, value Str, + value NullTerminate) { + return LLVMConstStringInContext(Context, String_val(Str), string_length(Str), + 0); +} + +/* lltype -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_array(LLVMTypeRef ElementTy, + value ElementVals) { + return LLVMConstArray(ElementTy, (LLVMValueRef*) Op_val(ElementVals), + Wosize_val(ElementVals)); +} + +/* llcontext -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_struct(LLVMContextRef C, value ElementVals) { + return LLVMConstStructInContext(C, (LLVMValueRef *) Op_val(ElementVals), + Wosize_val(ElementVals), 0); +} + +/* lltype -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_named_struct(LLVMTypeRef Ty, value ElementVals) { + return LLVMConstNamedStruct(Ty, (LLVMValueRef *) Op_val(ElementVals), Wosize_val(ElementVals)); +} + +/* llcontext -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_packed_struct(LLVMContextRef C, + value ElementVals) { + return LLVMConstStructInContext(C, (LLVMValueRef *) Op_val(ElementVals), + Wosize_val(ElementVals), 1); +} + +/* llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_vector(value ElementVals) { + return LLVMConstVector((LLVMValueRef*) Op_val(ElementVals), + Wosize_val(ElementVals)); +} + +/*--... Constant expressions ...............................................--*/ + +/* Icmp.t -> llvalue -> llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_const_icmp(value Pred, + LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return LLVMConstICmp(Int_val(Pred) + LLVMIntEQ, LHSConstant, RHSConstant); +} + +/* Fcmp.t -> llvalue -> llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_const_fcmp(value Pred, + LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return LLVMConstFCmp(Int_val(Pred), LHSConstant, RHSConstant); +} + +/* llvalue -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_gep(LLVMValueRef ConstantVal, value Indices) { + return LLVMConstGEP(ConstantVal, (LLVMValueRef*) Op_val(Indices), + Wosize_val(Indices)); +} + +/* llvalue -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_in_bounds_gep(LLVMValueRef ConstantVal, + value Indices) { + return LLVMConstInBoundsGEP(ConstantVal, (LLVMValueRef*) Op_val(Indices), + Wosize_val(Indices)); +} + +/* llvalue -> lltype -> is_signed:bool -> llvalue */ +CAMLprim LLVMValueRef llvm_const_intcast(LLVMValueRef CV, LLVMTypeRef T, + value IsSigned) { + return LLVMConstIntCast(CV, T, Bool_val(IsSigned)); +} + +/* llvalue -> int array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_extractvalue(LLVMValueRef Aggregate, + value Indices) { + CAMLparam1(Indices); + int size = Wosize_val(Indices); + int i; + LLVMValueRef result; + + unsigned* idxs = (unsigned*)malloc(size * sizeof(unsigned)); + for (i = 0; i < size; i++) { + idxs[i] = Int_val(Field(Indices, i)); + } + + result = LLVMConstExtractValue(Aggregate, idxs, size); + free(idxs); + CAMLreturnT(LLVMValueRef, result); +} + +/* llvalue -> llvalue -> int array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_insertvalue(LLVMValueRef Aggregate, + LLVMValueRef Val, value Indices) { + CAMLparam1(Indices); + int size = Wosize_val(Indices); + int i; + LLVMValueRef result; + + unsigned* idxs = (unsigned*)malloc(size * sizeof(unsigned)); + for (i = 0; i < size; i++) { + idxs[i] = Int_val(Field(Indices, i)); + } + + result = LLVMConstInsertValue(Aggregate, Val, idxs, size); + free(idxs); + CAMLreturnT(LLVMValueRef, result); +} + +/* lltype -> string -> string -> bool -> bool -> llvalue */ +CAMLprim LLVMValueRef llvm_const_inline_asm(LLVMTypeRef Ty, value Asm, + value Constraints, value HasSideEffects, + value IsAlignStack) { + return LLVMConstInlineAsm(Ty, String_val(Asm), String_val(Constraints), + Bool_val(HasSideEffects), Bool_val(IsAlignStack)); +} + +/*--... Operations on global variables, functions, and aliases (globals) ...--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_declaration(LLVMValueRef Global) { + return Val_bool(LLVMIsDeclaration(Global)); +} + +/* llvalue -> Linkage.t */ +CAMLprim value llvm_linkage(LLVMValueRef Global) { + return Val_int(LLVMGetLinkage(Global)); +} + +/* Linkage.t -> llvalue -> unit */ +CAMLprim value llvm_set_linkage(value Linkage, LLVMValueRef Global) { + LLVMSetLinkage(Global, Int_val(Linkage)); + return Val_unit; +} + +/* llvalue -> string */ +CAMLprim value llvm_section(LLVMValueRef Global) { + return copy_string(LLVMGetSection(Global)); +} + +/* string -> llvalue -> unit */ +CAMLprim value llvm_set_section(value Section, LLVMValueRef Global) { + LLVMSetSection(Global, String_val(Section)); + return Val_unit; +} + +/* llvalue -> Visibility.t */ +CAMLprim value llvm_visibility(LLVMValueRef Global) { + return Val_int(LLVMGetVisibility(Global)); +} + +/* Visibility.t -> llvalue -> unit */ +CAMLprim value llvm_set_visibility(value Viz, LLVMValueRef Global) { + LLVMSetVisibility(Global, Int_val(Viz)); + return Val_unit; +} + +/* llvalue -> int */ +CAMLprim value llvm_alignment(LLVMValueRef Global) { + return Val_int(LLVMGetAlignment(Global)); +} + +/* int -> llvalue -> unit */ +CAMLprim value llvm_set_alignment(value Bytes, LLVMValueRef Global) { + LLVMSetAlignment(Global, Int_val(Bytes)); + return Val_unit; +} + +/*--... Operations on uses .................................................--*/ + +/* llvalue -> lluse option */ +CAMLprim value llvm_use_begin(LLVMValueRef Val) { + CAMLparam0(); + LLVMUseRef First; + if ((First = LLVMGetFirstUse(Val))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) First; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* lluse -> lluse option */ +CAMLprim value llvm_use_succ(LLVMUseRef U) { + CAMLparam0(); + LLVMUseRef Next; + if ((Next = LLVMGetNextUse(U))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) Next; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* lluse -> llvalue */ +CAMLprim LLVMValueRef llvm_user(LLVMUseRef UR) { + return LLVMGetUser(UR); +} + +/* lluse -> llvalue */ +CAMLprim LLVMValueRef llvm_used_value(LLVMUseRef UR) { + return LLVMGetUsedValue(UR); +} + +/*--... Operations on global variables .....................................--*/ + +DEFINE_ITERATORS(global, Global, LLVMModuleRef, LLVMValueRef, + LLVMGetGlobalParent) + +/* lltype -> string -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_declare_global(LLVMTypeRef Ty, value Name, + LLVMModuleRef M) { + LLVMValueRef GlobalVar; + if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) { + if (LLVMGetElementType(LLVMTypeOf(GlobalVar)) != Ty) + return LLVMConstBitCast(GlobalVar, LLVMPointerType(Ty, 0)); + return GlobalVar; + } + return LLVMAddGlobal(M, Ty, String_val(Name)); +} + +/* lltype -> string -> int -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_declare_qualified_global(LLVMTypeRef Ty, value Name, + value AddressSpace, + LLVMModuleRef M) { + LLVMValueRef GlobalVar; + if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) { + if (LLVMGetElementType(LLVMTypeOf(GlobalVar)) != Ty) + return LLVMConstBitCast(GlobalVar, + LLVMPointerType(Ty, Int_val(AddressSpace))); + return GlobalVar; + } + return LLVMAddGlobalInAddressSpace(M, Ty, String_val(Name), + Int_val(AddressSpace)); +} + +/* string -> llmodule -> llvalue option */ +CAMLprim value llvm_lookup_global(value Name, LLVMModuleRef M) { + CAMLparam1(Name); + LLVMValueRef GlobalVar; + if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) GlobalVar; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* string -> llvalue -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_define_global(value Name, LLVMValueRef Initializer, + LLVMModuleRef M) { + LLVMValueRef GlobalVar = LLVMAddGlobal(M, LLVMTypeOf(Initializer), + String_val(Name)); + LLVMSetInitializer(GlobalVar, Initializer); + return GlobalVar; +} + +/* string -> llvalue -> int -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_define_qualified_global(value Name, + LLVMValueRef Initializer, + value AddressSpace, + LLVMModuleRef M) { + LLVMValueRef GlobalVar = LLVMAddGlobalInAddressSpace(M, + LLVMTypeOf(Initializer), + String_val(Name), + Int_val(AddressSpace)); + LLVMSetInitializer(GlobalVar, Initializer); + return GlobalVar; +} + +/* llvalue -> unit */ +CAMLprim value llvm_delete_global(LLVMValueRef GlobalVar) { + LLVMDeleteGlobal(GlobalVar); + return Val_unit; +} + +/* llvalue -> llvalue -> unit */ +CAMLprim value llvm_set_initializer(LLVMValueRef ConstantVal, + LLVMValueRef GlobalVar) { + LLVMSetInitializer(GlobalVar, ConstantVal); + return Val_unit; +} + +/* llvalue -> unit */ +CAMLprim value llvm_remove_initializer(LLVMValueRef GlobalVar) { + LLVMSetInitializer(GlobalVar, NULL); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_thread_local(LLVMValueRef GlobalVar) { + return Val_bool(LLVMIsThreadLocal(GlobalVar)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_thread_local(value IsThreadLocal, + LLVMValueRef GlobalVar) { + LLVMSetThreadLocal(GlobalVar, Bool_val(IsThreadLocal)); + return Val_unit; +} + +/* llvalue -> ThreadLocalMode.t */ +CAMLprim value llvm_thread_local_mode(LLVMValueRef GlobalVar) { + return Val_int(LLVMGetThreadLocalMode(GlobalVar)); +} + +/* ThreadLocalMode.t -> llvalue -> unit */ +CAMLprim value llvm_set_thread_local_mode(value ThreadLocalMode, + LLVMValueRef GlobalVar) { + LLVMSetThreadLocalMode(GlobalVar, Int_val(ThreadLocalMode)); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_externally_initialized(LLVMValueRef GlobalVar) { + return Val_bool(LLVMIsExternallyInitialized(GlobalVar)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_externally_initialized(value IsExternallyInitialized, + LLVMValueRef GlobalVar) { + LLVMSetExternallyInitialized(GlobalVar, Bool_val(IsExternallyInitialized)); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_global_constant(LLVMValueRef GlobalVar) { + return Val_bool(LLVMIsGlobalConstant(GlobalVar)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_global_constant(value Flag, LLVMValueRef GlobalVar) { + LLVMSetGlobalConstant(GlobalVar, Bool_val(Flag)); + return Val_unit; +} + +/*--... Operations on aliases ..............................................--*/ + +CAMLprim LLVMValueRef llvm_add_alias(LLVMModuleRef M, LLVMTypeRef Ty, + LLVMValueRef Aliasee, value Name) { + return LLVMAddAlias(M, Ty, Aliasee, String_val(Name)); +} + +/*--... Operations on functions ............................................--*/ + +DEFINE_ITERATORS(function, Function, LLVMModuleRef, LLVMValueRef, + LLVMGetGlobalParent) + +/* string -> lltype -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_declare_function(value Name, LLVMTypeRef Ty, + LLVMModuleRef M) { + LLVMValueRef Fn; + if ((Fn = LLVMGetNamedFunction(M, String_val(Name)))) { + if (LLVMGetElementType(LLVMTypeOf(Fn)) != Ty) + return LLVMConstBitCast(Fn, LLVMPointerType(Ty, 0)); + return Fn; + } + return LLVMAddFunction(M, String_val(Name), Ty); +} + +/* string -> llmodule -> llvalue option */ +CAMLprim value llvm_lookup_function(value Name, LLVMModuleRef M) { + CAMLparam1(Name); + LLVMValueRef Fn; + if ((Fn = LLVMGetNamedFunction(M, String_val(Name)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) Fn; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* string -> lltype -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_define_function(value Name, LLVMTypeRef Ty, + LLVMModuleRef M) { + LLVMValueRef Fn = LLVMAddFunction(M, String_val(Name), Ty); + LLVMAppendBasicBlockInContext(LLVMGetTypeContext(Ty), Fn, "entry"); + return Fn; +} + +/* llvalue -> unit */ +CAMLprim value llvm_delete_function(LLVMValueRef Fn) { + LLVMDeleteFunction(Fn); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_intrinsic(LLVMValueRef Fn) { + return Val_bool(LLVMGetIntrinsicID(Fn)); +} + +/* llvalue -> int */ +CAMLprim value llvm_function_call_conv(LLVMValueRef Fn) { + return Val_int(LLVMGetFunctionCallConv(Fn)); +} + +/* int -> llvalue -> unit */ +CAMLprim value llvm_set_function_call_conv(value Id, LLVMValueRef Fn) { + LLVMSetFunctionCallConv(Fn, Int_val(Id)); + return Val_unit; +} + +/* llvalue -> string option */ +CAMLprim value llvm_gc(LLVMValueRef Fn) { + const char *GC; + CAMLparam0(); + CAMLlocal2(Name, Option); + + if ((GC = LLVMGetGC(Fn))) { + Name = copy_string(GC); + + Option = alloc(1, 0); + Field(Option, 0) = Name; + CAMLreturn(Option); + } else { + CAMLreturn(Val_int(0)); + } +} + +/* string option -> llvalue -> unit */ +CAMLprim value llvm_set_gc(value GC, LLVMValueRef Fn) { + LLVMSetGC(Fn, GC == Val_int(0)? 0 : String_val(Field(GC, 0))); + return Val_unit; +} + +/* llvalue -> int32 -> unit */ +CAMLprim value llvm_add_function_attr(LLVMValueRef Arg, value PA) { + LLVMAddFunctionAttr(Arg, Int32_val(PA)); + return Val_unit; +} + +/* llvalue -> string -> string -> unit */ +CAMLprim value llvm_add_target_dependent_function_attr( + LLVMValueRef Arg, value A, value V) { + LLVMAddTargetDependentFunctionAttr(Arg, String_val(A), String_val(V)); + return Val_unit; +} + +/* llvalue -> int32 */ +CAMLprim value llvm_function_attr(LLVMValueRef Fn) +{ + CAMLparam0(); + CAMLreturn(caml_copy_int32(LLVMGetFunctionAttr(Fn))); +} + +/* llvalue -> int32 -> unit */ +CAMLprim value llvm_remove_function_attr(LLVMValueRef Arg, value PA) { + LLVMRemoveFunctionAttr(Arg, Int32_val(PA)); + return Val_unit; +} +/*--... Operations on parameters ...........................................--*/ + +DEFINE_ITERATORS(param, Param, LLVMValueRef, LLVMValueRef, LLVMGetParamParent) + +/* llvalue -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_param(LLVMValueRef Fn, value Index) { + return LLVMGetParam(Fn, Int_val(Index)); +} + +/* llvalue -> int */ +CAMLprim value llvm_param_attr(LLVMValueRef Param) +{ + CAMLparam0(); + CAMLreturn(caml_copy_int32(LLVMGetAttribute(Param))); +} + +/* llvalue -> llvalue */ +CAMLprim value llvm_params(LLVMValueRef Fn) { + value Params = alloc(LLVMCountParams(Fn), 0); + LLVMGetParams(Fn, (LLVMValueRef *) Op_val(Params)); + return Params; +} + +/* llvalue -> int32 -> unit */ +CAMLprim value llvm_add_param_attr(LLVMValueRef Arg, value PA) { + LLVMAddAttribute(Arg, Int32_val(PA)); + return Val_unit; +} + +/* llvalue -> int32 -> unit */ +CAMLprim value llvm_remove_param_attr(LLVMValueRef Arg, value PA) { + LLVMRemoveAttribute(Arg, Int32_val(PA)); + return Val_unit; +} + +/* llvalue -> int -> unit */ +CAMLprim value llvm_set_param_alignment(LLVMValueRef Arg, value align) { + LLVMSetParamAlignment(Arg, Int_val(align)); + return Val_unit; +} + +/*--... Operations on basic blocks .........................................--*/ + +DEFINE_ITERATORS( + block, BasicBlock, LLVMValueRef, LLVMBasicBlockRef, LLVMGetBasicBlockParent) + +/* llbasicblock -> llvalue option */ +CAMLprim value llvm_block_terminator(LLVMBasicBlockRef Block) +{ + CAMLparam0(); + LLVMValueRef Term = LLVMGetBasicBlockTerminator(Block); + if (Term) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) Term; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llvalue -> llbasicblock array */ +CAMLprim value llvm_basic_blocks(LLVMValueRef Fn) { + value MLArray = alloc(LLVMCountBasicBlocks(Fn), 0); + LLVMGetBasicBlocks(Fn, (LLVMBasicBlockRef *) Op_val(MLArray)); + return MLArray; +} + +/* llbasicblock -> unit */ +CAMLprim value llvm_delete_block(LLVMBasicBlockRef BB) { + LLVMDeleteBasicBlock(BB); + return Val_unit; +} + +/* llbasicblock -> unit */ +CAMLprim value llvm_remove_block(LLVMBasicBlockRef BB) { + LLVMRemoveBasicBlockFromParent(BB); + return Val_unit; +} + +/* llbasicblock -> llbasicblock -> unit */ +CAMLprim value llvm_move_block_before(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) { + LLVMMoveBasicBlockBefore(BB, Pos); + return Val_unit; +} + +/* llbasicblock -> llbasicblock -> unit */ +CAMLprim value llvm_move_block_after(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) { + LLVMMoveBasicBlockAfter(BB, Pos); + return Val_unit; +} + +/* string -> llvalue -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_append_block(LLVMContextRef Context, value Name, + LLVMValueRef Fn) { + return LLVMAppendBasicBlockInContext(Context, Fn, String_val(Name)); +} + +/* string -> llbasicblock -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_insert_block(LLVMContextRef Context, value Name, + LLVMBasicBlockRef BB) { + return LLVMInsertBasicBlockInContext(Context, BB, String_val(Name)); +} + +/* llvalue -> bool */ +CAMLprim value llvm_value_is_block(LLVMValueRef Val) { + return Val_bool(LLVMValueIsBasicBlock(Val)); +} + +/*--... Operations on instructions .........................................--*/ + +DEFINE_ITERATORS(instr, Instruction, LLVMBasicBlockRef, LLVMValueRef, + LLVMGetInstructionParent) + +/* llvalue -> Opcode.t */ +CAMLprim value llvm_instr_get_opcode(LLVMValueRef Inst) { + LLVMOpcode o; + if (!LLVMIsAInstruction(Inst)) + failwith("Not an instruction"); + o = LLVMGetInstructionOpcode(Inst); + assert (o <= LLVMLandingPad); + return Val_int(o); +} + +/* llvalue -> ICmp.t option */ +CAMLprim value llvm_instr_icmp_predicate(LLVMValueRef Val) { + CAMLparam0(); + int x = LLVMGetICmpPredicate(Val); + if (x) { + value Option = alloc(1, 0); + Field(Option, 0) = Val_int(x - LLVMIntEQ); + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + + +/*--... Operations on call sites ...........................................--*/ + +/* llvalue -> int */ +CAMLprim value llvm_instruction_call_conv(LLVMValueRef Inst) { + return Val_int(LLVMGetInstructionCallConv(Inst)); +} + +/* int -> llvalue -> unit */ +CAMLprim value llvm_set_instruction_call_conv(value CC, LLVMValueRef Inst) { + LLVMSetInstructionCallConv(Inst, Int_val(CC)); + return Val_unit; +} + +/* llvalue -> int -> int32 -> unit */ +CAMLprim value llvm_add_instruction_param_attr(LLVMValueRef Instr, + value index, + value PA) { + LLVMAddInstrAttribute(Instr, Int_val(index), Int32_val(PA)); + return Val_unit; +} + +/* llvalue -> int -> int32 -> unit */ +CAMLprim value llvm_remove_instruction_param_attr(LLVMValueRef Instr, + value index, + value PA) { + LLVMRemoveInstrAttribute(Instr, Int_val(index), Int32_val(PA)); + return Val_unit; +} + +/*--... Operations on call instructions (only) .............................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_tail_call(LLVMValueRef CallInst) { + return Val_bool(LLVMIsTailCall(CallInst)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_tail_call(value IsTailCall, + LLVMValueRef CallInst) { + LLVMSetTailCall(CallInst, Bool_val(IsTailCall)); + return Val_unit; +} + +/*--... Operations on load/store instructions (only)........................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_volatile(LLVMValueRef MemoryInst) { + return Val_bool(LLVMGetVolatile(MemoryInst)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_volatile(value IsVolatile, + LLVMValueRef MemoryInst) { + LLVMSetVolatile(MemoryInst, Bool_val(IsVolatile)); + return Val_unit; +} + +/*--... Operations on phi nodes ............................................--*/ + +/* (llvalue * llbasicblock) -> llvalue -> unit */ +CAMLprim value llvm_add_incoming(value Incoming, LLVMValueRef PhiNode) { + LLVMAddIncoming(PhiNode, + (LLVMValueRef*) &Field(Incoming, 0), + (LLVMBasicBlockRef*) &Field(Incoming, 1), + 1); + return Val_unit; +} + +/* llvalue -> (llvalue * llbasicblock) list */ +CAMLprim value llvm_incoming(LLVMValueRef PhiNode) { + unsigned I; + CAMLparam0(); + CAMLlocal3(Hd, Tl, Tmp); + + /* Build a tuple list of them. */ + Tl = Val_int(0); + for (I = LLVMCountIncoming(PhiNode); I != 0; ) { + Hd = alloc(2, 0); + Store_field(Hd, 0, (value) LLVMGetIncomingValue(PhiNode, --I)); + Store_field(Hd, 1, (value) LLVMGetIncomingBlock(PhiNode, I)); + + Tmp = alloc(2, 0); + Store_field(Tmp, 0, Hd); + Store_field(Tmp, 1, Tl); + Tl = Tmp; + } + + CAMLreturn(Tl); +} + +/* llvalue -> unit */ +CAMLprim value llvm_delete_instruction(LLVMValueRef Instruction) { + LLVMInstructionEraseFromParent(Instruction); + return Val_unit; +} + +/*===-- Instruction builders ----------------------------------------------===*/ + +#define Builder_val(v) (*(LLVMBuilderRef *)(Data_custom_val(v))) + +static void llvm_finalize_builder(value B) { + LLVMDisposeBuilder(Builder_val(B)); +} + +static struct custom_operations builder_ops = { + (char *) "LLVMIRBuilder", + llvm_finalize_builder, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +static value alloc_builder(LLVMBuilderRef B) { + value V = alloc_custom(&builder_ops, sizeof(LLVMBuilderRef), 0, 1); + Builder_val(V) = B; + return V; +} + +/* llcontext -> llbuilder */ +CAMLprim value llvm_builder(LLVMContextRef C) { + return alloc_builder(LLVMCreateBuilderInContext(C)); +} + +/* (llbasicblock, llvalue) llpos -> llbuilder -> unit */ +CAMLprim value llvm_position_builder(value Pos, value B) { + if (Tag_val(Pos) == 0) { + LLVMBasicBlockRef BB = (LLVMBasicBlockRef) Op_val(Field(Pos, 0)); + LLVMPositionBuilderAtEnd(Builder_val(B), BB); + } else { + LLVMValueRef I = (LLVMValueRef) Op_val(Field(Pos, 0)); + LLVMPositionBuilderBefore(Builder_val(B), I); + } + return Val_unit; +} + +/* llbuilder -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_insertion_block(value B) { + LLVMBasicBlockRef InsertBlock = LLVMGetInsertBlock(Builder_val(B)); + if (!InsertBlock) + raise_not_found(); + return InsertBlock; +} + +/* llvalue -> string -> llbuilder -> unit */ +CAMLprim value llvm_insert_into_builder(LLVMValueRef I, value Name, value B) { + LLVMInsertIntoBuilderWithName(Builder_val(B), I, String_val(Name)); + return Val_unit; +} + +/*--... Metadata ...........................................................--*/ + +/* llbuilder -> llvalue -> unit */ +CAMLprim value llvm_set_current_debug_location(value B, LLVMValueRef V) { + LLVMSetCurrentDebugLocation(Builder_val(B), V); + return Val_unit; +} + +/* llbuilder -> unit */ +CAMLprim value llvm_clear_current_debug_location(value B) { + LLVMSetCurrentDebugLocation(Builder_val(B), NULL); + return Val_unit; +} + +/* llbuilder -> llvalue option */ +CAMLprim value llvm_current_debug_location(value B) { + CAMLparam0(); + LLVMValueRef L; + if ((L = LLVMGetCurrentDebugLocation(Builder_val(B)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) L; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llbuilder -> llvalue -> unit */ +CAMLprim value llvm_set_inst_debug_location(value B, LLVMValueRef V) { + LLVMSetInstDebugLocation(Builder_val(B), V); + return Val_unit; +} + + +/*--... Terminators ........................................................--*/ + +/* llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ret_void(value B) { + return LLVMBuildRetVoid(Builder_val(B)); +} + +/* llvalue -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ret(LLVMValueRef Val, value B) { + return LLVMBuildRet(Builder_val(B), Val); +} + +/* llvalue array -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_aggregate_ret(value RetVals, value B) { + return LLVMBuildAggregateRet(Builder_val(B), (LLVMValueRef *) Op_val(RetVals), + Wosize_val(RetVals)); +} + +/* llbasicblock -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_br(LLVMBasicBlockRef BB, value B) { + return LLVMBuildBr(Builder_val(B), BB); +} + +/* llvalue -> llbasicblock -> llbasicblock -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_cond_br(LLVMValueRef If, + LLVMBasicBlockRef Then, + LLVMBasicBlockRef Else, + value B) { + return LLVMBuildCondBr(Builder_val(B), If, Then, Else); +} + +/* llvalue -> llbasicblock -> int -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_switch(LLVMValueRef Of, + LLVMBasicBlockRef Else, + value EstimatedCount, + value B) { + return LLVMBuildSwitch(Builder_val(B), Of, Else, Int_val(EstimatedCount)); +} + +/* lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_malloc(LLVMTypeRef Ty, value Name, + value B) +{ + return LLVMBuildMalloc(Builder_val(B), Ty, String_val(Name)); +} + +/* lltype -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_array_malloc(LLVMTypeRef Ty, + LLVMValueRef Val, + value Name, value B) +{ + return LLVMBuildArrayMalloc(Builder_val(B), Ty, Val, String_val(Name)); +} + +/* llvalue -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_free(LLVMValueRef P, value B) +{ + return LLVMBuildFree(Builder_val(B), P); +} + +/* llvalue -> llvalue -> llbasicblock -> unit */ +CAMLprim value llvm_add_case(LLVMValueRef Switch, LLVMValueRef OnVal, + LLVMBasicBlockRef Dest) { + LLVMAddCase(Switch, OnVal, Dest); + return Val_unit; +} + +/* llvalue -> llbasicblock -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_indirect_br(LLVMValueRef Addr, + value EstimatedDests, + value B) { + return LLVMBuildIndirectBr(Builder_val(B), Addr, EstimatedDests); +} + +/* llvalue -> llvalue -> llbasicblock -> unit */ +CAMLprim value llvm_add_destination(LLVMValueRef IndirectBr, + LLVMBasicBlockRef Dest) { + LLVMAddDestination(IndirectBr, Dest); + return Val_unit; +} + +/* llvalue -> llvalue array -> llbasicblock -> llbasicblock -> string -> + llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_invoke_nat(LLVMValueRef Fn, value Args, + LLVMBasicBlockRef Then, + LLVMBasicBlockRef Catch, + value Name, value B) { + return LLVMBuildInvoke(Builder_val(B), Fn, (LLVMValueRef *) Op_val(Args), + Wosize_val(Args), Then, Catch, String_val(Name)); +} + +/* llvalue -> llvalue array -> llbasicblock -> llbasicblock -> string -> + llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_invoke_bc(value Args[], int NumArgs) { + return llvm_build_invoke_nat((LLVMValueRef) Args[0], Args[1], + (LLVMBasicBlockRef) Args[2], + (LLVMBasicBlockRef) Args[3], + Args[4], Args[5]); +} + +/* lltype -> llvalue -> int -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_landingpad(LLVMTypeRef Ty, LLVMValueRef PersFn, + value NumClauses, value Name, + value B) { + return LLVMBuildLandingPad(Builder_val(B), Ty, PersFn, Int_val(NumClauses), + String_val(Name)); +} + +/* llvalue -> llvalue -> unit */ +CAMLprim value llvm_add_clause(LLVMValueRef LandingPadInst, LLVMValueRef ClauseVal) +{ + LLVMAddClause(LandingPadInst, ClauseVal); + return Val_unit; +} + + +/* llvalue -> bool -> unit */ +CAMLprim value llvm_set_cleanup(LLVMValueRef LandingPadInst, value flag) +{ + LLVMSetCleanup(LandingPadInst, Bool_val(flag)); + return Val_unit; +} + +/* llvalue -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_resume(LLVMValueRef Exn, value B) +{ + return LLVMBuildResume(Builder_val(B), Exn); +} + +/* llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_unreachable(value B) { + return LLVMBuildUnreachable(Builder_val(B)); +} + +/*--... Arithmetic .........................................................--*/ + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_add(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_add(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_add(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fadd(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fsub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fmul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_udiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildUDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sdiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildSDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_exact_sdiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildExactSDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fdiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_urem(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildURem(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_srem(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildSRem(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_frem(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFRem(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_shl(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildShl(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_lshr(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildLShr(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ashr(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildAShr(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_and(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildAnd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_or(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildOr(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_xor(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildXor(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNSWNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNUWNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fneg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildFNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_not(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNot(Builder_val(B), X, String_val(Name)); +} + +/*--... Memory .............................................................--*/ + +/* lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_alloca(LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildAlloca(Builder_val(B), Ty, String_val(Name)); +} + +/* lltype -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_array_alloca(LLVMTypeRef Ty, LLVMValueRef Size, + value Name, value B) { + return LLVMBuildArrayAlloca(Builder_val(B), Ty, Size, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_load(LLVMValueRef Pointer, + value Name, value B) { + return LLVMBuildLoad(Builder_val(B), Pointer, String_val(Name)); +} + +/* llvalue -> llvalue -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_store(LLVMValueRef Value, LLVMValueRef Pointer, + value B) { + return LLVMBuildStore(Builder_val(B), Value, Pointer); +} + +/* AtomicRMWBinOp.t -> llvalue -> llvalue -> AtomicOrdering.t -> + bool -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_atomicrmw_native(value BinOp, LLVMValueRef Ptr, + LLVMValueRef Val, value Ord, + value ST, value Name, value B) { + LLVMValueRef Instr; + Instr = LLVMBuildAtomicRMW(Builder_val(B), Int_val(BinOp), + Ptr, Val, Int_val(Ord), Bool_val(ST)); + LLVMSetValueName(Instr, String_val(Name)); + return Instr; +} + +CAMLprim LLVMValueRef llvm_build_atomicrmw_bytecode(value *argv, int argn) { + return llvm_build_atomicrmw_native(argv[0], (LLVMValueRef) argv[1], + (LLVMValueRef) argv[2], argv[3], + argv[4], argv[5], argv[6]); +} + +/* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_gep(LLVMValueRef Pointer, value Indices, + value Name, value B) { + return LLVMBuildGEP(Builder_val(B), Pointer, + (LLVMValueRef *) Op_val(Indices), Wosize_val(Indices), + String_val(Name)); +} + +/* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_in_bounds_gep(LLVMValueRef Pointer, + value Indices, value Name, + value B) { + return LLVMBuildInBoundsGEP(Builder_val(B), Pointer, + (LLVMValueRef *) Op_val(Indices), + Wosize_val(Indices), String_val(Name)); +} + +/* llvalue -> int -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_struct_gep(LLVMValueRef Pointer, + value Index, value Name, + value B) { + return LLVMBuildStructGEP(Builder_val(B), Pointer, + Int_val(Index), String_val(Name)); +} + +/* string -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_global_string(value Str, value Name, value B) { + return LLVMBuildGlobalString(Builder_val(B), String_val(Str), + String_val(Name)); +} + +/* string -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_global_stringptr(value Str, value Name, + value B) { + return LLVMBuildGlobalStringPtr(Builder_val(B), String_val(Str), + String_val(Name)); +} + +/*--... Casts ..............................................................--*/ + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_trunc(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildTrunc(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_zext(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildZExt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sext(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildSExt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fptoui(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPToUI(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fptosi(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPToSI(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_uitofp(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildUIToFP(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sitofp(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildSIToFP(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fptrunc(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPTrunc(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fpext(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPExt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_prttoint(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildPtrToInt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_inttoptr(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildIntToPtr(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_bitcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_zext_or_bitcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildZExtOrBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sext_or_bitcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildSExtOrBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_trunc_or_bitcast(LLVMValueRef X, + LLVMTypeRef Ty, value Name, + value B) { + return LLVMBuildTruncOrBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_pointercast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildPointerCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_intcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildIntCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fpcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/*--... Comparisons ........................................................--*/ + +/* Icmp.t -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_icmp(value Pred, + LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildICmp(Builder_val(B), Int_val(Pred) + LLVMIntEQ, LHS, RHS, + String_val(Name)); +} + +/* Fcmp.t -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fcmp(value Pred, + LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFCmp(Builder_val(B), Int_val(Pred), LHS, RHS, + String_val(Name)); +} + +/*--... Miscellaneous instructions .........................................--*/ + +/* (llvalue * llbasicblock) list -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) { + value Hd, Tl; + LLVMValueRef FirstValue, PhiNode; + + assert(Incoming != Val_int(0) && "Empty list passed to Llvm.build_phi!"); + + Hd = Field(Incoming, 0); + FirstValue = (LLVMValueRef) Field(Hd, 0); + PhiNode = LLVMBuildPhi(Builder_val(B), LLVMTypeOf(FirstValue), + String_val(Name)); + + for (Tl = Incoming; Tl != Val_int(0); Tl = Field(Tl, 1)) { + value Hd = Field(Tl, 0); + LLVMAddIncoming(PhiNode, (LLVMValueRef*) &Field(Hd, 0), + (LLVMBasicBlockRef*) &Field(Hd, 1), 1); + } + + return PhiNode; +} + +/* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_call(LLVMValueRef Fn, value Params, + value Name, value B) { + return LLVMBuildCall(Builder_val(B), Fn, (LLVMValueRef *) Op_val(Params), + Wosize_val(Params), String_val(Name)); +} + +/* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_select(LLVMValueRef If, + LLVMValueRef Then, LLVMValueRef Else, + value Name, value B) { + return LLVMBuildSelect(Builder_val(B), If, Then, Else, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_va_arg(LLVMValueRef List, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildVAArg(Builder_val(B), List, Ty, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_extractelement(LLVMValueRef Vec, + LLVMValueRef Idx, + value Name, value B) { + return LLVMBuildExtractElement(Builder_val(B), Vec, Idx, String_val(Name)); +} + +/* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_insertelement(LLVMValueRef Vec, + LLVMValueRef Element, + LLVMValueRef Idx, + value Name, value B) { + return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx, + String_val(Name)); +} + +/* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_shufflevector(LLVMValueRef V1, LLVMValueRef V2, + LLVMValueRef Mask, + value Name, value B) { + return LLVMBuildShuffleVector(Builder_val(B), V1, V2, Mask, String_val(Name)); +} + +/* llvalue -> int -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_extractvalue(LLVMValueRef Aggregate, + value Idx, value Name, value B) { + return LLVMBuildExtractValue(Builder_val(B), Aggregate, Int_val(Idx), + String_val(Name)); +} + +/* llvalue -> llvalue -> int -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_insertvalue(LLVMValueRef Aggregate, + LLVMValueRef Val, value Idx, + value Name, value B) { + return LLVMBuildInsertValue(Builder_val(B), Aggregate, Val, Int_val(Idx), + String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_is_null(LLVMValueRef Val, value Name, + value B) { + return LLVMBuildIsNull(Builder_val(B), Val, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_is_not_null(LLVMValueRef Val, value Name, + value B) { + return LLVMBuildIsNotNull(Builder_val(B), Val, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ptrdiff(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildPtrDiff(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/*===-- Memory buffers ----------------------------------------------------===*/ + +/* string -> llmemorybuffer + raises IoError msg on error */ +CAMLprim value llvm_memorybuffer_of_file(value Path) { + CAMLparam1(Path); + char *Message; + LLVMMemoryBufferRef MemBuf; + + if (LLVMCreateMemoryBufferWithContentsOfFile(String_val(Path), + &MemBuf, &Message)) + llvm_raise(llvm_ioerror_exn, Message); + + CAMLreturn((value) MemBuf); +} + +/* unit -> llmemorybuffer + raises IoError msg on error */ +CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) { + char *Message; + LLVMMemoryBufferRef MemBuf; + + if (LLVMCreateMemoryBufferWithSTDIN(&MemBuf, &Message)) + llvm_raise(llvm_ioerror_exn, Message); + + return MemBuf; +} + +/* ?name:string -> string -> llmemorybuffer */ +CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_string(value Name, value String) { + const char *NameCStr; + if(Name == Val_int(0)) + NameCStr = ""; + else + NameCStr = String_val(Field(Name, 0)); + + LLVMMemoryBufferRef MemBuf; + MemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy( + String_val(String), caml_string_length(String), NameCStr); + + return MemBuf; +} + +/* llmemorybuffer -> string */ +CAMLprim value llvm_memorybuffer_as_string(LLVMMemoryBufferRef MemBuf) { + value String = caml_alloc_string(LLVMGetBufferSize(MemBuf)); + memcpy(String_val(String), LLVMGetBufferStart(MemBuf), + LLVMGetBufferSize(MemBuf)); + + return String; +} + +/* llmemorybuffer -> unit */ +CAMLprim value llvm_memorybuffer_dispose(LLVMMemoryBufferRef MemBuf) { + LLVMDisposeMemoryBuffer(MemBuf); + return Val_unit; +} + +/*===-- Pass Managers -----------------------------------------------------===*/ + +/* unit -> [ `Module ] PassManager.t */ +CAMLprim LLVMPassManagerRef llvm_passmanager_create(value Unit) { + return LLVMCreatePassManager(); +} + +/* llmodule -> [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_run_module(LLVMModuleRef M, + LLVMPassManagerRef PM) { + return Val_bool(LLVMRunPassManager(PM, M)); +} + +/* [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_initialize(LLVMPassManagerRef FPM) { + return Val_bool(LLVMInitializeFunctionPassManager(FPM)); +} + +/* llvalue -> [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_run_function(LLVMValueRef F, + LLVMPassManagerRef FPM) { + return Val_bool(LLVMRunFunctionPassManager(FPM, F)); +} + +/* [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_finalize(LLVMPassManagerRef FPM) { + return Val_bool(LLVMFinalizeFunctionPassManager(FPM)); +} + +/* PassManager.any PassManager.t -> unit */ +CAMLprim value llvm_passmanager_dispose(LLVMPassManagerRef PM) { + LLVMDisposePassManager(PM); + return Val_unit; +} diff --git a/bindings/ocaml/target/Makefile b/bindings/ocaml/target/Makefile new file mode 100644 index 00000000..3c48cd8f --- /dev/null +++ b/bindings/ocaml/target/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/target/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_target interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_target +UsedComponents := target +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/target/llvm_target.ml b/bindings/ocaml/target/llvm_target.ml new file mode 100644 index 00000000..974bd49c --- /dev/null +++ b/bindings/ocaml/target/llvm_target.ml @@ -0,0 +1,138 @@ +(*===-- llvm_target.ml - LLVM OCaml Interface ------------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +module Endian = struct + type t = + | Big + | Little +end + +module CodeGenOptLevel = struct + type t = + | None + | Less + | Default + | Aggressive +end + +module RelocMode = struct + type t = + | Default + | Static + | PIC + | DynamicNoPIC +end + +module CodeModel = struct + type t = + | Default + | JITDefault + | Small + | Kernel + | Medium + | Large +end + +module CodeGenFileType = struct + type t = + | AssemblyFile + | ObjectFile +end + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_target_exns" +let _ = register_exns (Error "") + +module DataLayout = struct + type t + + external of_string : string -> t = "llvm_datalayout_of_string" + external as_string : t -> string = "llvm_datalayout_as_string" + external add_to_pass_manager : [ t -> unit + = "llvm_datalayout_add_to_pass_manager" + external byte_order : t -> Endian.t = "llvm_datalayout_byte_order" + external pointer_size : t -> int = "llvm_datalayout_pointer_size" + external intptr_type : Llvm.llcontext -> t -> Llvm.lltype + = "llvm_datalayout_intptr_type" + external qualified_pointer_size : int -> t -> int + = "llvm_datalayout_qualified_pointer_size" + external qualified_intptr_type : Llvm.llcontext -> int -> t -> Llvm.lltype + = "llvm_datalayout_qualified_intptr_type" + external size_in_bits : Llvm.lltype -> t -> Int64.t + = "llvm_datalayout_size_in_bits" + external store_size : Llvm.lltype -> t -> Int64.t + = "llvm_datalayout_store_size" + external abi_size : Llvm.lltype -> t -> Int64.t + = "llvm_datalayout_abi_size" + external abi_align : Llvm.lltype -> t -> int + = "llvm_datalayout_abi_align" + external stack_align : Llvm.lltype -> t -> int + = "llvm_datalayout_stack_align" + external preferred_align : Llvm.lltype -> t -> int + = "llvm_datalayout_preferred_align" + external preferred_align_of_global : Llvm.llvalue -> t -> int + = "llvm_datalayout_preferred_align_of_global" + external element_at_offset : Llvm.lltype -> Int64.t -> t -> int + = "llvm_datalayout_element_at_offset" + external offset_of_element : Llvm.lltype -> int -> t -> Int64.t + = "llvm_datalayout_offset_of_element" +end + +module Target = struct + type t + + external default_triple : unit -> string = "llvm_target_default_triple" + external first : unit -> t option = "llvm_target_first" + external succ : t -> t option = "llvm_target_succ" + external by_name : string -> t option = "llvm_target_by_name" + external by_triple : string -> t = "llvm_target_by_triple" + external name : t -> string = "llvm_target_name" + external description : t -> string = "llvm_target_description" + external has_jit : t -> bool = "llvm_target_has_jit" + external has_target_machine : t -> bool = "llvm_target_has_target_machine" + external has_asm_backend : t -> bool = "llvm_target_has_asm_backend" + + let all () = + let rec step elem lst = + match elem with + | Some target -> step (succ target) (target :: lst) + | None -> lst + in + step (first ()) [] +end + +module TargetMachine = struct + type t + + external create : triple:string -> ?cpu:string -> ?features:string -> + ?level:CodeGenOptLevel.t -> ?reloc_mode:RelocMode.t -> + ?code_model:CodeModel.t -> Target.t -> t + = "llvm_create_targetmachine_bytecode" + "llvm_create_targetmachine_native" + external target : t -> Target.t + = "llvm_targetmachine_target" + external triple : t -> string + = "llvm_targetmachine_triple" + external cpu : t -> string + = "llvm_targetmachine_cpu" + external features : t -> string + = "llvm_targetmachine_features" + external data_layout : t -> DataLayout.t + = "llvm_targetmachine_data_layout" + external set_verbose_asm : bool -> t -> unit + = "llvm_targetmachine_set_verbose_asm" + external emit_to_file : Llvm.llmodule -> CodeGenFileType.t -> string -> + t -> unit + = "llvm_targetmachine_emit_to_file" + external emit_to_memory_buffer : Llvm.llmodule -> CodeGenFileType.t -> + t -> Llvm.llmemorybuffer + = "llvm_targetmachine_emit_to_memory_buffer" +end diff --git a/bindings/ocaml/target/llvm_target.mli b/bindings/ocaml/target/llvm_target.mli new file mode 100644 index 00000000..4f5e7171 --- /dev/null +++ b/bindings/ocaml/target/llvm_target.mli @@ -0,0 +1,222 @@ +(*===-- llvm_target.mli - LLVM OCaml Interface -----------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Target Information. + + This interface provides an OCaml API for LLVM target information, + the classes in the Target library. *) + +module Endian : sig + type t = + | Big + | Little +end + +module CodeGenOptLevel : sig + type t = + | None + | Less + | Default + | Aggressive +end + +module RelocMode : sig + type t = + | Default + | Static + | PIC + | DynamicNoPIC +end + +module CodeModel : sig + type t = + | Default + | JITDefault + | Small + | Kernel + | Medium + | Large +end + +module CodeGenFileType : sig + type t = + | AssemblyFile + | ObjectFile +end + +(** {6 Exceptions} *) + +exception Error of string + +(** {6 Data Layout} *) + +module DataLayout : sig + type t + + (** [of_string rep] parses the data layout string representation [rep]. + See the constructor [llvm::DataLayout::DataLayout]. *) + val of_string : string -> t + + (** [as_string dl] is the string representation of the data layout [dl]. + See the method [llvm::DataLayout::getStringRepresentation]. *) + val as_string : t -> string + + (** [add_to_pass_manager dl pm] adds the target data [dl] to + the pass manager [pm]. + See the method [llvm::PassManagerBase::add]. *) + val add_to_pass_manager : [ + t -> unit + + (** Returns the byte order of a target, either [Endian.Big] or + [Endian.Little]. + See the method [llvm::DataLayout::isLittleEndian]. *) + val byte_order : t -> Endian.t + + (** Returns the pointer size in bytes for a target. + See the method [llvm::DataLayout::getPointerSize]. *) + val pointer_size : t -> int + + (** Returns the integer type that is the same size as a pointer on a target. + See the method [llvm::DataLayout::getIntPtrType]. *) + val intptr_type : Llvm.llcontext -> t -> Llvm.lltype + + (** Returns the pointer size in bytes for a target in a given address space. + See the method [llvm::DataLayout::getPointerSize]. *) + val qualified_pointer_size : int -> t -> int + + (** Returns the integer type that is the same size as a pointer on a target + in a given address space. + See the method [llvm::DataLayout::getIntPtrType]. *) + val qualified_intptr_type : Llvm.llcontext -> int -> t -> Llvm.lltype + + (** Computes the size of a type in bits for a target. + See the method [llvm::DataLayout::getTypeSizeInBits]. *) + val size_in_bits : Llvm.lltype -> t -> Int64.t + + (** Computes the storage size of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeStoreSize]. *) + val store_size : Llvm.lltype -> t -> Int64.t + + (** Computes the ABI size of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeAllocSize]. *) + val abi_size : Llvm.lltype -> t -> Int64.t + + (** Computes the ABI alignment of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeABISize]. *) + val abi_align : Llvm.lltype -> t -> int + + (** Computes the call frame alignment of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeABISize]. *) + val stack_align : Llvm.lltype -> t -> int + + (** Computes the preferred alignment of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeABISize]. *) + val preferred_align : Llvm.lltype -> t -> int + + (** Computes the preferred alignment of a global variable in bytes for + a target. See the method [llvm::DataLayout::getPreferredAlignment]. *) + val preferred_align_of_global : Llvm.llvalue -> t -> int + + (** Computes the structure element that contains the byte offset for a target. + See the method [llvm::StructLayout::getElementContainingOffset]. *) + val element_at_offset : Llvm.lltype -> Int64.t -> t -> int + + (** Computes the byte offset of the indexed struct element for a target. + See the method [llvm::StructLayout::getElementContainingOffset]. *) + val offset_of_element : Llvm.lltype -> int -> t -> Int64.t +end + +(** {6 Target} *) + +module Target : sig + type t + + (** [default_triple ()] returns the default target triple for current + platform. *) + val default_triple : unit -> string + + (** [first ()] returns the first target in the registered targets + list, or [None]. *) + val first : unit -> t option + + (** [succ t] returns the next target after [t], or [None] + if [t] was the last target. *) + val succ : t -> t option + + (** [all ()] returns a list of known targets. *) + val all : unit -> t list + + (** [by_name name] returns [Some t] if a target [t] named [name] is + registered, or [None] otherwise. *) + val by_name : string -> t option + + (** [by_triple triple] returns a target for a triple [triple], or raises + [Error] if [triple] does not correspond to a registered target. *) + val by_triple : string -> t + + (** Returns the name of a target. See [llvm::Target::getName]. *) + val name : t -> string + + (** Returns the description of a target. + See [llvm::Target::getDescription]. *) + val description : t -> string + + (** Returns [true] if the target has a JIT. *) + val has_jit : t -> bool + + (** Returns [true] if the target has a target machine associated. *) + val has_target_machine : t -> bool + + (** Returns [true] if the target has an ASM backend (required for + emitting output). *) + val has_asm_backend : t -> bool +end + +(** {6 Target Machine} *) + +module TargetMachine : sig + type t + + (** Creates a new target machine. + See [llvm::Target::createTargetMachine]. *) + val create : triple:string -> ?cpu:string -> ?features:string -> + ?level:CodeGenOptLevel.t -> ?reloc_mode:RelocMode.t -> + ?code_model:CodeModel.t -> Target.t -> t + + (** Returns the Target used in a TargetMachine *) + val target : t -> Target.t + + (** Returns the triple used while creating this target machine. See + [llvm::TargetMachine::getTriple]. *) + val triple : t -> string + + (** Returns the CPU used while creating this target machine. See + [llvm::TargetMachine::getCPU]. *) + val cpu : t -> string + + (** Returns the feature string used while creating this target machine. See + [llvm::TargetMachine::getFeatureString]. *) + val features : t -> string + + (** Returns the data layout of this target machine. *) + val data_layout : t -> DataLayout.t + + (** Sets the assembly verbosity of this target machine. + See [llvm::TargetMachine::setAsmVerbosity]. *) + val set_verbose_asm : bool -> t -> unit + + (** Emits assembly or object data for the given module to the given + file or raise [Error]. *) + val emit_to_file : Llvm.llmodule -> CodeGenFileType.t -> string -> t -> unit + + (** Emits assembly or object data for the given module to a fresh memory + buffer or raise [Error]. *) + val emit_to_memory_buffer : Llvm.llmodule -> CodeGenFileType.t -> t -> + Llvm.llmemorybuffer +end diff --git a/bindings/ocaml/target/target_ocaml.c b/bindings/ocaml/target/target_ocaml.c new file mode 100644 index 00000000..9e8778aa --- /dev/null +++ b/bindings/ocaml/target/target_ocaml.c @@ -0,0 +1,390 @@ +/*===-- target_ocaml.c - LLVM OCaml Glue ------------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/custom.h" + +/*===---- Exceptions ------------------------------------------------------===*/ + +static value llvm_target_error_exn; + +CAMLprim value llvm_register_target_exns(value Error) { + llvm_target_error_exn = Field(Error, 0); + register_global_root(&llvm_target_error_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + +static value llvm_string_of_message(char* Message) { + value String = caml_copy_string(Message); + LLVMDisposeMessage(Message); + + return String; +} + +/*===---- Data Layout -----------------------------------------------------===*/ + +#define DataLayout_val(v) (*(LLVMTargetDataRef *)(Data_custom_val(v))) + +static void llvm_finalize_data_layout(value DataLayout) { + LLVMDisposeTargetData(DataLayout_val(DataLayout)); +} + +static struct custom_operations llvm_data_layout_ops = { + (char *) "LLVMDataLayout", + llvm_finalize_data_layout, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +value llvm_alloc_data_layout(LLVMTargetDataRef DataLayout) { + value V = alloc_custom(&llvm_data_layout_ops, sizeof(LLVMTargetDataRef), + 0, 1); + DataLayout_val(V) = DataLayout; + return V; +} + +/* string -> DataLayout.t */ +CAMLprim value llvm_datalayout_of_string(value StringRep) { + return llvm_alloc_data_layout(LLVMCreateTargetData(String_val(StringRep))); +} + +/* DataLayout.t -> string */ +CAMLprim value llvm_datalayout_as_string(value TD) { + char *StringRep = LLVMCopyStringRepOfTargetData(DataLayout_val(TD)); + value Copy = copy_string(StringRep); + LLVMDisposeMessage(StringRep); + return Copy; +} + +/* [ DataLayout.t -> unit */ +CAMLprim value llvm_datalayout_add_to_pass_manager(LLVMPassManagerRef PM, + value DL) { + LLVMAddTargetData(DataLayout_val(DL), PM); + return Val_unit; +} + +/* DataLayout.t -> Endian.t */ +CAMLprim value llvm_datalayout_byte_order(value DL) { + return Val_int(LLVMByteOrder(DataLayout_val(DL))); +} + +/* DataLayout.t -> int */ +CAMLprim value llvm_datalayout_pointer_size(value DL) { + return Val_int(LLVMPointerSize(DataLayout_val(DL))); +} + +/* Llvm.llcontext -> DataLayout.t -> Llvm.lltype */ +CAMLprim LLVMTypeRef llvm_datalayout_intptr_type(LLVMContextRef C, value DL) { + return LLVMIntPtrTypeInContext(C, DataLayout_val(DL));; +} + +/* int -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_qualified_pointer_size(value AS, value DL) { + return Val_int(LLVMPointerSizeForAS(DataLayout_val(DL), Int_val(AS))); +} + +/* Llvm.llcontext -> int -> DataLayout.t -> Llvm.lltype */ +CAMLprim LLVMTypeRef llvm_datalayout_qualified_intptr_type(LLVMContextRef C, + value AS, + value DL) { + return LLVMIntPtrTypeForASInContext(C, DataLayout_val(DL), Int_val(AS)); +} + +/* Llvm.lltype -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_size_in_bits(LLVMTypeRef Ty, value DL) { + return caml_copy_int64(LLVMSizeOfTypeInBits(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_store_size(LLVMTypeRef Ty, value DL) { + return caml_copy_int64(LLVMStoreSizeOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_abi_size(LLVMTypeRef Ty, value DL) { + return caml_copy_int64(LLVMABISizeOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_abi_align(LLVMTypeRef Ty, value DL) { + return Val_int(LLVMABIAlignmentOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_stack_align(LLVMTypeRef Ty, value DL) { + return Val_int(LLVMCallFrameAlignmentOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_preferred_align(LLVMTypeRef Ty, value DL) { + return Val_int(LLVMPreferredAlignmentOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.llvalue -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_preferred_align_of_global(LLVMValueRef GlobalVar, + value DL) { + return Val_int(LLVMPreferredAlignmentOfGlobal(DataLayout_val(DL), GlobalVar)); +} + +/* Llvm.lltype -> Int64.t -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_element_at_offset(LLVMTypeRef Ty, value Offset, + value DL) { + return Val_int(LLVMElementAtOffset(DataLayout_val(DL), Ty, + Int64_val(Offset))); +} + +/* Llvm.lltype -> int -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_offset_of_element(LLVMTypeRef Ty, value Index, + value DL) { + return caml_copy_int64(LLVMOffsetOfElement(DataLayout_val(DL), Ty, + Int_val(Index))); +} + +/*===---- Target ----------------------------------------------------------===*/ + +static value llvm_target_option(LLVMTargetRef Target) { + if(Target != NULL) { + value Result = caml_alloc_small(1, 0); + Store_field(Result, 0, (value) Target); + return Result; + } + + return Val_int(0); +} + +/* unit -> string */ +CAMLprim value llvm_target_default_triple(value Unit) { + char *TripleCStr = LLVMGetDefaultTargetTriple(); + value TripleStr = caml_copy_string(TripleCStr); + LLVMDisposeMessage(TripleCStr); + + return TripleStr; +} + +/* unit -> Target.t option */ +CAMLprim value llvm_target_first(value Unit) { + return llvm_target_option(LLVMGetFirstTarget()); +} + +/* Target.t -> Target.t option */ +CAMLprim value llvm_target_succ(LLVMTargetRef Target) { + return llvm_target_option(LLVMGetNextTarget(Target)); +} + +/* string -> Target.t option */ +CAMLprim value llvm_target_by_name(value Name) { + return llvm_target_option(LLVMGetTargetFromName(String_val(Name))); +} + +/* string -> Target.t */ +CAMLprim LLVMTargetRef llvm_target_by_triple(value Triple) { + LLVMTargetRef T; + char *Error; + + if(LLVMGetTargetFromTriple(String_val(Triple), &T, &Error)) + llvm_raise(llvm_target_error_exn, Error); + + return T; +} + +/* Target.t -> string */ +CAMLprim value llvm_target_name(LLVMTargetRef Target) { + return caml_copy_string(LLVMGetTargetName(Target)); +} + +/* Target.t -> string */ +CAMLprim value llvm_target_description(LLVMTargetRef Target) { + return caml_copy_string(LLVMGetTargetDescription(Target)); +} + +/* Target.t -> bool */ +CAMLprim value llvm_target_has_jit(LLVMTargetRef Target) { + return Val_bool(LLVMTargetHasJIT(Target)); +} + +/* Target.t -> bool */ +CAMLprim value llvm_target_has_target_machine(LLVMTargetRef Target) { + return Val_bool(LLVMTargetHasTargetMachine(Target)); +} + +/* Target.t -> bool */ +CAMLprim value llvm_target_has_asm_backend(LLVMTargetRef Target) { + return Val_bool(LLVMTargetHasAsmBackend(Target)); +} + +/*===---- Target Machine --------------------------------------------------===*/ + +#define TargetMachine_val(v) (*(LLVMTargetMachineRef *)(Data_custom_val(v))) + +static void llvm_finalize_target_machine(value Machine) { + LLVMDisposeTargetMachine(TargetMachine_val(Machine)); +} + +static struct custom_operations llvm_target_machine_ops = { + (char *) "LLVMTargetMachine", + llvm_finalize_target_machine, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +static value llvm_alloc_targetmachine(LLVMTargetMachineRef Machine) { + value V = alloc_custom(&llvm_target_machine_ops, sizeof(LLVMTargetMachineRef), + 0, 1); + TargetMachine_val(V) = Machine; + return V; +} + +/* triple:string -> ?cpu:string -> ?features:string + ?level:CodeGenOptLevel.t -> ?reloc_mode:RelocMode.t + ?code_model:CodeModel.t -> Target.t -> TargetMachine.t */ +CAMLprim value llvm_create_targetmachine_native(value Triple, value CPU, + value Features, value OptLevel, value RelocMode, + value CodeModel, LLVMTargetRef Target) { + LLVMTargetMachineRef Machine; + const char *CPUStr = "", *FeaturesStr = ""; + LLVMCodeGenOptLevel OptLevelEnum = LLVMCodeGenLevelDefault; + LLVMRelocMode RelocModeEnum = LLVMRelocDefault; + LLVMCodeModel CodeModelEnum = LLVMCodeModelDefault; + + if(CPU != Val_int(0)) + CPUStr = String_val(Field(CPU, 0)); + if(Features != Val_int(0)) + FeaturesStr = String_val(Field(Features, 0)); + if(OptLevel != Val_int(0)) + OptLevelEnum = Int_val(Field(OptLevel, 0)); + if(RelocMode != Val_int(0)) + RelocModeEnum = Int_val(Field(RelocMode, 0)); + if(CodeModel != Val_int(0)) + CodeModelEnum = Int_val(Field(CodeModel, 0)); + + Machine = LLVMCreateTargetMachine(Target, String_val(Triple), CPUStr, + FeaturesStr, OptLevelEnum, RelocModeEnum, CodeModelEnum); + + return llvm_alloc_targetmachine(Machine); +} + +CAMLprim value llvm_create_targetmachine_bytecode(value *argv, int argn) { + return llvm_create_targetmachine_native(argv[0], argv[1], argv[2], argv[3], + argv[4], argv[5], (LLVMTargetRef) argv[6]); +} + +/* TargetMachine.t -> Target.t */ +CAMLprim LLVMTargetRef llvm_targetmachine_target(value Machine) { + return LLVMGetTargetMachineTarget(TargetMachine_val(Machine)); +} + +/* TargetMachine.t -> string */ +CAMLprim value llvm_targetmachine_triple(value Machine) { + return llvm_string_of_message(LLVMGetTargetMachineTriple( + TargetMachine_val(Machine))); +} + +/* TargetMachine.t -> string */ +CAMLprim value llvm_targetmachine_cpu(value Machine) { + return llvm_string_of_message(LLVMGetTargetMachineCPU( + TargetMachine_val(Machine))); +} + +/* TargetMachine.t -> string */ +CAMLprim value llvm_targetmachine_features(value Machine) { + return llvm_string_of_message(LLVMGetTargetMachineFeatureString( + TargetMachine_val(Machine))); +} + +/* TargetMachine.t -> DataLayout.t */ +CAMLprim value llvm_targetmachine_data_layout(value Machine) { + CAMLparam1(Machine); + CAMLlocal1(DataLayout); + + /* LLVMGetTargetMachineData returns a pointer owned by the TargetMachine, + so it is impossible to wrap it with llvm_alloc_target_data, which assumes + that OCaml owns the pointer. */ + LLVMTargetDataRef OrigDataLayout; + OrigDataLayout = LLVMGetTargetMachineData(TargetMachine_val(Machine)); + + char* TargetDataCStr; + TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); + DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); + LLVMDisposeMessage(TargetDataCStr); + + CAMLreturn(DataLayout); +} + +/* TargetMachine.t -> bool -> unit */ +CAMLprim value llvm_targetmachine_set_verbose_asm(value Machine, value Verb) { + LLVMSetTargetMachineAsmVerbosity(TargetMachine_val(Machine), Bool_val(Verb)); + return Val_unit; +} + +/* Llvm.llmodule -> CodeGenFileType.t -> string -> TargetMachine.t -> unit */ +CAMLprim value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, + value FileType, value FileName, value Machine) { + char* ErrorMessage; + + if(LLVMTargetMachineEmitToFile(TargetMachine_val(Machine), Module, + String_val(FileName), Int_val(FileType), + &ErrorMessage)) { + llvm_raise(llvm_target_error_exn, ErrorMessage); + } + + return Val_unit; +} + +/* Llvm.llmodule -> CodeGenFileType.t -> TargetMachine.t -> + Llvm.llmemorybuffer */ +CAMLprim LLVMMemoryBufferRef llvm_targetmachine_emit_to_memory_buffer( + LLVMModuleRef Module, value FileType, + value Machine) { + char* ErrorMessage; + LLVMMemoryBufferRef Buffer; + + if(LLVMTargetMachineEmitToMemoryBuffer(TargetMachine_val(Machine), Module, + Int_val(FileType), &ErrorMessage, + &Buffer)) { + llvm_raise(llvm_target_error_exn, ErrorMessage); + } + + return Buffer; +} diff --git a/bindings/ocaml/transforms/Makefile b/bindings/ocaml/transforms/Makefile new file mode 100644 index 00000000..92c8396d --- /dev/null +++ b/bindings/ocaml/transforms/Makefile @@ -0,0 +1,18 @@ +##===- bindings/ocaml/transforms/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +DIRS = scalar ipo vectorize passmgr_builder + +ocamldoc: + $(Verb) for i in $(DIRS) ; do \ + $(MAKE) -C $$i ocamldoc; \ + done + +include $(LEVEL)/Makefile.common diff --git a/bindings/ocaml/transforms/ipo/Makefile b/bindings/ocaml/transforms/ipo/Makefile new file mode 100644 index 00000000..ed67a7cb --- /dev/null +++ b/bindings/ocaml/transforms/ipo/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_scalar_opts interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_ipo +UsedComponents := ipo +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/ipo/ipo_ocaml.c b/bindings/ocaml/transforms/ipo/ipo_ocaml.c new file mode 100644 index 00000000..4ad8afbc --- /dev/null +++ b/bindings/ocaml/transforms/ipo/ipo_ocaml.c @@ -0,0 +1,110 @@ +/*===-- ipo_ocaml.c - LLVM OCaml Glue ---------------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Transforms/IPO.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_argument_promotion(LLVMPassManagerRef PM) { + LLVMAddArgumentPromotionPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_constant_merge(LLVMPassManagerRef PM) { + LLVMAddConstantMergePass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_dead_arg_elimination(LLVMPassManagerRef PM) { + LLVMAddDeadArgEliminationPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_function_attrs(LLVMPassManagerRef PM) { + LLVMAddFunctionAttrsPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_function_inlining(LLVMPassManagerRef PM) { + LLVMAddFunctionInliningPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_always_inliner(LLVMPassManagerRef PM) { + LLVMAddAlwaysInlinerPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_always_inliner_pass(LLVMPassManagerRef PM) { + LLVMAddAlwaysInlinerPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_global_dce(LLVMPassManagerRef PM) { + LLVMAddGlobalDCEPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_global_optimizer(LLVMPassManagerRef PM) { + LLVMAddGlobalOptimizerPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_ipc_propagation(LLVMPassManagerRef PM) { + LLVMAddIPConstantPropagationPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_prune_eh(LLVMPassManagerRef PM) { + LLVMAddPruneEHPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_ipsccp(LLVMPassManagerRef PM) { + LLVMAddIPSCCPPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> bool -> unit */ +CAMLprim value llvm_add_internalize(LLVMPassManagerRef PM, value AllButMain) { + LLVMAddInternalizePass(PM, Bool_val(AllButMain)); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_strip_dead_prototypes(LLVMPassManagerRef PM) { + LLVMAddStripDeadPrototypesPass(PM); + return Val_unit; +} + +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_strip_symbols(LLVMPassManagerRef PM) { + LLVMAddStripSymbolsPass(PM); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.ml b/bindings/ocaml/transforms/ipo/llvm_ipo.ml new file mode 100644 index 00000000..93f564a1 --- /dev/null +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.ml @@ -0,0 +1,37 @@ +(*===-- llvm_ipo.ml - LLVM OCaml Interface --------------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_argument_promotion" +external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_constant_merge" +external add_dead_arg_elimination : + [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination" +external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_function_attrs" +external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_function_inlining" +external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_always_inliner" +external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_global_dce" +external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_global_optimizer" +external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_ipc_propagation" +external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_prune_eh" +external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_ipsccp" +external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit = + "llvm_add_internalize" +external add_strip_dead_prototypes : + [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes" +external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_strip_symbols" diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.mli b/bindings/ocaml/transforms/ipo/llvm_ipo.mli new file mode 100644 index 00000000..1944c30b --- /dev/null +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.mli @@ -0,0 +1,69 @@ +(*===-- llvm_ipo.mli - LLVM OCaml Interface -------------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** IPO Transforms. + + This interface provides an OCaml API for LLVM interprocedural optimizations, the + classes in the [LLVMIPO] library. *) + +(** See llvm::createAddArgumentPromotionPass *) +external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_argument_promotion" + +(** See llvm::createConstantMergePass function. *) +external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_constant_merge" + +(** See llvm::createDeadArgEliminationPass function. *) +external add_dead_arg_elimination : + [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination" + +(** See llvm::createFunctionAttrsPass function. *) +external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_function_attrs" + +(** See llvm::createFunctionInliningPass function. *) +external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_function_inlining" + +(** See llvm::createAlwaysInlinerPass function. *) +external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_always_inliner" + +(** See llvm::createGlobalDCEPass function. *) +external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_global_dce" + +(** See llvm::createGlobalOptimizerPass function. *) +external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_global_optimizer" + +(** See llvm::createIPConstantPropagationPass function. *) +external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_ipc_propagation" + +(** See llvm::createPruneEHPass function. *) +external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_prune_eh" + +(** See llvm::createIPSCCPPass function. *) +external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_ipsccp" + +(** See llvm::createInternalizePass function. *) +external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit = + "llvm_add_internalize" + +(** See llvm::createStripDeadPrototypesPass function. *) +external add_strip_dead_prototypes : + [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes" + +(** See llvm::createStripSymbolsPass function. *) +external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_strip_symbols" diff --git a/bindings/ocaml/transforms/passmgr_builder/Makefile b/bindings/ocaml/transforms/passmgr_builder/Makefile new file mode 100644 index 00000000..54099dbb --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/passmgr_builder/Makefile --*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_passmgr_builder interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_passmgr_builder +UsedComponents := ipo +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.ml b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.ml new file mode 100644 index 00000000..60df4461 --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.ml @@ -0,0 +1,32 @@ +(*===-- llvm_passmgr_builder.ml - LLVM OCaml Interface --------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +type t + +external create : unit -> t + = "llvm_pmbuilder_create" +external set_opt_level : int -> t -> unit + = "llvm_pmbuilder_set_opt_level" +external set_size_level : int -> t -> unit + = "llvm_pmbuilder_set_size_level" +external set_disable_unit_at_a_time : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unit_at_a_time" +external set_disable_unroll_loops : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unroll_loops" +external use_inliner_with_threshold : int -> t -> unit + = "llvm_pmbuilder_use_inliner_with_threshold" +external populate_function_pass_manager + : [ `Function ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_function_pass_manager" +external populate_module_pass_manager + : [ `Module ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_module_pass_manager" +external populate_lto_pass_manager + : [ `Module ] Llvm.PassManager.t -> internalize:bool -> run_inliner:bool -> t -> unit + = "llvm_pmbuilder_populate_lto_pass_manager" \ No newline at end of file diff --git a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli new file mode 100644 index 00000000..66b0981e --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli @@ -0,0 +1,54 @@ +(*===-- llvm_passmgr_builder.mli - LLVM OCaml Interface -------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Pass Manager Builder. + + This interface provides an OCaml API for LLVM pass manager builder + from the [LLVMCore] library. *) + +type t + +(** See [llvm::PassManagerBuilder]. *) +external create : unit -> t + = "llvm_pmbuilder_create" + +(** See [llvm::PassManagerBuilder::OptLevel]. *) +external set_opt_level : int -> t -> unit + = "llvm_pmbuilder_set_opt_level" + +(** See [llvm::PassManagerBuilder::SizeLevel]. *) +external set_size_level : int -> t -> unit + = "llvm_pmbuilder_set_size_level" + +(** See [llvm::PassManagerBuilder::DisableUnitAtATime]. *) +external set_disable_unit_at_a_time : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unit_at_a_time" + +(** See [llvm::PassManagerBuilder::DisableUnrollLoops]. *) +external set_disable_unroll_loops : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unroll_loops" + +(** See [llvm::PassManagerBuilder::Inliner]. *) +external use_inliner_with_threshold : int -> t -> unit + = "llvm_pmbuilder_use_inliner_with_threshold" + +(** See [llvm::PassManagerBuilder::populateFunctionPassManager]. *) +external populate_function_pass_manager + : [ `Function ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_function_pass_manager" + +(** See [llvm::PassManagerBuilder::populateModulePassManager]. *) +external populate_module_pass_manager + : [ `Module ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_module_pass_manager" + +(** See [llvm::PassManagerBuilder::populateLTOPassManager]. *) +external populate_lto_pass_manager + : [ `Module ] Llvm.PassManager.t -> internalize:bool -> run_inliner:bool -> t -> unit + = "llvm_pmbuilder_populate_lto_pass_manager" \ No newline at end of file diff --git a/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c new file mode 100644 index 00000000..a707856b --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c @@ -0,0 +1,113 @@ +/*===-- passmgr_builder_ocaml.c - LLVM OCaml Glue ---------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Transforms/PassManagerBuilder.h" +#include "caml/mlvalues.h" +#include "caml/custom.h" +#include "caml/misc.h" + +#define PMBuilder_val(v) (*(LLVMPassManagerBuilderRef *)(Data_custom_val(v))) + +static void llvm_finalize_pmbuilder(value PMB) { + LLVMPassManagerBuilderDispose(PMBuilder_val(PMB)); +} + +static struct custom_operations pmbuilder_ops = { + (char *) "LLVMPassManagerBuilder", + llvm_finalize_pmbuilder, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +static value alloc_pmbuilder(LLVMPassManagerBuilderRef Ref) { + value Val = alloc_custom(&pmbuilder_ops, + sizeof(LLVMPassManagerBuilderRef), 0, 1); + PMBuilder_val(Val) = Ref; + return Val; +} + +/* t -> unit */ +CAMLprim value llvm_pmbuilder_create(value Unit) { + return alloc_pmbuilder(LLVMPassManagerBuilderCreate()); +} + +/* int -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_opt_level(value OptLevel, value PMB) { + LLVMPassManagerBuilderSetOptLevel(PMBuilder_val(PMB), Int_val(OptLevel)); + return Val_unit; +} + +/* int -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_size_level(value SizeLevel, value PMB) { + LLVMPassManagerBuilderSetSizeLevel(PMBuilder_val(PMB), Int_val(SizeLevel)); + return Val_unit; +} + +/* int -> t -> unit */ +CAMLprim value llvm_pmbuilder_use_inliner_with_threshold( + value Threshold, value PMB) { + LLVMPassManagerBuilderSetOptLevel(PMBuilder_val(PMB), Int_val(Threshold)); + return Val_unit; +} + +/* bool -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_disable_unit_at_a_time( + value DisableUnitAtATime, value PMB) { + LLVMPassManagerBuilderSetDisableUnitAtATime( + PMBuilder_val(PMB), Bool_val(DisableUnitAtATime)); + return Val_unit; +} + +/* bool -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_disable_unroll_loops( + value DisableUnroll, value PMB) { + LLVMPassManagerBuilderSetDisableUnrollLoops( + PMBuilder_val(PMB), Bool_val(DisableUnroll)); + return Val_unit; +} + +/* [ `Function ] Llvm.PassManager.t -> t -> unit */ +CAMLprim value llvm_pmbuilder_populate_function_pass_manager( + LLVMPassManagerRef PM, value PMB) { + LLVMPassManagerBuilderPopulateFunctionPassManager( + PMBuilder_val(PMB), PM); + return Val_unit; +} + +/* [ `Module ] Llvm.PassManager.t -> t -> unit */ +CAMLprim value llvm_pmbuilder_populate_module_pass_manager( + LLVMPassManagerRef PM, value PMB) { + LLVMPassManagerBuilderPopulateModulePassManager( + PMBuilder_val(PMB), PM); + return Val_unit; +} + +/* [ `Module ] Llvm.PassManager.t -> + internalize:bool -> run_inliner:bool -> t -> unit */ +CAMLprim value llvm_pmbuilder_populate_lto_pass_manager( + LLVMPassManagerRef PM, value Internalize, value RunInliner, + value PMB) { + LLVMPassManagerBuilderPopulateLTOPassManager( + PMBuilder_val(PMB), PM, + Bool_val(Internalize), Bool_val(RunInliner)); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/scalar/Makefile b/bindings/ocaml/transforms/scalar/Makefile new file mode 100644 index 00000000..6e250f66 --- /dev/null +++ b/bindings/ocaml/transforms/scalar/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_scalar_opts interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_scalar_opts +UsedComponents := scalaropts +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml new file mode 100644 index 00000000..958939dc --- /dev/null +++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml @@ -0,0 +1,114 @@ +(*===-- llvm_scalar_opts.ml - LLVM OCaml Interface -------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +external add_constant_propagation : [ unit + = "llvm_add_constant_propagation" +external add_sccp : [ unit + = "llvm_add_sccp" +external add_dead_store_elimination : [ unit + = "llvm_add_dead_store_elimination" +external add_aggressive_dce : [ unit + = "llvm_add_aggressive_dce" +external +add_scalar_repl_aggregation : [ unit + = "llvm_add_scalar_repl_aggregation" + +external +add_scalar_repl_aggregation_ssa : [ unit + = "llvm_add_scalar_repl_aggregation_ssa" + +external +add_scalar_repl_aggregation_with_threshold : int -> [ unit + = "llvm_add_scalar_repl_aggregation_with_threshold" +external add_ind_var_simplification : [ unit + = "llvm_add_ind_var_simplification" +external +add_instruction_combination : [ unit + = "llvm_add_instruction_combination" +external add_licm : [ unit + = "llvm_add_licm" +external add_loop_unswitch : [ unit + = "llvm_add_loop_unswitch" +external add_loop_unroll : [ unit + = "llvm_add_loop_unroll" +external add_loop_rotation : [ unit + = "llvm_add_loop_rotation" +external +add_memory_to_register_promotion : [ unit + = "llvm_add_memory_to_register_promotion" +external +add_memory_to_register_demotion : [ unit + = "llvm_add_memory_to_register_demotion" +external add_reassociation : [ unit + = "llvm_add_reassociation" +external add_jump_threading : [ unit + = "llvm_add_jump_threading" +external add_cfg_simplification : [ unit + = "llvm_add_cfg_simplification" +external +add_tail_call_elimination : [ unit + = "llvm_add_tail_call_elimination" +external add_gvn : [ unit + = "llvm_add_gvn" +external add_memcpy_opt : [ unit + = "llvm_add_memcpy_opt" +external add_loop_deletion : [ unit + = "llvm_add_loop_deletion" + +external add_loop_idiom : [ unit + = "llvm_add_loop_idiom" + +external +add_lib_call_simplification : [ unit + = "llvm_add_lib_call_simplification" + +external +add_verifier : [ unit + = "llvm_add_verifier" + +external +add_correlated_value_propagation : [ unit + = "llvm_add_correlated_value_propagation" + +external +add_early_cse : [ unit + = "llvm_add_early_cse" + +external +add_lower_expect_intrinsic : [ unit + = "llvm_add_lower_expect_intrinsic" + +external +add_type_based_alias_analysis : [ unit + = "llvm_add_type_based_alias_analysis" + +external +add_basic_alias_analysis : [ unit + = "llvm_add_basic_alias_analysis" + +external +add_partially_inline_lib_calls : [ unit + = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli new file mode 100644 index 00000000..d69abe20 --- /dev/null +++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli @@ -0,0 +1,168 @@ +(*===-- llvm_scalar_opts.mli - LLVM OCaml Interface ------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Scalar Transforms. + + This interface provides an OCaml API for LLVM scalar transforms, the + classes in the [LLVMScalarOpts] library. *) + +(** See the [llvm::createConstantPropogationPass] function. *) +external add_constant_propagation : [ unit + = "llvm_add_constant_propagation" + +(** See the [llvm::createSCCPPass] function. *) +external add_sccp : [ unit + = "llvm_add_sccp" + +(** See [llvm::createDeadStoreEliminationPass] function. *) +external add_dead_store_elimination : [ unit + = "llvm_add_dead_store_elimination" + +(** See The [llvm::createAggressiveDCEPass] function. *) +external add_aggressive_dce : [ unit + = "llvm_add_aggressive_dce" + +(** See the [llvm::createScalarReplAggregatesPass] function. *) +external +add_scalar_repl_aggregation : [ unit + = "llvm_add_scalar_repl_aggregation" + +(** See the [llvm::createScalarReplAggregatesPassSSA] function. *) +external +add_scalar_repl_aggregation_ssa : [ unit + = "llvm_add_scalar_repl_aggregation_ssa" + +(** See the [llvm::createScalarReplAggregatesWithThreshold] function. *) +external +add_scalar_repl_aggregation_with_threshold : int -> [ unit + = "llvm_add_scalar_repl_aggregation_with_threshold" + +(** See the [llvm::createIndVarSimplifyPass] function. *) +external add_ind_var_simplification : [ unit + = "llvm_add_ind_var_simplification" + +(** See the [llvm::createInstructionCombiningPass] function. *) +external +add_instruction_combination : [ unit + = "llvm_add_instruction_combination" + +(** See the [llvm::createLICMPass] function. *) +external add_licm : [ unit + = "llvm_add_licm" + +(** See the [llvm::createLoopUnswitchPass] function. *) +external add_loop_unswitch : [ unit + = "llvm_add_loop_unswitch" + +(** See the [llvm::createLoopUnrollPass] function. *) +external add_loop_unroll : [ unit + = "llvm_add_loop_unroll" + +(** See the [llvm::createLoopRotatePass] function. *) +external add_loop_rotation : [ unit + = "llvm_add_loop_rotation" + +(** See the [llvm::createPromoteMemoryToRegisterPass] function. *) +external +add_memory_to_register_promotion : [ unit + = "llvm_add_memory_to_register_promotion" + +(** See the [llvm::createDemoteMemoryToRegisterPass] function. *) +external +add_memory_to_register_demotion : [ unit + = "llvm_add_memory_to_register_demotion" + +(** See the [llvm::createReassociatePass] function. *) +external add_reassociation : [ unit + = "llvm_add_reassociation" + +(** See the [llvm::createJumpThreadingPass] function. *) +external add_jump_threading : [ unit + = "llvm_add_jump_threading" + +(** See the [llvm::createCFGSimplificationPass] function. *) +external add_cfg_simplification : [ unit + = "llvm_add_cfg_simplification" + +(** See the [llvm::createTailCallEliminationPass] function. *) +external +add_tail_call_elimination : [ unit + = "llvm_add_tail_call_elimination" + +(** See the [llvm::createGVNPass] function. *) +external add_gvn : [ unit + = "llvm_add_gvn" + +(** See the [llvm::createMemCpyOptPass] function. *) +external add_memcpy_opt : [ unit + = "llvm_add_memcpy_opt" + +(** See the [llvm::createLoopDeletionPass] function. *) +external add_loop_deletion : [ unit + = "llvm_add_loop_deletion" + +external add_loop_idiom : [ unit + = "llvm_add_loop_idiom" + +(** See the [llvm::createSimplifyLibCallsPass] function. *) +external +add_lib_call_simplification : [ unit + = "llvm_add_lib_call_simplification" + +(** See the [llvm::createVerifierPass] function. *) +external +add_verifier : [ unit + = "llvm_add_verifier" + +(** See the [llvm::createCorrelatedValuePropagationPass] function. *) +external +add_correlated_value_propagation : [ unit + = "llvm_add_correlated_value_propagation" + +(** See the [llvm::createEarlyCSE] function. *) +external +add_early_cse : [ unit + = "llvm_add_early_cse" + +(** See the [llvm::createLowerExpectIntrinsicPass] function. *) +external +add_lower_expect_intrinsic : [ unit + = "llvm_add_lower_expect_intrinsic" + +(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *) +external +add_type_based_alias_analysis : [ unit + = "llvm_add_type_based_alias_analysis" + +(** See the [llvm::createBasicAliasAnalysisPass] function. *) +external +add_basic_alias_analysis : [ unit + = "llvm_add_basic_alias_analysis" + +(** See the [llvm::createPartiallyInlineLibCallsPass] function. *) +external +add_partially_inline_lib_calls : [ unit + = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c new file mode 100644 index 00000000..0a71bd7c --- /dev/null +++ b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c @@ -0,0 +1,207 @@ +/*===-- scalar_opts_ocaml.c - LLVM OCaml Glue -------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Transforms/Scalar.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* [ unit */ +CAMLprim value llvm_add_constant_propagation(LLVMPassManagerRef PM) { + LLVMAddConstantPropagationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_sccp(LLVMPassManagerRef PM) { + LLVMAddSCCPPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_dead_store_elimination(LLVMPassManagerRef PM) { + LLVMAddDeadStoreEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_aggressive_dce(LLVMPassManagerRef PM) { + LLVMAddAggressiveDCEPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scalar_repl_aggregation(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scalar_repl_aggregation_ssa(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPassSSA(PM); + return Val_unit; +} + +/* [ int -> unit */ +CAMLprim value llvm_add_scalar_repl_aggregation_with_threshold(value threshold, + LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPassWithThreshold(PM, Int_val(threshold)); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_ind_var_simplification(LLVMPassManagerRef PM) { + LLVMAddIndVarSimplifyPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_instruction_combination(LLVMPassManagerRef PM) { + LLVMAddInstructionCombiningPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) { + LLVMAddLICMPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) { + LLVMAddLoopUnswitchPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unroll(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_rotation(LLVMPassManagerRef PM) { + LLVMAddLoopRotatePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memory_to_register_promotion(LLVMPassManagerRef PM) { + LLVMAddPromoteMemoryToRegisterPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memory_to_register_demotion(LLVMPassManagerRef PM) { + LLVMAddDemoteMemoryToRegisterPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_reassociation(LLVMPassManagerRef PM) { + LLVMAddReassociatePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_jump_threading(LLVMPassManagerRef PM) { + LLVMAddJumpThreadingPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_cfg_simplification(LLVMPassManagerRef PM) { + LLVMAddCFGSimplificationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_tail_call_elimination(LLVMPassManagerRef PM) { + LLVMAddTailCallEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { + LLVMAddGVNPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memcpy_opt(LLVMPassManagerRef PM) { + LLVMAddMemCpyOptPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) { + LLVMAddLoopDeletionPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_idiom(LLVMPassManagerRef PM) { + LLVMAddLoopIdiomPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_lib_call_simplification(LLVMPassManagerRef PM) { + LLVMAddSimplifyLibCallsPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_verifier(LLVMPassManagerRef PM) { + LLVMAddVerifierPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_correlated_value_propagation(LLVMPassManagerRef PM) { + LLVMAddCorrelatedValuePropagationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_early_cse(LLVMPassManagerRef PM) { + LLVMAddEarlyCSEPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_lower_expect_intrinsic(LLVMPassManagerRef PM) { + LLVMAddLowerExpectIntrinsicPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) { + LLVMAddTypeBasedAliasAnalysisPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) { + LLVMAddBasicAliasAnalysisPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_partially_inline_lib_calls(LLVMPassManagerRef PM) { + LLVMAddPartiallyInlineLibCallsPass(PM); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/vectorize/Makefile b/bindings/ocaml/transforms/vectorize/Makefile new file mode 100644 index 00000000..5a854d17 --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/vectorize/Makefile --------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_vectorize_opts interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_vectorize +UsedComponents := vectorize +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml new file mode 100644 index 00000000..4fc53c6d --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml @@ -0,0 +1,15 @@ +(*===-- llvm_vectorize.ml - LLVM OCaml Interface --------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +external add_bb_vectorize : [ unit + = "llvm_add_bb_vectorize" +external add_loop_vectorize : [ unit + = "llvm_add_loop_vectorize" +external add_slp_vectorize : [ unit + = "llvm_add_slp_vectorize" diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli new file mode 100644 index 00000000..02530398 --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli @@ -0,0 +1,25 @@ +(*===-- llvm_vectorize.mli - LLVM OCaml Interface -------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Vectorize Transforms. + + This interface provides an OCaml API for LLVM vectorize transforms, the + classes in the [LLVMVectorize] library. *) + +(** See the [llvm::createBBVectorizePass] function. *) +external add_bb_vectorize : [ unit + = "llvm_add_bb_vectorize" + +(** See the [llvm::createLoopVectorizePass] function. *) +external add_loop_vectorize : [ unit + = "llvm_add_loop_vectorize" + +(** See [llvm::createSLPVectorizerPass] function. *) +external add_slp_vectorize : [ unit + = "llvm_add_slp_vectorize" diff --git a/bindings/ocaml/transforms/vectorize/vectorize_ocaml.c b/bindings/ocaml/transforms/vectorize/vectorize_ocaml.c new file mode 100644 index 00000000..1c810495 --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/vectorize_ocaml.c @@ -0,0 +1,38 @@ +/*===-- vectorize_ocaml.c - LLVM OCaml Glue ---------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Transforms/Vectorize.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* [ unit */ +CAMLprim value llvm_add_bb_vectorize(LLVMPassManagerRef PM) { + LLVMAddBBVectorizePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_vectorize(LLVMPassManagerRef PM) { + LLVMAddLoopVectorizePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_slp_vectorize(LLVMPassManagerRef PM) { + LLVMAddSLPVectorizePass(PM); + return Val_unit; +} diff --git a/bindings/python/README.txt b/bindings/python/README.txt new file mode 100644 index 00000000..96e33431 --- /dev/null +++ b/bindings/python/README.txt @@ -0,0 +1,67 @@ +This directory contains Python bindings for LLVM's C library. + +The bindings are currently a work in progress and are far from complete. +Use at your own risk. + +Developer Info +============== + +The single Python package is "llvm." Modules inside this package roughly +follow the names of the modules/headers defined by LLVM's C API. + +Testing +------- + +All test code is location in llvm/tests. Tests are written as classes +which inherit from llvm.tests.base.TestBase, which is a convenience base +class that provides common functionality. + +Tests can be executed by installing nose: + + pip install nosetests + +Then by running nosetests: + + nosetests + +To see more output: + + nosetests -v + +To step into the Python debugger while running a test, add the following +to your test at the point you wish to enter the debugger: + + import pdb; pdb.set_trace() + +Then run nosetests: + + nosetests -s -v + +You should strive for high code coverage. To see current coverage: + + pip install coverage + nosetests --with-coverage --cover-html + +Then open cover/index.html in your browser of choice to see the code coverage. + +Style Convention +---------------- + +All code should pass PyFlakes. First, install PyFlakes: + + pip install pyflakes + +Then at any time run it to see a report: + + pyflakes . + +Eventually we'll provide a Pylint config file. In the meantime, install +Pylint: + + pip install pylint + +And run: + + pylint llvm + +And try to keep the number of violations to a minimum. diff --git a/bindings/python/llvm/__init__.py b/bindings/python/llvm/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bindings/python/llvm/bit_reader.py b/bindings/python/llvm/bit_reader.py new file mode 100644 index 00000000..5bf5e220 --- /dev/null +++ b/bindings/python/llvm/bit_reader.py @@ -0,0 +1,31 @@ + +from .common import LLVMObject +from .common import c_object_p +from .common import get_library +from . import enumerations +from .core import MemoryBuffer +from .core import Module +from .core import OpCode +from ctypes import POINTER +from ctypes import byref +from ctypes import c_char_p +from ctypes import cast +__all__ = ['parse_bitcode'] +lib = get_library() + +def parse_bitcode(mem_buffer): + """Input is .core.MemoryBuffer""" + module = c_object_p() + out = c_char_p(None) + result = lib.LLVMParseBitcode(mem_buffer, byref(module), byref(out)) + if result: + raise RuntimeError('LLVM Error: %s' % out.value) + m = Module(module) + m.take_ownership(mem_buffer) + return m + +def register_library(library): + library.LLVMParseBitcode.argtypes = [MemoryBuffer, POINTER(c_object_p), POINTER(c_char_p)] + library.LLVMParseBitcode.restype = bool + +register_library(lib) diff --git a/bindings/python/llvm/common.py b/bindings/python/llvm/common.py new file mode 100644 index 00000000..b177f7fa --- /dev/null +++ b/bindings/python/llvm/common.py @@ -0,0 +1,126 @@ +#===- common.py - Python LLVM Bindings -----------------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +from ctypes import POINTER +from ctypes import c_void_p +from ctypes import cdll + +import ctypes.util +import platform + +# LLVM_VERSION: sync with PACKAGE_VERSION in autoconf/configure.ac and CMakeLists.txt +# but leave out the 'svn' suffix. +LLVM_VERSION = '3.4' + +__all__ = [ + 'c_object_p', + 'get_library', +] + +c_object_p = POINTER(c_void_p) + +class LLVMObject(object): + """Base class for objects that are backed by an LLVM data structure. + + This class should never be instantiated outside of this package. + """ + def __init__(self, ptr, ownable=True, disposer=None): + assert isinstance(ptr, c_object_p) + + self._ptr = self._as_parameter_ = ptr + + self._self_owned = True + self._ownable = ownable + self._disposer = disposer + + self._owned_objects = [] + + def take_ownership(self, obj): + """Take ownership of another object. + + When you take ownership of another object, you are responsible for + destroying that object. In addition, a reference to that object is + placed inside this object so the Python garbage collector will not + collect the object while it is still alive in libLLVM. + + This method should likely only be called from within modules inside + this package. + """ + assert isinstance(obj, LLVMObject) + + self._owned_objects.append(obj) + obj._self_owned = False + + def from_param(self): + """ctypes function that converts this object to a function parameter.""" + return self._as_parameter_ + + def __del__(self): + if not hasattr(self, '_self_owned') or not hasattr(self, '_disposer'): + return + + if self._self_owned and self._disposer: + self._disposer(self) + +class CachedProperty(object): + """Decorator that caches the result of a property lookup. + + This is a useful replacement for @property. It is recommended to use this + decorator on properties that invoke C API calls for which the result of the + call will be idempotent. + """ + def __init__(self, wrapped): + self.wrapped = wrapped + try: + self.__doc__ = wrapped.__doc__ + except: # pragma: no cover + pass + + def __get__(self, instance, instance_type=None): + if instance is None: + return self + + value = self.wrapped(instance) + setattr(instance, self.wrapped.__name__, value) + + return value + +def get_library(): + """Obtain a reference to the llvm library.""" + + # On Linux, ctypes.cdll.LoadLibrary() respects LD_LIBRARY_PATH + # while ctypes.util.find_library() doesn't. + # See http://docs.python.org/2/library/ctypes.html#finding-shared-libraries + # + # To make it possible to run the unit tests without installing the LLVM shared + # library into a default linker search path. Always Try ctypes.cdll.LoadLibrary() + # with all possible library names first, then try ctypes.util.find_library(). + + names = ['LLVM-' + LLVM_VERSION, 'LLVM-' + LLVM_VERSION + 'svn'] + t = platform.system() + if t == 'Darwin': + pfx, ext = 'lib', '.dylib' + elif t == 'Windows': + pfx, ext = '', '.dll' + else: + pfx, ext = 'lib', '.so' + + for i in names: + try: + lib = cdll.LoadLibrary(pfx + i + ext) + except OSError: + pass + else: + return lib + + for i in names: + t = ctypes.util.find_library(i) + if t: + return cdll.LoadLibrary(t) + raise Exception('LLVM shared library not found!') diff --git a/bindings/python/llvm/core.py b/bindings/python/llvm/core.py new file mode 100644 index 00000000..ebf57d44 --- /dev/null +++ b/bindings/python/llvm/core.py @@ -0,0 +1,540 @@ +#===- core.py - Python LLVM Bindings -------------------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +from .common import LLVMObject +from .common import c_object_p +from .common import get_library + +from . import enumerations + +from ctypes import POINTER +from ctypes import byref +from ctypes import c_char_p +from ctypes import c_uint + +__all__ = [ + "lib", + "OpCode", + "MemoryBuffer", + "Module", + "Value", + "Function", + "BasicBlock", + "Instruction", + "Context", + "PassRegistry" +] + +lib = get_library() + +class OpCode(object): + """Represents an individual OpCode enumeration.""" + + _value_map = {} + + def __init__(self, name, value): + self.name = name + self.value = value + + def __repr__(self): + return 'OpCode.%s' % self.name + + @staticmethod + def from_value(value): + """Obtain an OpCode instance from a numeric value.""" + result = OpCode._value_map.get(value, None) + + if result is None: + raise ValueError('Unknown OpCode: %d' % value) + + return result + + @staticmethod + def register(name, value): + """Registers a new OpCode enumeration. + + This is called by this module for each enumeration defined in + enumerations. You should not need to call this outside this module. + """ + if value in OpCode._value_map: + raise ValueError('OpCode value already registered: %d' % value) + + opcode = OpCode(name, value) + OpCode._value_map[value] = opcode + setattr(OpCode, name, opcode) + +class MemoryBuffer(LLVMObject): + """Represents an opaque memory buffer.""" + + def __init__(self, filename=None): + """Create a new memory buffer. + + Currently, we support creating from the contents of a file at the + specified filename. + """ + if filename is None: + raise Exception("filename argument must be defined") + + memory = c_object_p() + out = c_char_p(None) + + result = lib.LLVMCreateMemoryBufferWithContentsOfFile(filename, + byref(memory), byref(out)) + + if result: + raise Exception("Could not create memory buffer: %s" % out.value) + + LLVMObject.__init__(self, memory, disposer=lib.LLVMDisposeMemoryBuffer) + + def __len__(self): + return lib.LLVMGetBufferSize(self) + +class Value(LLVMObject): + + def __init__(self, value): + LLVMObject.__init__(self, value) + + @property + def name(self): + return lib.LLVMGetValueName(self) + + def dump(self): + lib.LLVMDumpValue(self) + + def get_operand(self, i): + return Value(lib.LLVMGetOperand(self, i)) + + def set_operand(self, i, v): + return lib.LLVMSetOperand(self, i, v) + + def __len__(self): + return lib.LLVMGetNumOperands(self) + +class Module(LLVMObject): + """Represents the top-level structure of an llvm program in an opaque object.""" + + def __init__(self, module, name=None, context=None): + LLVMObject.__init__(self, module, disposer=lib.LLVMDisposeModule) + + @classmethod + def CreateWithName(cls, module_id): + m = Module(lib.LLVMModuleCreateWithName(module_id)) + c = Context.GetGlobalContext().take_ownership(m) + return m + + @property + def datalayout(self): + return lib.LLVMGetDataLayout(self) + + @datalayout.setter + def datalayout(self, new_data_layout): + """new_data_layout is a string.""" + lib.LLVMSetDataLayout(self, new_data_layout) + + @property + def target(self): + return lib.LLVMGetTarget(self) + + @target.setter + def target(self, new_target): + """new_target is a string.""" + lib.LLVMSetTarget(self, new_target) + + def dump(self): + lib.LLVMDumpModule(self) + + class __function_iterator(object): + def __init__(self, module, reverse=False): + self.module = module + self.reverse = reverse + if self.reverse: + self.function = self.module.last + else: + self.function = self.module.first + + def __iter__(self): + return self + + def next(self): + if not isinstance(self.function, Function): + raise StopIteration("") + result = self.function + if self.reverse: + self.function = self.function.prev + else: + self.function = self.function.next + return result + + def __iter__(self): + return Module.__function_iterator(self) + + def __reversed__(self): + return Module.__function_iterator(self, reverse=True) + + @property + def first(self): + return Function(lib.LLVMGetFirstFunction(self)) + + @property + def last(self): + return Function(lib.LLVMGetLastFunction(self)) + + def print_module_to_file(self, filename): + out = c_char_p(None) + # Result is inverted so 0 means everything was ok. + result = lib.LLVMPrintModuleToFile(self, filename, byref(out)) + if result: + raise RuntimeError("LLVM Error: %s" % out.value) + +class Function(Value): + + def __init__(self, value): + Value.__init__(self, value) + + @property + def next(self): + f = lib.LLVMGetNextFunction(self) + return f and Function(f) + + @property + def prev(self): + f = lib.LLVMGetPreviousFunction(self) + return f and Function(f) + + @property + def first(self): + b = lib.LLVMGetFirstBasicBlock(self) + return b and BasicBlock(b) + + @property + def last(self): + b = lib.LLVMGetLastBasicBlock(self) + return b and BasicBlock(b) + + class __bb_iterator(object): + def __init__(self, function, reverse=False): + self.function = function + self.reverse = reverse + if self.reverse: + self.bb = function.last + else: + self.bb = function.first + + def __iter__(self): + return self + + def next(self): + if not isinstance(self.bb, BasicBlock): + raise StopIteration("") + result = self.bb + if self.reverse: + self.bb = self.bb.prev + else: + self.bb = self.bb.next + return result + + def __iter__(self): + return Function.__bb_iterator(self) + + def __reversed__(self): + return Function.__bb_iterator(self, reverse=True) + + def __len__(self): + return lib.LLVMCountBasicBlocks(self) + +class BasicBlock(LLVMObject): + + def __init__(self, value): + LLVMObject.__init__(self, value) + + @property + def next(self): + b = lib.LLVMGetNextBasicBlock(self) + return b and BasicBlock(b) + + @property + def prev(self): + b = lib.LLVMGetPreviousBasicBlock(self) + return b and BasicBlock(b) + + @property + def first(self): + i = lib.LLVMGetFirstInstruction(self) + return i and Instruction(i) + + @property + def last(self): + i = lib.LLVMGetLastInstruction(self) + return i and Instruction(i) + + def __as_value(self): + return Value(lib.LLVMBasicBlockAsValue(self)) + + @property + def name(self): + return lib.LLVMGetValueName(self.__as_value()) + + def dump(self): + lib.LLVMDumpValue(self.__as_value()) + + def get_operand(self, i): + return Value(lib.LLVMGetOperand(self.__as_value(), + i)) + + def set_operand(self, i, v): + return lib.LLVMSetOperand(self.__as_value(), + i, v) + + def __len__(self): + return lib.LLVMGetNumOperands(self.__as_value()) + + class __inst_iterator(object): + def __init__(self, bb, reverse=False): + self.bb = bb + self.reverse = reverse + if self.reverse: + self.inst = self.bb.last + else: + self.inst = self.bb.first + + def __iter__(self): + return self + + def next(self): + if not isinstance(self.inst, Instruction): + raise StopIteration("") + result = self.inst + if self.reverse: + self.inst = self.inst.prev + else: + self.inst = self.inst.next + return result + + def __iter__(self): + return BasicBlock.__inst_iterator(self) + + def __reversed__(self): + return BasicBlock.__inst_iterator(self, reverse=True) + + +class Instruction(Value): + + def __init__(self, value): + Value.__init__(self, value) + + @property + def next(self): + i = lib.LLVMGetNextInstruction(self) + return i and Instruction(i) + + @property + def prev(self): + i = lib.LLVMGetPreviousInstruction(self) + return i and Instruction(i) + + @property + def opcode(self): + return OpCode.from_value(lib.LLVMGetInstructionOpcode(self)) + +class Context(LLVMObject): + + def __init__(self, context=None): + if context is None: + context = lib.LLVMContextCreate() + LLVMObject.__init__(self, context, disposer=lib.LLVMContextDispose) + else: + LLVMObject.__init__(self, context) + + @classmethod + def GetGlobalContext(cls): + return Context(lib.LLVMGetGlobalContext()) + +class PassRegistry(LLVMObject): + """Represents an opaque pass registry object.""" + + def __init__(self): + LLVMObject.__init__(self, + lib.LLVMGetGlobalPassRegistry()) + +def register_library(library): + # Initialization/Shutdown declarations. + library.LLVMInitializeCore.argtypes = [PassRegistry] + library.LLVMInitializeCore.restype = None + + library.LLVMInitializeTransformUtils.argtypes = [PassRegistry] + library.LLVMInitializeTransformUtils.restype = None + + library.LLVMInitializeScalarOpts.argtypes = [PassRegistry] + library.LLVMInitializeScalarOpts.restype = None + + library.LLVMInitializeObjCARCOpts.argtypes = [PassRegistry] + library.LLVMInitializeObjCARCOpts.restype = None + + library.LLVMInitializeVectorization.argtypes = [PassRegistry] + library.LLVMInitializeVectorization.restype = None + + library.LLVMInitializeInstCombine.argtypes = [PassRegistry] + library.LLVMInitializeInstCombine.restype = None + + library.LLVMInitializeIPO.argtypes = [PassRegistry] + library.LLVMInitializeIPO.restype = None + + library.LLVMInitializeInstrumentation.argtypes = [PassRegistry] + library.LLVMInitializeInstrumentation.restype = None + + library.LLVMInitializeAnalysis.argtypes = [PassRegistry] + library.LLVMInitializeAnalysis.restype = None + + library.LLVMInitializeIPA.argtypes = [PassRegistry] + library.LLVMInitializeIPA.restype = None + + library.LLVMInitializeCodeGen.argtypes = [PassRegistry] + library.LLVMInitializeCodeGen.restype = None + + library.LLVMInitializeTarget.argtypes = [PassRegistry] + library.LLVMInitializeTarget.restype = None + + library.LLVMShutdown.argtypes = [] + library.LLVMShutdown.restype = None + + # Pass Registry declarations. + library.LLVMGetGlobalPassRegistry.argtypes = [] + library.LLVMGetGlobalPassRegistry.restype = c_object_p + + # Context declarations. + library.LLVMContextCreate.argtypes = [] + library.LLVMContextCreate.restype = c_object_p + + library.LLVMContextDispose.argtypes = [Context] + library.LLVMContextDispose.restype = None + + library.LLVMGetGlobalContext.argtypes = [] + library.LLVMGetGlobalContext.restype = c_object_p + + # Memory buffer declarations + library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p, + POINTER(c_object_p), POINTER(c_char_p)] + library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool + + library.LLVMGetBufferSize.argtypes = [MemoryBuffer] + + library.LLVMDisposeMemoryBuffer.argtypes = [MemoryBuffer] + + # Module declarations + library.LLVMModuleCreateWithName.argtypes = [c_char_p] + library.LLVMModuleCreateWithName.restype = c_object_p + + library.LLVMDisposeModule.argtypes = [Module] + library.LLVMDisposeModule.restype = None + + library.LLVMGetDataLayout.argtypes = [Module] + library.LLVMGetDataLayout.restype = c_char_p + + library.LLVMSetDataLayout.argtypes = [Module, c_char_p] + library.LLVMSetDataLayout.restype = None + + library.LLVMGetTarget.argtypes = [Module] + library.LLVMGetTarget.restype = c_char_p + + library.LLVMSetTarget.argtypes = [Module, c_char_p] + library.LLVMSetTarget.restype = None + + library.LLVMDumpModule.argtypes = [Module] + library.LLVMDumpModule.restype = None + + library.LLVMPrintModuleToFile.argtypes = [Module, c_char_p, + POINTER(c_char_p)] + library.LLVMPrintModuleToFile.restype = bool + + library.LLVMGetFirstFunction.argtypes = [Module] + library.LLVMGetFirstFunction.restype = c_object_p + + library.LLVMGetLastFunction.argtypes = [Module] + library.LLVMGetLastFunction.restype = c_object_p + + library.LLVMGetNextFunction.argtypes = [Function] + library.LLVMGetNextFunction.restype = c_object_p + + library.LLVMGetPreviousFunction.argtypes = [Function] + library.LLVMGetPreviousFunction.restype = c_object_p + + # Value declarations. + library.LLVMGetValueName.argtypes = [Value] + library.LLVMGetValueName.restype = c_char_p + + library.LLVMDumpValue.argtypes = [Value] + library.LLVMDumpValue.restype = None + + library.LLVMGetOperand.argtypes = [Value, c_uint] + library.LLVMGetOperand.restype = c_object_p + + library.LLVMSetOperand.argtypes = [Value, Value, c_uint] + library.LLVMSetOperand.restype = None + + library.LLVMGetNumOperands.argtypes = [Value] + library.LLVMGetNumOperands.restype = c_uint + + # Basic Block Declarations. + library.LLVMGetFirstBasicBlock.argtypes = [Function] + library.LLVMGetFirstBasicBlock.restype = c_object_p + + library.LLVMGetLastBasicBlock.argtypes = [Function] + library.LLVMGetLastBasicBlock.restype = c_object_p + + library.LLVMGetNextBasicBlock.argtypes = [BasicBlock] + library.LLVMGetNextBasicBlock.restype = c_object_p + + library.LLVMGetPreviousBasicBlock.argtypes = [BasicBlock] + library.LLVMGetPreviousBasicBlock.restype = c_object_p + + library.LLVMGetFirstInstruction.argtypes = [BasicBlock] + library.LLVMGetFirstInstruction.restype = c_object_p + + library.LLVMGetLastInstruction.argtypes = [BasicBlock] + library.LLVMGetLastInstruction.restype = c_object_p + + library.LLVMBasicBlockAsValue.argtypes = [BasicBlock] + library.LLVMBasicBlockAsValue.restype = c_object_p + + library.LLVMCountBasicBlocks.argtypes = [Function] + library.LLVMCountBasicBlocks.restype = c_uint + + # Instruction Declarations. + library.LLVMGetNextInstruction.argtypes = [Instruction] + library.LLVMGetNextInstruction.restype = c_object_p + + library.LLVMGetPreviousInstruction.argtypes = [Instruction] + library.LLVMGetPreviousInstruction.restype = c_object_p + + library.LLVMGetInstructionOpcode.argtypes = [Instruction] + library.LLVMGetInstructionOpcode.restype = c_uint + +def register_enumerations(): + for name, value in enumerations.OpCodes: + OpCode.register(name, value) + +def initialize_llvm(): + c = Context.GetGlobalContext() + p = PassRegistry() + lib.LLVMInitializeCore(p) + lib.LLVMInitializeTransformUtils(p) + lib.LLVMInitializeScalarOpts(p) + lib.LLVMInitializeObjCARCOpts(p) + lib.LLVMInitializeVectorization(p) + lib.LLVMInitializeInstCombine(p) + lib.LLVMInitializeIPO(p) + lib.LLVMInitializeInstrumentation(p) + lib.LLVMInitializeAnalysis(p) + lib.LLVMInitializeIPA(p) + lib.LLVMInitializeCodeGen(p) + lib.LLVMInitializeTarget(p) + +register_library(lib) +register_enumerations() +initialize_llvm() diff --git a/bindings/python/llvm/disassembler.py b/bindings/python/llvm/disassembler.py new file mode 100644 index 00000000..f2df275b --- /dev/null +++ b/bindings/python/llvm/disassembler.py @@ -0,0 +1,170 @@ +#===- disassembler.py - Python LLVM Bindings -----------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +from ctypes import CFUNCTYPE +from ctypes import POINTER +from ctypes import addressof +from ctypes import c_byte +from ctypes import c_char_p +from ctypes import c_int +from ctypes import c_size_t +from ctypes import c_ubyte +from ctypes import c_uint64 +from ctypes import c_void_p +from ctypes import cast + +from .common import LLVMObject +from .common import c_object_p +from .common import get_library + +__all__ = [ + 'Disassembler', +] + +lib = get_library() +callbacks = {} + +# Constants for set_options +Option_UseMarkup = 1 + + + +_initialized = False +_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore'] +def _ensure_initialized(): + global _initialized + if not _initialized: + # Here one would want to call the functions + # LLVMInitializeAll{TargetInfo,TargetMC,Disassembler}s, but + # unfortunately they are only defined as static inline + # functions in the header files of llvm-c, so they don't exist + # as symbols in the shared library. + # So until that is fixed use this hack to initialize them all + for tgt in _targets: + for initializer in ("TargetInfo", "TargetMC", "Disassembler"): + try: + f = getattr(lib, "LLVMInitialize" + tgt + initializer) + except AttributeError: + continue + f() + _initialized = True + + +class Disassembler(LLVMObject): + """Represents a disassembler instance. + + Disassembler instances are tied to specific "triple," which must be defined + at creation time. + + Disassembler instances can disassemble instructions from multiple sources. + """ + def __init__(self, triple): + """Create a new disassembler instance. + + The triple argument is the triple to create the disassembler for. This + is something like 'i386-apple-darwin9'. + """ + + _ensure_initialized() + + ptr = lib.LLVMCreateDisasm(c_char_p(triple), c_void_p(None), c_int(0), + callbacks['op_info'](0), callbacks['symbol_lookup'](0)) + if not ptr: + raise Exception('Could not obtain disassembler for triple: %s' % + triple) + + LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisasmDispose) + + def get_instruction(self, source, pc=0): + """Obtain the next instruction from an input source. + + The input source should be a str or bytearray or something that + represents a sequence of bytes. + + This function will start reading bytes from the beginning of the + source. + + The pc argument specifies the address that the first byte is at. + + This returns a 2-tuple of: + + long number of bytes read. 0 if no instruction was read. + str representation of instruction. This will be the assembly that + represents the instruction. + """ + buf = cast(c_char_p(source), POINTER(c_ubyte)) + out_str = cast((c_byte * 255)(), c_char_p) + + result = lib.LLVMDisasmInstruction(self, buf, c_uint64(len(source)), + c_uint64(pc), out_str, 255) + + return (result, out_str.value) + + def get_instructions(self, source, pc=0): + """Obtain multiple instructions from an input source. + + This is like get_instruction() except it is a generator for all + instructions within the source. It starts at the beginning of the + source and reads instructions until no more can be read. + + This generator returns 3-tuple of: + + long address of instruction. + long size of instruction, in bytes. + str representation of instruction. + """ + source_bytes = c_char_p(source) + out_str = cast((c_byte * 255)(), c_char_p) + + # This could probably be written cleaner. But, it does work. + buf = cast(source_bytes, POINTER(c_ubyte * len(source))).contents + offset = 0 + address = pc + end_address = pc + len(source) + while address < end_address: + b = cast(addressof(buf) + offset, POINTER(c_ubyte)) + result = lib.LLVMDisasmInstruction(self, b, + c_uint64(len(source) - offset), c_uint64(address), + out_str, 255) + + if result == 0: + break + + yield (address, result, out_str.value) + + address += result + offset += result + + def set_options(self, options): + if not lib.LLVMSetDisasmOptions(self, options): + raise Exception('Unable to set all disassembler options in %i' % options) + + +def register_library(library): + library.LLVMCreateDisasm.argtypes = [c_char_p, c_void_p, c_int, + callbacks['op_info'], callbacks['symbol_lookup']] + library.LLVMCreateDisasm.restype = c_object_p + + library.LLVMDisasmDispose.argtypes = [Disassembler] + + library.LLVMDisasmInstruction.argtypes = [Disassembler, POINTER(c_ubyte), + c_uint64, c_uint64, c_char_p, c_size_t] + library.LLVMDisasmInstruction.restype = c_size_t + + library.LLVMSetDisasmOptions.argtypes = [Disassembler, c_uint64] + library.LLVMSetDisasmOptions.restype = c_int + + +callbacks['op_info'] = CFUNCTYPE(c_int, c_void_p, c_uint64, c_uint64, c_uint64, + c_int, c_void_p) +callbacks['symbol_lookup'] = CFUNCTYPE(c_char_p, c_void_p, c_uint64, + POINTER(c_uint64), c_uint64, + POINTER(c_char_p)) + +register_library(lib) diff --git a/bindings/python/llvm/enumerations.py b/bindings/python/llvm/enumerations.py new file mode 100644 index 00000000..f49d2faa --- /dev/null +++ b/bindings/python/llvm/enumerations.py @@ -0,0 +1,211 @@ +#===- enumerations.py - Python LLVM Enumerations -------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +r""" +LLVM Enumerations +================= + +This file defines enumerations from LLVM. + +Each enumeration is exposed as a list of 2-tuples. These lists are consumed by +dedicated types elsewhere in the package. The enumerations are centrally +defined in this file so they are easier to locate and maintain. +""" + +__all__ = [ + 'Attributes', + 'OpCodes', + 'TypeKinds', + 'Linkages', + 'Visibility', + 'CallConv', + 'IntPredicate', + 'RealPredicate', + 'LandingPadClauseTy', +] + +Attributes = [ + ('ZExt', 1 << 0), + ('MSExt', 1 << 1), + ('NoReturn', 1 << 2), + ('InReg', 1 << 3), + ('StructRet', 1 << 4), + ('NoUnwind', 1 << 5), + ('NoAlias', 1 << 6), + ('ByVal', 1 << 7), + ('Nest', 1 << 8), + ('ReadNone', 1 << 9), + ('ReadOnly', 1 << 10), + ('NoInline', 1 << 11), + ('AlwaysInline', 1 << 12), + ('OptimizeForSize', 1 << 13), + ('StackProtect', 1 << 14), + ('StackProtectReq', 1 << 15), + ('Alignment', 31 << 16), + ('NoCapture', 1 << 21), + ('NoRedZone', 1 << 22), + ('ImplicitFloat', 1 << 23), + ('Naked', 1 << 24), + ('InlineHint', 1 << 25), + ('StackAlignment', 7 << 26), + ('ReturnsTwice', 1 << 29), + ('UWTable', 1 << 30), + ('NonLazyBind', 1 << 31), +] + +OpCodes = [ + ('Ret', 1), + ('Br', 2), + ('Switch', 3), + ('IndirectBr', 4), + ('Invoke', 5), + ('Unreachable', 7), + ('Add', 8), + ('FAdd', 9), + ('Sub', 10), + ('FSub', 11), + ('Mul', 12), + ('FMul', 13), + ('UDiv', 14), + ('SDiv', 15), + ('FDiv', 16), + ('URem', 17), + ('SRem', 18), + ('FRem', 19), + ('Shl', 20), + ('LShr', 21), + ('AShr', 22), + ('And', 23), + ('Or', 24), + ('Xor', 25), + ('Alloca', 26), + ('Load', 27), + ('Store', 28), + ('GetElementPtr', 29), + ('Trunc', 30), + ('ZExt', 31), + ('SExt', 32), + ('FPToUI', 33), + ('FPToSI', 34), + ('UIToFP', 35), + ('SIToFP', 36), + ('FPTrunc', 37), + ('FPExt', 38), + ('PtrToInt', 39), + ('IntToPtr', 40), + ('BitCast', 41), + ('ICmp', 42), + ('FCmpl', 43), + ('PHI', 44), + ('Call', 45), + ('Select', 46), + ('UserOp1', 47), + ('UserOp2', 48), + ('AArg', 49), + ('ExtractElement', 50), + ('InsertElement', 51), + ('ShuffleVector', 52), + ('ExtractValue', 53), + ('InsertValue', 54), + ('Fence', 55), + ('AtomicCmpXchg', 56), + ('AtomicRMW', 57), + ('Resume', 58), + ('LandingPad', 59), +] + +TypeKinds = [ + ('Void', 0), + ('Half', 1), + ('Float', 2), + ('Double', 3), + ('X86_FP80', 4), + ('FP128', 5), + ('PPC_FP128', 6), + ('Label', 7), + ('Integer', 8), + ('Function', 9), + ('Struct', 10), + ('Array', 11), + ('Pointer', 12), + ('Vector', 13), + ('Metadata', 14), + ('X86_MMX', 15), +] + +Linkages = [ + ('External', 0), + ('AvailableExternally', 1), + ('LinkOnceAny', 2), + ('LinkOnceODR', 3), + ('WeakAny', 4), + ('WeakODR', 5), + ('Appending', 6), + ('Internal', 7), + ('Private', 8), + ('DLLImport', 9), + ('DLLExport', 10), + ('ExternalWeak', 11), + ('Ghost', 12), + ('Common', 13), + ('LinkerPrivate', 14), + ('LinkerPrivateWeak', 15), + ('LinkerPrivateWeakDefAuto', 16), +] + +Visibility = [ + ('Default', 0), + ('Hidden', 1), + ('Protected', 2), +] + +CallConv = [ + ('CCall', 0), + ('FastCall', 8), + ('ColdCall', 9), + ('X86StdcallCall', 64), + ('X86FastcallCall', 65), +] + +IntPredicate = [ + ('EQ', 32), + ('NE', 33), + ('UGT', 34), + ('UGE', 35), + ('ULT', 36), + ('ULE', 37), + ('SGT', 38), + ('SGE', 39), + ('SLT', 40), + ('SLE', 41), +] + +RealPredicate = [ + ('PredicateFalse', 0), + ('OEQ', 1), + ('OGT', 2), + ('OGE', 3), + ('OLT', 4), + ('OLE', 5), + ('ONE', 6), + ('ORD', 7), + ('UNO', 8), + ('UEQ', 9), + ('UGT', 10), + ('UGE', 11), + ('ULT', 12), + ('ULE', 13), + ('UNE', 14), + ('PredicateTrue', 15), +] + +LandingPadClauseTy = [ + ('Catch', 0), + ('Filter', 1), +] diff --git a/bindings/python/llvm/object.py b/bindings/python/llvm/object.py new file mode 100644 index 00000000..473aa3a1 --- /dev/null +++ b/bindings/python/llvm/object.py @@ -0,0 +1,523 @@ +#===- object.py - Python Object Bindings --------------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +r""" +Object File Interface +===================== + +This module provides an interface for reading information from object files +(e.g. binary executables and libraries). + +Using this module, you can obtain information about an object file's sections, +symbols, and relocations. These are represented by the classes ObjectFile, +Section, Symbol, and Relocation, respectively. + +Usage +----- + +The only way to use this module is to start by creating an ObjectFile. You can +create an ObjectFile by loading a file (specified by its path) or by creating a +llvm.core.MemoryBuffer and loading that. + +Once you have an object file, you can inspect its sections and symbols directly +by calling get_sections() and get_symbols() respectively. To inspect +relocations, call get_relocations() on a Section instance. + +Iterator Interface +------------------ + +The LLVM bindings expose iteration over sections, symbols, and relocations in a +way that only allows one instance to be operated on at a single time. This is +slightly annoying from a Python perspective, as it isn't very Pythonic to have +objects that "expire" but are still active from a dynamic language. + +To aid working around this limitation, each Section, Symbol, and Relocation +instance caches its properties after first access. So, if the underlying +iterator is advanced, the properties can still be obtained provided they have +already been retrieved. + +In addition, we also provide a "cache" method on each class to cache all +available data. You can call this on each obtained instance. Or, you can pass +cache=True to the appropriate get_XXX() method to have this done for you. + +Here are some examples on how to perform iteration: + + obj = ObjectFile(filename='/bin/ls') + + # This is OK. Each Section is only accessed inside its own iteration slot. + section_names = [] + for section in obj.get_sections(): + section_names.append(section.name) + + # This is NOT OK. You perform a lookup after the object has expired. + symbols = list(obj.get_symbols()) + for symbol in symbols: + print symbol.name # This raises because the object has expired. + + # In this example, we mix a working and failing scenario. + symbols = [] + for symbol in obj.get_symbols(): + symbols.append(symbol) + print symbol.name + + for symbol in symbols: + print symbol.name # OK + print symbol.address # NOT OK. We didn't look up this property before. + + # Cache everything up front. + symbols = list(obj.get_symbols(cache=True)) + for symbol in symbols: + print symbol.name # OK + +""" + +from ctypes import c_char_p +from ctypes import c_uint64 + +from .common import CachedProperty +from .common import LLVMObject +from .common import c_object_p +from .common import get_library +from .core import MemoryBuffer + +__all__ = [ + "lib", + "ObjectFile", + "Relocation", + "Section", + "Symbol", +] + +class ObjectFile(LLVMObject): + """Represents an object/binary file.""" + + def __init__(self, filename=None, contents=None): + """Construct an instance from a filename or binary data. + + filename must be a path to a file that can be opened with open(). + contents can be either a native Python buffer type (like str) or a + llvm.core.MemoryBuffer instance. + """ + if contents: + assert isinstance(contents, MemoryBuffer) + + if filename is not None: + contents = MemoryBuffer(filename=filename) + + if contents is None: + raise Exception('No input found.') + + ptr = lib.LLVMCreateObjectFile(contents) + LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisposeObjectFile) + self.take_ownership(contents) + + def get_sections(self, cache=False): + """Obtain the sections in this object file. + + This is a generator for llvm.object.Section instances. + + Sections are exposed as limited-use objects. See the module's + documentation on iterators for more. + """ + sections = lib.LLVMGetSections(self) + last = None + while True: + if lib.LLVMIsSectionIteratorAtEnd(self, sections): + break + + last = Section(sections) + if cache: + last.cache() + + yield last + + lib.LLVMMoveToNextSection(sections) + last.expire() + + if last is not None: + last.expire() + + lib.LLVMDisposeSectionIterator(sections) + + def get_symbols(self, cache=False): + """Obtain the symbols in this object file. + + This is a generator for llvm.object.Symbol instances. + + Each Symbol instance is a limited-use object. See this module's + documentation on iterators for more. + """ + symbols = lib.LLVMGetSymbols(self) + last = None + while True: + if lib.LLVMIsSymbolIteratorAtEnd(self, symbols): + break + + last = Symbol(symbols, self) + if cache: + last.cache() + + yield last + + lib.LLVMMoveToNextSymbol(symbols) + last.expire() + + if last is not None: + last.expire() + + lib.LLVMDisposeSymbolIterator(symbols) + +class Section(LLVMObject): + """Represents a section in an object file.""" + + def __init__(self, ptr): + """Construct a new section instance. + + Section instances can currently only be created from an ObjectFile + instance. Therefore, this constructor should not be used outside of + this module. + """ + LLVMObject.__init__(self, ptr) + + self.expired = False + + @CachedProperty + def name(self): + """Obtain the string name of the section. + + This is typically something like '.dynsym' or '.rodata'. + """ + if self.expired: + raise Exception('Section instance has expired.') + + return lib.LLVMGetSectionName(self) + + @CachedProperty + def size(self): + """The size of the section, in long bytes.""" + if self.expired: + raise Exception('Section instance has expired.') + + return lib.LLVMGetSectionSize(self) + + @CachedProperty + def contents(self): + if self.expired: + raise Exception('Section instance has expired.') + + return lib.LLVMGetSectionContents(self) + + @CachedProperty + def address(self): + """The address of this section, in long bytes.""" + if self.expired: + raise Exception('Section instance has expired.') + + return lib.LLVMGetSectionAddress(self) + + def has_symbol(self, symbol): + """Returns whether a Symbol instance is present in this Section.""" + if self.expired: + raise Exception('Section instance has expired.') + + assert isinstance(symbol, Symbol) + return lib.LLVMGetSectionContainsSymbol(self, symbol) + + def get_relocations(self, cache=False): + """Obtain the relocations in this Section. + + This is a generator for llvm.object.Relocation instances. + + Each instance is a limited used object. See this module's documentation + on iterators for more. + """ + if self.expired: + raise Exception('Section instance has expired.') + + relocations = lib.LLVMGetRelocations(self) + last = None + while True: + if lib.LLVMIsRelocationIteratorAtEnd(self, relocations): + break + + last = Relocation(relocations) + if cache: + last.cache() + + yield last + + lib.LLVMMoveToNextRelocation(relocations) + last.expire() + + if last is not None: + last.expire() + + lib.LLVMDisposeRelocationIterator(relocations) + + def cache(self): + """Cache properties of this Section. + + This can be called as a workaround to the single active Section + limitation. When called, the properties of the Section are fetched so + they are still available after the Section has been marked inactive. + """ + getattr(self, 'name') + getattr(self, 'size') + getattr(self, 'contents') + getattr(self, 'address') + + def expire(self): + """Expire the section. + + This is called internally by the section iterator. + """ + self.expired = True + +class Symbol(LLVMObject): + """Represents a symbol in an object file.""" + def __init__(self, ptr, object_file): + assert isinstance(ptr, c_object_p) + assert isinstance(object_file, ObjectFile) + + LLVMObject.__init__(self, ptr) + + self.expired = False + self._object_file = object_file + + @CachedProperty + def name(self): + """The str name of the symbol. + + This is often a function or variable name. Keep in mind that name + mangling could be in effect. + """ + if self.expired: + raise Exception('Symbol instance has expired.') + + return lib.LLVMGetSymbolName(self) + + @CachedProperty + def address(self): + """The address of this symbol, in long bytes.""" + if self.expired: + raise Exception('Symbol instance has expired.') + + return lib.LLVMGetSymbolAddress(self) + + @CachedProperty + def file_offset(self): + """The offset of this symbol in the file, in long bytes.""" + if self.expired: + raise Exception('Symbol instance has expired.') + + return lib.LLVMGetSymbolFileOffset(self) + + @CachedProperty + def size(self): + """The size of the symbol, in long bytes.""" + if self.expired: + raise Exception('Symbol instance has expired.') + + return lib.LLVMGetSymbolSize(self) + + @CachedProperty + def section(self): + """The Section to which this Symbol belongs. + + The returned Section instance does not expire, unlike Sections that are + commonly obtained through iteration. + + Because this obtains a new section iterator each time it is accessed, + calling this on a number of Symbol instances could be expensive. + """ + sections = lib.LLVMGetSections(self._object_file) + lib.LLVMMoveToContainingSection(sections, self) + + return Section(sections) + + def cache(self): + """Cache all cacheable properties.""" + getattr(self, 'name') + getattr(self, 'address') + getattr(self, 'file_offset') + getattr(self, 'size') + + def expire(self): + """Mark the object as expired to prevent future API accesses. + + This is called internally by this module and it is unlikely that + external callers have a legitimate reason for using it. + """ + self.expired = True + +class Relocation(LLVMObject): + """Represents a relocation definition.""" + def __init__(self, ptr): + """Create a new relocation instance. + + Relocations are created from objects derived from Section instances. + Therefore, this constructor should not be called outside of this + module. See Section.get_relocations() for the proper method to obtain + a Relocation instance. + """ + assert isinstance(ptr, c_object_p) + + LLVMObject.__init__(self, ptr) + + self.expired = False + + @CachedProperty + def address(self): + """The address of this relocation, in long bytes.""" + if self.expired: + raise Exception('Relocation instance has expired.') + + return lib.LLVMGetRelocationAddress(self) + + @CachedProperty + def offset(self): + """The offset of this relocation, in long bytes.""" + if self.expired: + raise Exception('Relocation instance has expired.') + + return lib.LLVMGetRelocationOffset(self) + + @CachedProperty + def symbol(self): + """The Symbol corresponding to this Relocation.""" + if self.expired: + raise Exception('Relocation instance has expired.') + + ptr = lib.LLVMGetRelocationSymbol(self) + return Symbol(ptr) + + @CachedProperty + def type_number(self): + """The relocation type, as a long.""" + if self.expired: + raise Exception('Relocation instance has expired.') + + return lib.LLVMGetRelocationType(self) + + @CachedProperty + def type_name(self): + """The relocation type's name, as a str.""" + if self.expired: + raise Exception('Relocation instance has expired.') + + return lib.LLVMGetRelocationTypeName(self) + + @CachedProperty + def value_string(self): + if self.expired: + raise Exception('Relocation instance has expired.') + + return lib.LLVMGetRelocationValueString(self) + + def expire(self): + """Expire this instance, making future API accesses fail.""" + self.expired = True + + def cache(self): + """Cache all cacheable properties on this instance.""" + getattr(self, 'address') + getattr(self, 'offset') + getattr(self, 'symbol') + getattr(self, 'type') + getattr(self, 'type_name') + getattr(self, 'value_string') + +def register_library(library): + """Register function prototypes with LLVM library instance.""" + + # Object.h functions + library.LLVMCreateObjectFile.argtypes = [MemoryBuffer] + library.LLVMCreateObjectFile.restype = c_object_p + + library.LLVMDisposeObjectFile.argtypes = [ObjectFile] + + library.LLVMGetSections.argtypes = [ObjectFile] + library.LLVMGetSections.restype = c_object_p + + library.LLVMDisposeSectionIterator.argtypes = [c_object_p] + + library.LLVMIsSectionIteratorAtEnd.argtypes = [ObjectFile, c_object_p] + library.LLVMIsSectionIteratorAtEnd.restype = bool + + library.LLVMMoveToNextSection.argtypes = [c_object_p] + + library.LLVMMoveToContainingSection.argtypes = [c_object_p, c_object_p] + + library.LLVMGetSymbols.argtypes = [ObjectFile] + library.LLVMGetSymbols.restype = c_object_p + + library.LLVMDisposeSymbolIterator.argtypes = [c_object_p] + + library.LLVMIsSymbolIteratorAtEnd.argtypes = [ObjectFile, c_object_p] + library.LLVMIsSymbolIteratorAtEnd.restype = bool + + library.LLVMMoveToNextSymbol.argtypes = [c_object_p] + + library.LLVMGetSectionName.argtypes = [c_object_p] + library.LLVMGetSectionName.restype = c_char_p + + library.LLVMGetSectionSize.argtypes = [c_object_p] + library.LLVMGetSectionSize.restype = c_uint64 + + library.LLVMGetSectionContents.argtypes = [c_object_p] + library.LLVMGetSectionContents.restype = c_char_p + + library.LLVMGetSectionAddress.argtypes = [c_object_p] + library.LLVMGetSectionAddress.restype = c_uint64 + + library.LLVMGetSectionContainsSymbol.argtypes = [c_object_p, c_object_p] + library.LLVMGetSectionContainsSymbol.restype = bool + + library.LLVMGetRelocations.argtypes = [c_object_p] + library.LLVMGetRelocations.restype = c_object_p + + library.LLVMDisposeRelocationIterator.argtypes = [c_object_p] + + library.LLVMIsRelocationIteratorAtEnd.argtypes = [c_object_p, c_object_p] + library.LLVMIsRelocationIteratorAtEnd.restype = bool + + library.LLVMMoveToNextRelocation.argtypes = [c_object_p] + + library.LLVMGetSymbolName.argtypes = [Symbol] + library.LLVMGetSymbolName.restype = c_char_p + + library.LLVMGetSymbolAddress.argtypes = [Symbol] + library.LLVMGetSymbolAddress.restype = c_uint64 + + library.LLVMGetSymbolFileOffset.argtypes = [Symbol] + library.LLVMGetSymbolFileOffset.restype = c_uint64 + + library.LLVMGetSymbolSize.argtypes = [Symbol] + library.LLVMGetSymbolSize.restype = c_uint64 + + library.LLVMGetRelocationAddress.argtypes = [c_object_p] + library.LLVMGetRelocationAddress.restype = c_uint64 + + library.LLVMGetRelocationOffset.argtypes = [c_object_p] + library.LLVMGetRelocationOffset.restype = c_uint64 + + library.LLVMGetRelocationSymbol.argtypes = [c_object_p] + library.LLVMGetRelocationSymbol.restype = c_object_p + + library.LLVMGetRelocationType.argtypes = [c_object_p] + library.LLVMGetRelocationType.restype = c_uint64 + + library.LLVMGetRelocationTypeName.argtypes = [c_object_p] + library.LLVMGetRelocationTypeName.restype = c_char_p + + library.LLVMGetRelocationValueString.argtypes = [c_object_p] + library.LLVMGetRelocationValueString.restype = c_char_p + +lib = get_library() +register_library(lib) diff --git a/bindings/python/llvm/tests/__init__.py b/bindings/python/llvm/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bindings/python/llvm/tests/base.py b/bindings/python/llvm/tests/base.py new file mode 100644 index 00000000..194f1a41 --- /dev/null +++ b/bindings/python/llvm/tests/base.py @@ -0,0 +1,38 @@ +import os.path +import unittest + +POSSIBLE_TEST_BINARIES = [ + 'libreadline.so.5', + 'libreadline.so.6', +] + +POSSIBLE_TEST_BINARY_PATHS = [ + '/usr/lib/debug', + '/lib', + '/usr/lib', + '/usr/local/lib', + '/lib/i386-linux-gnu', +] + +class TestBase(unittest.TestCase): + def get_test_binary(self): + """Helper to obtain a test binary for object file testing. + + FIXME Support additional, highly-likely targets or create one + ourselves. + """ + for d in POSSIBLE_TEST_BINARY_PATHS: + for lib in POSSIBLE_TEST_BINARIES: + path = os.path.join(d, lib) + + if os.path.exists(path): + return path + + raise Exception('No suitable test binaries available!') + get_test_binary.__test__ = False + + def get_test_file(self): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_file") + + def get_test_bc(self): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.bc") diff --git a/bindings/python/llvm/tests/test.bc b/bindings/python/llvm/tests/test.bc new file mode 100644 index 00000000..8d3d28fb Binary files /dev/null and b/bindings/python/llvm/tests/test.bc differ diff --git a/bindings/python/llvm/tests/test_bitreader.py b/bindings/python/llvm/tests/test_bitreader.py new file mode 100644 index 00000000..d5850091 --- /dev/null +++ b/bindings/python/llvm/tests/test_bitreader.py @@ -0,0 +1,15 @@ +from .base import TestBase +from ..core import OpCode +from ..core import MemoryBuffer +from ..core import PassRegistry +from ..core import Context +from ..core import Module +from ..bit_reader import parse_bitcode + +class TestBitReader(TestBase): + + def test_parse_bitcode(self): + source = self.get_test_bc() + m = parse_bitcode(MemoryBuffer(filename=source)) + print m.target + print m.datalayout diff --git a/bindings/python/llvm/tests/test_core.py b/bindings/python/llvm/tests/test_core.py new file mode 100644 index 00000000..63f84c82 --- /dev/null +++ b/bindings/python/llvm/tests/test_core.py @@ -0,0 +1,130 @@ +from .base import TestBase +from ..core import OpCode +from ..core import MemoryBuffer +from ..core import PassRegistry +from ..core import Context +from ..core import Module +from ..bit_reader import parse_bitcode + +class TestCore(TestBase): + def test_opcode(self): + self.assertTrue(hasattr(OpCode, 'Ret')) + self.assertTrue(isinstance(OpCode.Ret, OpCode)) + self.assertEqual(OpCode.Ret.value, 1) + + op = OpCode.from_value(1) + self.assertTrue(isinstance(op, OpCode)) + self.assertEqual(op, OpCode.Ret) + + def test_memory_buffer_create_from_file(self): + source = self.get_test_file() + + MemoryBuffer(filename=source) + + def test_memory_buffer_failing(self): + with self.assertRaises(Exception): + MemoryBuffer(filename="/hopefully/this/path/doesnt/exist") + + def test_memory_buffer_len(self): + source = self.get_test_file() + m = MemoryBuffer(filename=source) + self.assertEqual(len(m), 50) + + def test_create_passregistry(self): + PassRegistry() + + def test_create_context(self): + Context.GetGlobalContext() + + def test_create_module_with_name(self): + # Make sure we can not create a module without a LLVMModuleRef. + with self.assertRaises(TypeError): + m = Module() + m = Module.CreateWithName("test-module") + + def test_module_getset_datalayout(self): + m = Module.CreateWithName("test-module") + dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32" + m.datalayout = dl + self.assertEqual(m.datalayout, dl) + + def test_module_getset_target(self): + m = Module.CreateWithName("test-module") + target = "thumbv7-apple-ios5.0.0" + m.target = target + self.assertEqual(m.target, target) + + def test_module_print_module_to_file(self): + m = Module.CreateWithName("test") + dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32" + m.datalayout = dl + target = "thumbv7-apple-ios5.0.0" + m.target = target + m.print_module_to_file("test2.ll") + + def test_module_function_iteration(self): + m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc())) + i = 0 + functions = ["f", "f2", "f3", "f4", "f5", "f6", "g1", "g2", "h1", "h2", + "h3"] + # Forward + for f in m: + self.assertEqual(f.name, functions[i]) + f.dump() + i += 1 + # Backwards + for f in reversed(m): + i -= 1 + self.assertEqual(f.name, functions[i]) + f.dump() + + def test_function_basicblock_iteration(self): + m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc())) + i = 0 + + bb_list = ['b1', 'b2', 'end'] + + f = m.first + while f.name != "f6": + f = f.next + + # Forward + for bb in f: + self.assertEqual(bb.name, bb_list[i]) + bb.dump() + i += 1 + + # Backwards + for bb in reversed(f): + i -= 1 + self.assertEqual(bb.name, bb_list[i]) + bb.dump() + + def test_basicblock_instruction_iteration(self): + m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc())) + i = 0 + + inst_list = [('arg1', OpCode.ExtractValue), + ('arg2', OpCode.ExtractValue), + ('', OpCode.Call), + ('', OpCode.Ret)] + + bb = m.first.first + + # Forward + for inst in bb: + self.assertEqual(inst.name, inst_list[i][0]) + self.assertEqual(inst.opcode, inst_list[i][1]) + for op in range(len(inst)): + o = inst.get_operand(op) + print o.name + o.dump() + inst.dump() + i += 1 + + # Backwards + for inst in reversed(bb): + i -= 1 + self.assertEqual(inst.name, inst_list[i][0]) + self.assertEqual(inst.opcode, inst_list[i][1]) + inst.dump() diff --git a/bindings/python/llvm/tests/test_disassembler.py b/bindings/python/llvm/tests/test_disassembler.py new file mode 100644 index 00000000..e960dc0b --- /dev/null +++ b/bindings/python/llvm/tests/test_disassembler.py @@ -0,0 +1,43 @@ +from .base import TestBase + +from ..disassembler import Disassembler, Option_UseMarkup + +class TestDisassembler(TestBase): + def test_instantiate(self): + Disassembler('i686-apple-darwin9') + + def test_basic(self): + sequence = '\x67\xe3\x81' # jcxz -127 + triple = 'i686-apple-darwin9' + + disassembler = Disassembler(triple) + + count, s = disassembler.get_instruction(sequence) + self.assertEqual(count, 3) + self.assertEqual(s, '\tjcxz\t-127') + + def test_nonexistant_triple(self): + with self.assertRaisesRegexp(Exception, "Could not obtain disassembler for triple"): + Disassembler("nonexistant-triple-raises") + + def test_get_instructions(self): + sequence = '\x67\xe3\x81\x01\xc7' # jcxz -127; addl %eax, %edi + + disassembler = Disassembler('i686-apple-darwin9') + + instructions = list(disassembler.get_instructions(sequence)) + self.assertEqual(len(instructions), 2) + + self.assertEqual(instructions[0], (0, 3, '\tjcxz\t-127')) + self.assertEqual(instructions[1], (3, 2, '\taddl\t%eax, %edi')) + + def test_set_options(self): + sequence = '\x10\x40\x2d\xe9' + triple = 'arm-linux-android' + + disassembler = Disassembler(triple) + disassembler.set_options(Option_UseMarkup) + count, s = disassembler.get_instruction(sequence) + print s + self.assertEqual(count, 4) + self.assertEqual(s, '\tpush\t{, }') diff --git a/bindings/python/llvm/tests/test_file b/bindings/python/llvm/tests/test_file new file mode 100644 index 00000000..6c9b0385 --- /dev/null +++ b/bindings/python/llvm/tests/test_file @@ -0,0 +1 @@ +I,"ìcAGðxq‘ÑÔ¹d«±ùà§vl¥À\»L>šg>`ö©ÿ©`‡wÉ© \ No newline at end of file diff --git a/bindings/python/llvm/tests/test_object.py b/bindings/python/llvm/tests/test_object.py new file mode 100644 index 00000000..7ff981b6 --- /dev/null +++ b/bindings/python/llvm/tests/test_object.py @@ -0,0 +1,67 @@ +from .base import TestBase +from ..object import ObjectFile +from ..object import Relocation +from ..object import Section +from ..object import Symbol + +class TestObjectFile(TestBase): + def get_object_file(self): + source = self.get_test_binary() + return ObjectFile(filename=source) + + def test_create_from_file(self): + self.get_object_file() + + def test_get_sections(self): + o = self.get_object_file() + + count = 0 + for section in o.get_sections(): + count += 1 + assert isinstance(section, Section) + assert isinstance(section.name, str) + assert isinstance(section.size, long) + assert isinstance(section.contents, str) + assert isinstance(section.address, long) + + self.assertGreater(count, 0) + + for section in o.get_sections(): + section.cache() + + def test_get_symbols(self): + o = self.get_object_file() + + count = 0 + for symbol in o.get_symbols(): + count += 1 + assert isinstance(symbol, Symbol) + assert isinstance(symbol.name, str) + assert isinstance(symbol.address, long) + assert isinstance(symbol.size, long) + assert isinstance(symbol.file_offset, long) + + self.assertGreater(count, 0) + + for symbol in o.get_symbols(): + symbol.cache() + + def test_symbol_section_accessor(self): + o = self.get_object_file() + + for symbol in o.get_symbols(): + section = symbol.section + assert isinstance(section, Section) + + break + + def test_get_relocations(self): + o = self.get_object_file() + for section in o.get_sections(): + for relocation in section.get_relocations(): + assert isinstance(relocation, Relocation) + assert isinstance(relocation.address, long) + assert isinstance(relocation.offset, long) + assert isinstance(relocation.type_number, long) + assert isinstance(relocation.type_name, str) + assert isinstance(relocation.value_string, str) diff --git a/cmake/README b/cmake/README new file mode 100644 index 00000000..4aafdbf3 --- /dev/null +++ b/cmake/README @@ -0,0 +1 @@ +See docs/CMake.html for instructions on how to build LLVM with CMake. diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake new file mode 100755 index 00000000..dc991a23 --- /dev/null +++ b/cmake/config-ix.cmake @@ -0,0 +1,500 @@ +if( WIN32 AND NOT CYGWIN ) + # We consider Cygwin as another Unix + set(PURE_WINDOWS 1) +endif() + +include(CheckIncludeFile) +include(CheckIncludeFileCXX) +include(CheckLibraryExists) +include(CheckSymbolExists) +include(CheckFunctionExists) +include(CheckCXXSourceCompiles) +include(TestBigEndian) + +if( UNIX AND NOT BEOS ) + # Used by check_symbol_exists: + set(CMAKE_REQUIRED_LIBRARIES m) +endif() + +# Helper macros and functions +macro(add_cxx_include result files) + set(${result} "") + foreach (file_name ${files}) + set(${result} "${${result}}#include<${file_name}>\n") + endforeach() +endmacro(add_cxx_include files result) + +function(check_type_exists type files variable) + add_cxx_include(includes "${files}") + CHECK_CXX_SOURCE_COMPILES(" + ${includes} ${type} typeVar; + int main() { + return 0; + } + " ${variable}) +endfunction() + +# include checks +check_include_file_cxx(cxxabi.h HAVE_CXXABI_H) +check_include_file(dirent.h HAVE_DIRENT_H) +check_include_file(dlfcn.h HAVE_DLFCN_H) +check_include_file(errno.h HAVE_ERRNO_H) +check_include_file(execinfo.h HAVE_EXECINFO_H) +check_include_file(fcntl.h HAVE_FCNTL_H) +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(limits.h HAVE_LIMITS_H) +check_include_file(malloc.h HAVE_MALLOC_H) +check_include_file(malloc/malloc.h HAVE_MALLOC_MALLOC_H) +check_include_file(ndir.h HAVE_NDIR_H) +if( NOT PURE_WINDOWS ) + check_include_file(pthread.h HAVE_PTHREAD_H) +endif() +check_include_file(sanitizer/msan_interface.h HAVE_SANITIZER_MSAN_INTERFACE_H) +check_include_file(signal.h HAVE_SIGNAL_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(sys/dir.h HAVE_SYS_DIR_H) +check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H) +check_include_file(sys/mman.h HAVE_SYS_MMAN_H) +check_include_file(sys/ndir.h HAVE_SYS_NDIR_H) +check_include_file(sys/param.h HAVE_SYS_PARAM_H) +check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/time.h HAVE_SYS_TIME_H) +check_include_file(sys/uio.h HAVE_SYS_UIO_H) +check_include_file(sys/wait.h HAVE_SYS_WAIT_H) +check_include_file(termios.h HAVE_TERMIOS_H) +check_include_file(unistd.h HAVE_UNISTD_H) +check_include_file(utime.h HAVE_UTIME_H) +check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H) +check_include_file(zlib.h HAVE_ZLIB_H) +check_include_file(fenv.h HAVE_FENV_H) +check_symbol_exists(FE_ALL_EXCEPT "fenv.h" HAVE_DECL_FE_ALL_EXCEPT) +check_symbol_exists(FE_INEXACT "fenv.h" HAVE_DECL_FE_INEXACT) + +check_include_file(mach/mach.h HAVE_MACH_MACH_H) +check_include_file(mach-o/dyld.h HAVE_MACH_O_DYLD_H) + +# library checks +if( NOT PURE_WINDOWS ) + check_library_exists(pthread pthread_create "" HAVE_LIBPTHREAD) + if (HAVE_LIBPTHREAD) + check_library_exists(pthread pthread_getspecific "" HAVE_PTHREAD_GETSPECIFIC) + check_library_exists(pthread pthread_rwlock_init "" HAVE_PTHREAD_RWLOCK_INIT) + check_library_exists(pthread pthread_mutex_lock "" HAVE_PTHREAD_MUTEX_LOCK) + else() + # this could be Android + check_library_exists(c pthread_create "" PTHREAD_IN_LIBC) + if (PTHREAD_IN_LIBC) + check_library_exists(c pthread_getspecific "" HAVE_PTHREAD_GETSPECIFIC) + check_library_exists(c pthread_rwlock_init "" HAVE_PTHREAD_RWLOCK_INIT) + check_library_exists(c pthread_mutex_lock "" HAVE_PTHREAD_MUTEX_LOCK) + endif() + endif() + check_library_exists(dl dlopen "" HAVE_LIBDL) + check_library_exists(rt clock_gettime "" HAVE_LIBRT) + if (LLVM_ENABLE_ZLIB) + check_library_exists(z compress2 "" HAVE_LIBZ) + else() + set(HAVE_LIBZ 0) + endif() + if(LLVM_ENABLE_TERMINFO) + set(HAVE_TERMINFO 0) + foreach(library tinfo terminfo curses ncurses ncursesw) + string(TOUPPER ${library} library_suffix) + check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix}) + if(HAVE_TERMINFO_${library_suffix}) + set(HAVE_TERMINFO 1) + set(TERMINFO_LIBS "${library}") + break() + endif() + endforeach() + else() + set(HAVE_TERMINFO 0) + endif() +endif() + +# function checks +check_symbol_exists(arc4random "stdlib.h" HAVE_ARC4RANDOM) +check_symbol_exists(backtrace "execinfo.h" HAVE_BACKTRACE) +check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE) +check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE) +check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT) +check_symbol_exists(isatty unistd.h HAVE_ISATTY) +check_symbol_exists(isinf cmath HAVE_ISINF_IN_CMATH) +check_symbol_exists(isinf math.h HAVE_ISINF_IN_MATH_H) +check_symbol_exists(finite ieeefp.h HAVE_FINITE_IN_IEEEFP_H) +check_symbol_exists(isnan cmath HAVE_ISNAN_IN_CMATH) +check_symbol_exists(isnan math.h HAVE_ISNAN_IN_MATH_H) +check_symbol_exists(ceilf math.h HAVE_CEILF) +check_symbol_exists(floorf math.h HAVE_FLOORF) +check_symbol_exists(fmodf math.h HAVE_FMODF) +check_symbol_exists(log math.h HAVE_LOG) +check_symbol_exists(log2 math.h HAVE_LOG2) +check_symbol_exists(log10 math.h HAVE_LOG10) +check_symbol_exists(exp math.h HAVE_EXP) +check_symbol_exists(exp2 math.h HAVE_EXP2) +check_symbol_exists(exp10 math.h HAVE_EXP10) +check_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS) +check_symbol_exists(futimes sys/time.h HAVE_FUTIMES) +if( HAVE_SETJMP_H ) + check_symbol_exists(longjmp setjmp.h HAVE_LONGJMP) + check_symbol_exists(setjmp setjmp.h HAVE_SETJMP) + check_symbol_exists(siglongjmp setjmp.h HAVE_SIGLONGJMP) + check_symbol_exists(sigsetjmp setjmp.h HAVE_SIGSETJMP) +endif() +if( HAVE_SYS_UIO_H ) + check_symbol_exists(writev sys/uio.h HAVE_WRITEV) +endif() +check_symbol_exists(nearbyintf math.h HAVE_NEARBYINTF) +check_symbol_exists(mallinfo malloc.h HAVE_MALLINFO) +check_symbol_exists(malloc_zone_statistics malloc/malloc.h + HAVE_MALLOC_ZONE_STATISTICS) +check_symbol_exists(mkdtemp "stdlib.h;unistd.h" HAVE_MKDTEMP) +check_symbol_exists(mkstemp "stdlib.h;unistd.h" HAVE_MKSTEMP) +check_symbol_exists(mktemp "stdlib.h;unistd.h" HAVE_MKTEMP) +check_symbol_exists(closedir "sys/types.h;dirent.h" HAVE_CLOSEDIR) +check_symbol_exists(opendir "sys/types.h;dirent.h" HAVE_OPENDIR) +check_symbol_exists(readdir "sys/types.h;dirent.h" HAVE_READDIR) +check_symbol_exists(getcwd unistd.h HAVE_GETCWD) +check_symbol_exists(gettimeofday sys/time.h HAVE_GETTIMEOFDAY) +check_symbol_exists(getrlimit "sys/types.h;sys/time.h;sys/resource.h" HAVE_GETRLIMIT) +check_symbol_exists(posix_spawn spawn.h HAVE_POSIX_SPAWN) +check_symbol_exists(pread unistd.h HAVE_PREAD) +check_symbol_exists(realpath stdlib.h HAVE_REALPATH) +check_symbol_exists(sbrk unistd.h HAVE_SBRK) +check_symbol_exists(srand48 stdlib.h HAVE_RAND48_SRAND48) +if( HAVE_RAND48_SRAND48 ) + check_symbol_exists(lrand48 stdlib.h HAVE_RAND48_LRAND48) + if( HAVE_RAND48_LRAND48 ) + check_symbol_exists(drand48 stdlib.h HAVE_RAND48_DRAND48) + if( HAVE_RAND48_DRAND48 ) + set(HAVE_RAND48 1 CACHE INTERNAL "are srand48/lrand48/drand48 available?") + endif() + endif() +endif() +check_symbol_exists(strtoll stdlib.h HAVE_STRTOLL) +check_symbol_exists(strtoq stdlib.h HAVE_STRTOQ) +check_symbol_exists(strerror string.h HAVE_STRERROR) +check_symbol_exists(strerror_r string.h HAVE_STRERROR_R) +check_symbol_exists(strerror_s string.h HAVE_DECL_STRERROR_S) +check_symbol_exists(setenv stdlib.h HAVE_SETENV) +if( PURE_WINDOWS ) + check_symbol_exists(_chsize_s io.h HAVE__CHSIZE_S) + + check_function_exists(_alloca HAVE__ALLOCA) + check_function_exists(__alloca HAVE___ALLOCA) + check_function_exists(__chkstk HAVE___CHKSTK) + check_function_exists(___chkstk HAVE____CHKSTK) + + check_function_exists(__ashldi3 HAVE___ASHLDI3) + check_function_exists(__ashrdi3 HAVE___ASHRDI3) + check_function_exists(__divdi3 HAVE___DIVDI3) + check_function_exists(__fixdfdi HAVE___FIXDFDI) + check_function_exists(__fixsfdi HAVE___FIXSFDI) + check_function_exists(__floatdidf HAVE___FLOATDIDF) + check_function_exists(__lshrdi3 HAVE___LSHRDI3) + check_function_exists(__moddi3 HAVE___MODDI3) + check_function_exists(__udivdi3 HAVE___UDIVDI3) + check_function_exists(__umoddi3 HAVE___UMODDI3) + + check_function_exists(__main HAVE___MAIN) + check_function_exists(__cmpdi2 HAVE___CMPDI2) +endif() +if( HAVE_DLFCN_H ) + if( HAVE_LIBDL ) + list(APPEND CMAKE_REQUIRED_LIBRARIES dl) + endif() + check_symbol_exists(dlerror dlfcn.h HAVE_DLERROR) + check_symbol_exists(dlopen dlfcn.h HAVE_DLOPEN) + if( HAVE_LIBDL ) + list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES dl) + endif() +endif() + +check_symbol_exists(__GLIBC__ stdio.h LLVM_USING_GLIBC) +if( LLVM_USING_GLIBC ) + add_llvm_definitions( -D_GNU_SOURCE ) +endif() + +set(headers "sys/types.h") + +if (HAVE_INTTYPES_H) + set(headers ${headers} "inttypes.h") +endif() + +if (HAVE_STDINT_H) + set(headers ${headers} "stdint.h") +endif() + +check_type_exists(int64_t "${headers}" HAVE_INT64_T) +check_type_exists(uint64_t "${headers}" HAVE_UINT64_T) +check_type_exists(u_int64_t "${headers}" HAVE_U_INT64_T) + +# available programs checks +function(llvm_find_program name) + string(TOUPPER ${name} NAME) + string(REGEX REPLACE "\\." "_" NAME ${NAME}) + + find_program(LLVM_PATH_${NAME} NAMES ${ARGV}) + mark_as_advanced(LLVM_PATH_${NAME}) + if(LLVM_PATH_${NAME}) + set(HAVE_${NAME} 1 CACHE INTERNAL "Is ${name} available ?") + mark_as_advanced(HAVE_${NAME}) + else(LLVM_PATH_${NAME}) + set(HAVE_${NAME} "" CACHE INTERNAL "Is ${name} available ?") + endif(LLVM_PATH_${NAME}) +endfunction() + +llvm_find_program(gv) +llvm_find_program(circo) +llvm_find_program(twopi) +llvm_find_program(neato) +llvm_find_program(fdp) +llvm_find_program(dot) +llvm_find_program(dotty) +llvm_find_program(xdot xdot.py) +llvm_find_program(Graphviz) + +if( LLVM_ENABLE_FFI ) + find_path(FFI_INCLUDE_PATH ffi.h PATHS ${FFI_INCLUDE_DIR}) + if( FFI_INCLUDE_PATH ) + set(FFI_HEADER ffi.h CACHE INTERNAL "") + set(HAVE_FFI_H 1 CACHE INTERNAL "") + else() + find_path(FFI_INCLUDE_PATH ffi/ffi.h PATHS ${FFI_INCLUDE_DIR}) + if( FFI_INCLUDE_PATH ) + set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "") + set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "") + endif() + endif() + + if( NOT FFI_HEADER ) + message(FATAL_ERROR "libffi includes are not found.") + endif() + + find_library(FFI_LIBRARY_PATH ffi PATHS ${FFI_LIBRARY_DIR}) + if( NOT FFI_LIBRARY_PATH ) + message(FATAL_ERROR "libffi is not found.") + endif() + + list(APPEND CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARY_PATH}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${FFI_INCLUDE_PATH}) + check_symbol_exists(ffi_call ${FFI_HEADER} HAVE_FFI_CALL) + list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES ${FFI_INCLUDE_PATH}) + list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARY_PATH}) +else() + unset(HAVE_FFI_FFI_H CACHE) + unset(HAVE_FFI_H CACHE) + unset(HAVE_FFI_CALL CACHE) +endif( LLVM_ENABLE_FFI ) + +# Define LLVM_HAS_ATOMICS if gcc or MSVC atomic builtins are supported. +include(CheckAtomic) + +if( LLVM_ENABLE_PIC ) + set(ENABLE_PIC 1) +else() + set(ENABLE_PIC 0) +endif() + +find_package(LibXml2) +if (LIBXML2_FOUND) + set(CLANG_HAVE_LIBXML 1) + # When cross-compiling, liblzma is not detected as a dependency for libxml2, + # which makes linking c-index-test fail. But for native builds, all libraries + # are installed and checked by CMake before Makefiles are generated and everything + # works according to the plan. However, if a -llzma is added to native builds, + # an additional requirement on the static liblzma.a is required, but will not + # be checked by CMake, breaking native compilation. + # Since this is only pertinent to cross-compilations, and there's no way CMake + # can check for every foreign library on every OS, we add the dep and warn the dev. + if ( CMAKE_CROSSCOMPILING ) + if (NOT PC_LIBXML_VERSION VERSION_LESS "2.8.0") + message(STATUS "Adding LZMA as a dep to XML2 for cross-compilation, make sure liblzma.a is available.") + set(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} "-llzma") + endif () + endif () +endif () + +include(CheckCXXCompilerFlag) + +check_cxx_compiler_flag("-Wno-variadic-macros" SUPPORTS_NO_VARIADIC_MACROS_FLAG) + +set(USE_NO_MAYBE_UNINITIALIZED 0) +set(USE_NO_UNINITIALIZED 0) + +# Disable gcc's potentially uninitialized use analysis as it presents lots of +# false positives. +if (CMAKE_COMPILER_IS_GNUCXX) + check_cxx_compiler_flag("-Wmaybe-uninitialized" HAS_MAYBE_UNINITIALIZED) + if (HAS_MAYBE_UNINITIALIZED) + set(USE_NO_MAYBE_UNINITIALIZED 1) + else() + # Only recent versions of gcc make the distinction between -Wuninitialized + # and -Wmaybe-uninitialized. If -Wmaybe-uninitialized isn't supported, just + # turn off all uninitialized use warnings. + check_cxx_compiler_flag("-Wuninitialized" HAS_UNINITIALIZED) + set(USE_NO_UNINITIALIZED ${HAS_UNINITIALIZED}) + endif() +endif() + +# By default, we target the host, but this can be overridden at CMake +# invocation time. +include(GetHostTriple) +get_host_triple(LLVM_INFERRED_HOST_TRIPLE) + +set(LLVM_HOST_TRIPLE "${LLVM_INFERRED_HOST_TRIPLE}" CACHE STRING + "Host on which LLVM binaries will run") + +# Determine the native architecture. +string(TOLOWER "${LLVM_TARGET_ARCH}" LLVM_NATIVE_ARCH) +if( LLVM_NATIVE_ARCH STREQUAL "host" ) + string(REGEX MATCH "^[^-]*" LLVM_NATIVE_ARCH ${LLVM_HOST_TRIPLE}) +endif () + +if (LLVM_NATIVE_ARCH MATCHES "i[2-6]86") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "x86") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "amd64") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "x86_64") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH MATCHES "sparc") + set(LLVM_NATIVE_ARCH Sparc) +elseif (LLVM_NATIVE_ARCH MATCHES "powerpc") + set(LLVM_NATIVE_ARCH PowerPC) +elseif (LLVM_NATIVE_ARCH MATCHES "aarch64") + set(LLVM_NATIVE_ARCH AArch64) +elseif (LLVM_NATIVE_ARCH MATCHES "arm") + set(LLVM_NATIVE_ARCH ARM) +elseif (LLVM_NATIVE_ARCH MATCHES "mips") + set(LLVM_NATIVE_ARCH Mips) +elseif (LLVM_NATIVE_ARCH MATCHES "xcore") + set(LLVM_NATIVE_ARCH XCore) +elseif (LLVM_NATIVE_ARCH MATCHES "msp430") + set(LLVM_NATIVE_ARCH MSP430) +elseif (LLVM_NATIVE_ARCH MATCHES "hexagon") + set(LLVM_NATIVE_ARCH Hexagon) +elseif (LLVM_NATIVE_ARCH MATCHES "s390x") + set(LLVM_NATIVE_ARCH SystemZ) +else () + message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}") +endif () + +# If build targets includes "host", then replace with native architecture. +list(FIND LLVM_TARGETS_TO_BUILD "host" idx) +if( NOT idx LESS 0 ) + list(REMOVE_AT LLVM_TARGETS_TO_BUILD ${idx}) + list(APPEND LLVM_TARGETS_TO_BUILD ${LLVM_NATIVE_ARCH}) + list(REMOVE_DUPLICATES LLVM_TARGETS_TO_BUILD) +endif() + +list(FIND LLVM_TARGETS_TO_BUILD ${LLVM_NATIVE_ARCH} NATIVE_ARCH_IDX) +if (NATIVE_ARCH_IDX EQUAL -1) + message(STATUS + "Native target ${LLVM_NATIVE_ARCH} is not selected; lli will not JIT code") +else () + message(STATUS "Native target architecture is ${LLVM_NATIVE_ARCH}") + set(LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target) + set(LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo) + set(LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC) + set(LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter) + + # We don't have an ASM parser for all architectures yet. + if (EXISTS ${CMAKE_SOURCE_DIR}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/CMakeLists.txt) + set(LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser) + endif () + + # We don't have an disassembler for all architectures yet. + if (EXISTS ${CMAKE_SOURCE_DIR}/lib/Target/${LLVM_NATIVE_ARCH}/Disassembler/CMakeLists.txt) + set(LLVM_NATIVE_DISASSEMBLER LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler) + endif () +endif () + +if( MINGW ) + set(HAVE_LIBIMAGEHLP 1) + set(HAVE_LIBPSAPI 1) + set(HAVE_LIBSHELL32 1) + # TODO: Check existence of libraries. + # include(CheckLibraryExists) + # CHECK_LIBRARY_EXISTS(imagehlp ??? . HAVE_LIBIMAGEHLP) +endif( MINGW ) + +if (NOT HAVE_STRTOLL) + # Use _strtoi64 if strtoll is not available. + check_symbol_exists(_strtoi64 stdlib.h have_strtoi64) + if (have_strtoi64) + set(HAVE_STRTOLL 1) + set(strtoll "_strtoi64") + set(strtoull "_strtoui64") + endif () +endif () + +if( MSVC ) + set(SHLIBEXT ".lib") + set(stricmp "_stricmp") + set(strdup "_strdup") +endif( MSVC ) + +if( PURE_WINDOWS ) + CHECK_CXX_SOURCE_COMPILES(" + #include + #include + extern \"C\" void foo(PENUMLOADED_MODULES_CALLBACK); + extern \"C\" void foo(BOOL(CALLBACK*)(PCSTR,ULONG_PTR,ULONG,PVOID)); + int main(){return 0;}" + HAVE_ELMCB_PCSTR) + if( HAVE_ELMCB_PCSTR ) + set(WIN32_ELMCB_PCSTR "PCSTR") + else() + set(WIN32_ELMCB_PCSTR "PSTR") + endif() +endif( PURE_WINDOWS ) + +# FIXME: Signal handler return type, currently hardcoded to 'void' +set(RETSIGTYPE void) + +if( LLVM_ENABLE_THREADS ) + # Check if threading primitives aren't supported on this platform + if( NOT HAVE_PTHREAD_H AND NOT WIN32 ) + set(LLVM_ENABLE_THREADS 0) + endif() +endif() + +if( LLVM_ENABLE_THREADS ) + message(STATUS "Threads enabled.") +else( LLVM_ENABLE_THREADS ) + message(STATUS "Threads disabled.") +endif() + +if (LLVM_ENABLE_ZLIB ) + # Check if zlib is available in the system. + if ( NOT HAVE_ZLIB_H OR NOT HAVE_LIBZ ) + set(LLVM_ENABLE_ZLIB 0) + endif() +endif() + +set(LLVM_PREFIX ${CMAKE_INSTALL_PREFIX}) + +if (LLVM_ENABLE_DOXYGEN) + message(STATUS "Doxygen enabled.") + find_package(Doxygen) + + if (DOXYGEN_FOUND) + # If we find doxygen and we want to enable doxygen by default create a + # global aggregate doxygen target for generating llvm and any/all + # subprojects doxygen documentation. + if (LLVM_BUILD_DOCS) + add_custom_target(doxygen ALL) + endif() + + option(LLVM_DOXYGEN_EXTERNAL_SEARCH "Enable doxygen external search." OFF) + if (LLVM_DOXYGEN_EXTERNAL_SEARCH) + set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external searhc.") + set(LLVM_DOXYGEN_SEARCH_MAPPINGS "" CACHE STRING "Doxygen Search Mappings") + endif() + endif() +else() + message(STATUS "Doxygen disabled.") +endif() diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake new file mode 100644 index 00000000..34e40172 --- /dev/null +++ b/cmake/modules/AddLLVM.cmake @@ -0,0 +1,366 @@ +include(LLVMParseArguments) +include(LLVMProcessSources) +include(LLVM-Config) + +macro(add_llvm_library name) + llvm_process_sources( ALL_FILES ${ARGN} ) + add_library( ${name} ${ALL_FILES} ) + set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} ) + if( LLVM_COMMON_DEPENDS ) + add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) + endif( LLVM_COMMON_DEPENDS ) + + if( BUILD_SHARED_LIBS ) + llvm_config( ${name} ${LLVM_LINK_COMPONENTS} ) + if (MSVC) + set_target_properties(${name} + PROPERTIES + IMPORT_SUFFIX ".imp") + endif () + endif() + + # Ensure that the system libraries always comes last on the + # list. Without this, linking the unit tests on MinGW fails. + link_system_libs( ${name} ) + + if( EXCLUDE_FROM_ALL ) + set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON) + else() + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LTO") + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + endif() + endif() + set_target_properties(${name} PROPERTIES FOLDER "Libraries") + + # Add the explicit dependency information for this library. + # + # It would be nice to verify that we have the dependencies for this library + # name, but using get_property(... SET) doesn't suffice to determine if a + # property has been set to an empty value. + get_property(lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${name}) + target_link_libraries(${name} ${lib_deps}) +endmacro(add_llvm_library name) + +macro(add_llvm_loadable_module name) + if( NOT LLVM_ON_UNIX OR CYGWIN ) + message(STATUS "Loadable modules not supported on this platform. +${name} ignored.") + # Add empty "phony" target + add_custom_target(${name}) + else() + llvm_process_sources( ALL_FILES ${ARGN} ) + if (MODULE) + set(libkind MODULE) + else() + set(libkind SHARED) + endif() + + add_library( ${name} ${libkind} ${ALL_FILES} ) + set_target_properties( ${name} PROPERTIES PREFIX "" ) + + llvm_config( ${name} ${LLVM_LINK_COMPONENTS} ) + link_system_libs( ${name} ) + + if (APPLE) + # Darwin-specific linker flags for loadable modules. + set_target_properties(${name} PROPERTIES + LINK_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress") + endif() + + if( EXCLUDE_FROM_ALL ) + set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON) + else() + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + endif() + endif() + endif() + + set_target_properties(${name} PROPERTIES FOLDER "Loadable modules") +endmacro(add_llvm_loadable_module name) + + +macro(add_llvm_executable name) + llvm_process_sources( ALL_FILES ${ARGN} ) + if( EXCLUDE_FROM_ALL ) + add_executable(${name} EXCLUDE_FROM_ALL ${ALL_FILES}) + else() + add_executable(${name} ${ALL_FILES}) + endif() + set(EXCLUDE_FROM_ALL OFF) + llvm_config( ${name} ${LLVM_LINK_COMPONENTS} ) + if( LLVM_COMMON_DEPENDS ) + add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) + endif( LLVM_COMMON_DEPENDS ) + link_system_libs( ${name} ) +endmacro(add_llvm_executable name) + + +set (LLVM_TOOLCHAIN_TOOLS + llvm-ar + llvm-objdump + ) + +macro(add_llvm_tool name) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR}) + if( NOT LLVM_BUILD_TOOLS ) + set(EXCLUDE_FROM_ALL ON) + endif() + add_llvm_executable(${name} ${ARGN}) + + list(FIND LLVM_TOOLCHAIN_TOOLS ${name} LLVM_IS_${name}_TOOLCHAIN_TOOL) + if (LLVM_IS_${name}_TOOLCHAIN_TOOL GREATER -1 OR NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + if( LLVM_BUILD_TOOLS ) + install(TARGETS ${name} RUNTIME DESTINATION bin) + endif() + endif() + set_target_properties(${name} PROPERTIES FOLDER "Tools") +endmacro(add_llvm_tool name) + + +macro(add_llvm_example name) +# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_EXAMPLES_BINARY_DIR}) + if( NOT LLVM_BUILD_EXAMPLES ) + set(EXCLUDE_FROM_ALL ON) + endif() + add_llvm_executable(${name} ${ARGN}) + if( LLVM_BUILD_EXAMPLES ) + install(TARGETS ${name} RUNTIME DESTINATION examples) + endif() + set_target_properties(${name} PROPERTIES FOLDER "Examples") +endmacro(add_llvm_example name) + + +macro(add_llvm_utility name) + add_llvm_executable(${name} ${ARGN}) + set_target_properties(${name} PROPERTIES FOLDER "Utils") +endmacro(add_llvm_utility name) + + +macro(add_llvm_target target_name) + include_directories(BEFORE + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) + add_llvm_library(LLVM${target_name} ${ARGN} ${TABLEGEN_OUTPUT}) + set( CURRENT_LLVM_TARGET LLVM${target_name} ) +endmacro(add_llvm_target) + +# Add external project that may want to be built as part of llvm such as Clang, +# lld, and Polly. This adds two options. One for the source directory of the +# project, which defaults to ${CMAKE_CURRENT_SOURCE_DIR}/${name}. Another to +# enable or disable building it with everthing else. +# Additional parameter can be specified as the name of directory. +macro(add_llvm_external_project name) + set(add_llvm_external_dir "${ARGN}") + if("${add_llvm_external_dir}" STREQUAL "") + set(add_llvm_external_dir ${name}) + endif() + list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}") + string(REPLACE "-" "_" nameUNDERSCORE ${name}) + string(TOUPPER ${nameUNDERSCORE} nameUPPER) + set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}" + CACHE PATH "Path to ${name} source directory") + if (NOT ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} STREQUAL "" + AND EXISTS ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}/CMakeLists.txt) + option(LLVM_EXTERNAL_${nameUPPER}_BUILD + "Whether to build ${name} as part of LLVM" ON) + if (LLVM_EXTERNAL_${nameUPPER}_BUILD) + add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir}) + endif() + endif() +endmacro(add_llvm_external_project) + +macro(add_llvm_tool_subdirectory name) + list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") + add_subdirectory(${name}) +endmacro(add_llvm_tool_subdirectory) + +macro(ignore_llvm_tool_subdirectory name) + list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") +endmacro(ignore_llvm_tool_subdirectory) + +function(add_llvm_implicit_external_projects) + set(list_of_implicit_subdirs "") + file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*") + foreach(dir ${sub-dirs}) + if(IS_DIRECTORY "${dir}") + list(FIND LLVM_IMPLICIT_PROJECT_IGNORE "${dir}" tool_subdir_ignore) + if( tool_subdir_ignore EQUAL -1 + AND EXISTS "${dir}/CMakeLists.txt") + get_filename_component(fn "${dir}" NAME) + list(APPEND list_of_implicit_subdirs "${fn}") + endif() + endif() + endforeach() + + foreach(external_proj ${list_of_implicit_subdirs}) + add_llvm_external_project("${external_proj}") + endforeach() +endfunction(add_llvm_implicit_external_projects) + +# Generic support for adding a unittest. +function(add_unittest test_suite test_name) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + if( NOT LLVM_BUILD_TESTS ) + set(EXCLUDE_FROM_ALL ON) + endif() + + add_llvm_executable(${test_name} ${ARGN}) + target_link_libraries(${test_name} + gtest + gtest_main + LLVMSupport # gtest needs it for raw_ostream. + ) + + add_dependencies(${test_suite} ${test_name}) + get_target_property(test_suite_folder ${test_suite} FOLDER) + if (NOT ${test_suite_folder} STREQUAL "NOTFOUND") + set_property(TARGET ${test_name} PROPERTY FOLDER "${test_suite_folder}") + endif () + + # Visual Studio 2012 only supports up to 8 template parameters in + # std::tr1::tuple by default, but gtest requires 10 + if (MSVC AND MSVC_VERSION EQUAL 1700) + set_property(TARGET ${test_name} APPEND PROPERTY COMPILE_DEFINITIONS _VARIADIC_MAX=10) + endif () + + include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) + set_property(TARGET ${test_name} APPEND PROPERTY COMPILE_DEFINITIONS GTEST_HAS_RTTI=0) + if (NOT LLVM_ENABLE_THREADS) + set_property(TARGET ${test_name} APPEND PROPERTY COMPILE_DEFINITIONS GTEST_HAS_PTHREAD=0) + endif () + + get_property(target_compile_flags TARGET ${test_name} PROPERTY COMPILE_FLAGS) + if (LLVM_COMPILER_IS_GCC_COMPATIBLE) + set(target_compile_flags "${target_compile_flags} -fno-rtti") + elseif (MSVC) + llvm_replace_compiler_option(target_compile_flags "/GR" "/GR-") + endif () + + if (SUPPORTS_NO_VARIADIC_MACROS_FLAG) + set(target_compile_flags "${target_compile_flags} -Wno-variadic-macros") + endif () + set_property(TARGET ${test_name} PROPERTY COMPILE_FLAGS "${target_compile_flags}") +endfunction() + +# This function provides an automatic way to 'configure'-like generate a file +# based on a set of common and custom variables, specifically targetting the +# variables needed for the 'lit.site.cfg' files. This function bundles the +# common variables that any Lit instance is likely to need, and custom +# variables can be passed in. +function(configure_lit_site_cfg input output) + foreach(c ${LLVM_TARGETS_TO_BUILD}) + set(TARGETS_BUILT "${TARGETS_BUILT} ${c}") + endforeach(c) + set(TARGETS_TO_BUILD ${TARGETS_BUILT}) + + set(SHLIBEXT "${LTDL_SHLIB_EXT}") + set(SHLIBDIR "${LLVM_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}") + + if(BUILD_SHARED_LIBS) + set(LLVM_SHARED_LIBS_ENABLED "1") + else() + set(LLVM_SHARED_LIBS_ENABLED "0") + endif(BUILD_SHARED_LIBS) + + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(SHLIBPATH_VAR "DYLD_LIBRARY_PATH") + else() # Default for all other unix like systems. + # CMake hardcodes the library locaction using rpath. + # Therefore LD_LIBRARY_PATH is not required to run binaries in the + # build dir. We pass it anyways. + set(SHLIBPATH_VAR "LD_LIBRARY_PATH") + endif() + + # Configuration-time: See Unit/lit.site.cfg.in + set(LLVM_BUILD_MODE "%(build_mode)s") + + set(LLVM_SOURCE_DIR ${LLVM_MAIN_SRC_DIR}) + set(LLVM_BINARY_DIR ${LLVM_BINARY_DIR}) + set(LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}/%(build_mode)s") + set(LLVM_LIBS_DIR "${LLVM_BINARY_DIR}/lib/%(build_mode)s") + set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}) + set(ENABLE_SHARED ${LLVM_SHARED_LIBS_ENABLED}) + set(SHLIBPATH_VAR ${SHLIBPATH_VAR}) + + if(LLVM_ENABLE_ASSERTIONS AND NOT MSVC_IDE) + set(ENABLE_ASSERTIONS "1") + else() + set(ENABLE_ASSERTIONS "0") + endif() + + set(HOST_OS ${CMAKE_SYSTEM_NAME}) + set(HOST_ARCH ${CMAKE_SYSTEM_PROCESSOR}) + + if (CLANG_ENABLE_ARCMT) + set(ENABLE_CLANG_ARCMT "1") + else() + set(ENABLE_CLANG_ARCMT "0") + endif() + if (CLANG_ENABLE_REWRITER) + set(ENABLE_CLANG_REWRITER "1") + else() + set(ENABLE_CLANG_REWRITER "0") + endif() + if (CLANG_ENABLE_STATIC_ANALYZER) + set(ENABLE_CLANG_STATIC_ANALYZER "1") + else() + set(ENABLE_CLANG_STATIC_ANALYZER "0") + endif() + + configure_file(${input} ${output} @ONLY) +endfunction() + +# A raw function to create a lit target. This is used to implement the testuite +# management functions. +function(add_lit_target target comment) + parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN}) + set(LIT_ARGS "${ARG_ARGS} ${LLVM_LIT_ARGS}") + separate_arguments(LIT_ARGS) + set(LIT_COMMAND + ${PYTHON_EXECUTABLE} + ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py + --param build_mode=${CMAKE_CFG_INTDIR} + ${LIT_ARGS} + ) + foreach(param ${ARG_PARAMS}) + list(APPEND LIT_COMMAND --param ${param}) + endforeach() + if( ARG_DEPENDS ) + add_custom_target(${target} + COMMAND ${LIT_COMMAND} ${ARG_DEFAULT_ARGS} + COMMENT "${comment}" + ) + add_dependencies(${target} ${ARG_DEPENDS}) + else() + add_custom_target(${target} + COMMAND cmake -E echo "${target} does nothing, no tools built.") + message(STATUS "${target} does nothing.") + endif() +endfunction() + +# A function to add a set of lit test suites to be driven through 'check-*' targets. +function(add_lit_testsuite target comment) + parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN}) + + # EXCLUDE_FROM_ALL excludes the test ${target} out of check-all. + if(NOT EXCLUDE_FROM_ALL) + # Register the testsuites, params and depends for the global check rule. + set_property(GLOBAL APPEND PROPERTY LLVM_LIT_TESTSUITES ${ARG_DEFAULT_ARGS}) + set_property(GLOBAL APPEND PROPERTY LLVM_LIT_PARAMS ${ARG_PARAMS}) + set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS ${ARG_DEPENDS}) + set_property(GLOBAL APPEND PROPERTY LLVM_LIT_EXTRA_ARGS ${ARG_ARGS}) + endif() + + # Produce a specific suffixed check rule. + add_lit_target(${target} ${comment} + ${ARG_DEFAULT_ARGS} + PARAMS ${ARG_PARAMS} + DEPENDS ${ARG_DEPENDS} + ARGS ${ARG_ARGS} + ) +endfunction() diff --git a/cmake/modules/AddLLVMDefinitions.cmake b/cmake/modules/AddLLVMDefinitions.cmake new file mode 100644 index 00000000..33ac9731 --- /dev/null +++ b/cmake/modules/AddLLVMDefinitions.cmake @@ -0,0 +1,13 @@ +# There is no clear way of keeping track of compiler command-line +# options chosen via `add_definitions', so we need our own method for +# using it on tools/llvm-config/CMakeLists.txt. + +# Beware that there is no implementation of remove_llvm_definitions. + +macro(add_llvm_definitions) + # We don't want no semicolons on LLVM_DEFINITIONS: + foreach(arg ${ARGN}) + set(LLVM_DEFINITIONS "${LLVM_DEFINITIONS} ${arg}") + endforeach(arg) + add_definitions( ${ARGN} ) +endmacro(add_llvm_definitions) diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt new file mode 100644 index 00000000..0253952c --- /dev/null +++ b/cmake/modules/CMakeLists.txt @@ -0,0 +1,39 @@ +set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/share/llvm/cmake") +set(LLVM_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) + +get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS) + +foreach(lib ${llvm_libs}) + get_property(llvm_lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${lib}) + set(all_llvm_lib_deps + "${all_llvm_lib_deps}\nset_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${lib} ${llvm_lib_deps})") +endforeach(lib) + +configure_file( + LLVMConfig.cmake.in + ${llvm_cmake_builddir}/LLVMConfig.cmake + @ONLY) + +configure_file( + LLVMConfigVersion.cmake.in + ${llvm_cmake_builddir}/LLVMConfigVersion.cmake + @ONLY) + +if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(FILES + ${llvm_cmake_builddir}/LLVMConfig.cmake + ${llvm_cmake_builddir}/LLVMConfigVersion.cmake + LLVM-Config.cmake + DESTINATION share/llvm/cmake) + + install(DIRECTORY . + DESTINATION share/llvm/cmake + FILES_MATCHING PATTERN *.cmake + PATTERN .svn EXCLUDE + PATTERN LLVMConfig.cmake EXCLUDE + PATTERN LLVMConfigVersion.cmake EXCLUDE + PATTERN LLVM-Config.cmake EXCLUDE + PATTERN GetHostTriple.cmake EXCLUDE + PATTERN VersionFromVCS.cmake EXCLUDE + PATTERN CheckAtomic.cmake EXCLUDE) +endif() diff --git a/cmake/modules/CheckAtomic.cmake b/cmake/modules/CheckAtomic.cmake new file mode 100644 index 00000000..0d63a82b --- /dev/null +++ b/cmake/modules/CheckAtomic.cmake @@ -0,0 +1,29 @@ +# atomic builtins are required for threading support. + +INCLUDE(CheckCXXSourceCompiles) + +CHECK_CXX_SOURCE_COMPILES(" +#ifdef _MSC_VER +#include +#endif +int main() { +#ifdef _MSC_VER + volatile LONG val = 1; + MemoryBarrier(); + InterlockedCompareExchange(&val, 0, 1); + InterlockedIncrement(&val); + InterlockedDecrement(&val); +#else + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); +#endif + return 0; + } +" LLVM_HAS_ATOMICS) + +if( NOT LLVM_HAS_ATOMICS ) + message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") +endif() diff --git a/cmake/modules/ChooseMSVCCRT.cmake b/cmake/modules/ChooseMSVCCRT.cmake new file mode 100644 index 00000000..25ed9c71 --- /dev/null +++ b/cmake/modules/ChooseMSVCCRT.cmake @@ -0,0 +1,106 @@ +# The macro choose_msvc_crt() takes a list of possible +# C runtimes to choose from, in the form of compiler flags, +# to present to the user. (MTd for /MTd, etc) +# +# The macro is invoked at the end of the file. +# +# CMake already sets CRT flags in the CMAKE_CXX_FLAGS_* and +# CMAKE_C_FLAGS_* variables by default. To let the user +# override that for each build type: +# 1. Detect which CRT is already selected, and reflect this in +# LLVM_USE_CRT_* so the user can have a better idea of what +# changes they're making. +# 2. Replace the flags in both variables with the new flag via a regex. +# 3. set() the variables back into the cache so the changes +# are user-visible. + +### Helper macros: ### +macro(make_crt_regex regex crts) + set(${regex} "") + foreach(crt ${${crts}}) + # Trying to match the beginning or end of the string with stuff + # like [ ^]+ didn't work, so use a bunch of parentheses instead. + set(${regex} "${${regex}}|(^| +)/${crt}($| +)") + endforeach(crt) + string(REGEX REPLACE "^\\|" "" ${regex} "${${regex}}") +endmacro(make_crt_regex) + +macro(get_current_crt crt_current regex flagsvar) + # Find the selected-by-CMake CRT for each build type, if any. + # Strip off the leading slash and any whitespace. + string(REGEX MATCH "${${regex}}" ${crt_current} "${${flagsvar}}") + string(REPLACE "/" " " ${crt_current} "${${crt_current}}") + string(STRIP "${${crt_current}}" ${crt_current}) +endmacro(get_current_crt) + +# Replaces or adds a flag to a variable. +# Expects 'flag' to be padded with spaces. +macro(set_flag_in_var flagsvar regex flag) + string(REGEX MATCH "${${regex}}" current_flag "${${flagsvar}}") + if("${current_flag}" STREQUAL "") + set(${flagsvar} "${${flagsvar}}${${flag}}") + else() + string(REGEX REPLACE "${${regex}}" "${${flag}}" ${flagsvar} "${${flagsvar}}") + endif() + string(STRIP "${${flagsvar}}" ${flagsvar}) + # Make sure this change gets reflected in the cache/gui. + # CMake requires the docstring parameter whenever set() touches the cache, + # so get the existing docstring and re-use that. + get_property(flagsvar_docs CACHE ${flagsvar} PROPERTY HELPSTRING) + set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE) +endmacro(set_flag_in_var) + + +macro(choose_msvc_crt MSVC_CRT) + if(LLVM_USE_CRT) + message(FATAL_ERROR + "LLVM_USE_CRT is deprecated. Use the CMAKE_BUILD_TYPE-specific +variables (LLVM_USE_CRT_DEBUG, etc) instead.") + endif() + + make_crt_regex(MSVC_CRT_REGEX ${MSVC_CRT}) + + foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) + string(TOUPPER "${build_type}" build) + if (NOT LLVM_USE_CRT_${build}) + get_current_crt(LLVM_USE_CRT_${build} + MSVC_CRT_REGEX + CMAKE_CXX_FLAGS_${build}) + set(LLVM_USE_CRT_${build} + "${LLVM_USE_CRT_${build}}" + CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations." + FORCE) + set_property(CACHE LLVM_USE_CRT_${build} + PROPERTY STRINGS ;${${MSVC_CRT}}) + endif(NOT LLVM_USE_CRT_${build}) + endforeach(build_type) + + foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) + string(TOUPPER "${build_type}" build) + if ("${LLVM_USE_CRT_${build}}" STREQUAL "") + set(flag_string " ") + else() + set(flag_string " /${LLVM_USE_CRT_${build}} ") + list(FIND ${MSVC_CRT} ${LLVM_USE_CRT_${build}} idx) + if (idx LESS 0) + message(FATAL_ERROR + "Invalid value for LLVM_USE_CRT_${build}: ${LLVM_USE_CRT_${build}}. Valid options are one of: ${${MSVC_CRT}}") + endif (idx LESS 0) + message(STATUS "Using ${build_type} VC++ CRT: ${LLVM_USE_CRT_${build}}") + endif() + foreach(lang C CXX) + set_flag_in_var(CMAKE_${lang}_FLAGS_${build} MSVC_CRT_REGEX flag_string) + endforeach(lang) + endforeach(build_type) +endmacro(choose_msvc_crt MSVC_CRT) + + +# List of valid CRTs for MSVC +set(MSVC_CRT + MD + MDd + MT + MTd) + +choose_msvc_crt(MSVC_CRT) + diff --git a/cmake/modules/GetHostTriple.cmake b/cmake/modules/GetHostTriple.cmake new file mode 100644 index 00000000..671a8ce7 --- /dev/null +++ b/cmake/modules/GetHostTriple.cmake @@ -0,0 +1,30 @@ +# Returns the host triple. +# Invokes config.guess + +function( get_host_triple var ) + if( MSVC ) + if( CMAKE_CL_64 ) + set( value "x86_64-pc-win32" ) + else() + set( value "i686-pc-win32" ) + endif() + elseif( MINGW AND NOT MSYS ) + if( CMAKE_SIZEOF_VOID_P EQUAL 8 ) + set( value "x86_64-w64-mingw32" ) + else() + set( value "i686-pc-mingw32" ) + endif() + else( MSVC ) + set(config_guess ${LLVM_MAIN_SRC_DIR}/autoconf/config.guess) + execute_process(COMMAND sh ${config_guess} + RESULT_VARIABLE TT_RV + OUTPUT_VARIABLE TT_OUT + OUTPUT_STRIP_TRAILING_WHITESPACE) + if( NOT TT_RV EQUAL 0 ) + message(FATAL_ERROR "Failed to execute ${config_guess}") + endif( NOT TT_RV EQUAL 0 ) + set( value ${TT_OUT} ) + endif( MSVC ) + set( ${var} ${value} PARENT_SCOPE ) + message(STATUS "Target triple: ${value}") +endfunction( get_host_triple var ) diff --git a/cmake/modules/GetSVN.cmake b/cmake/modules/GetSVN.cmake new file mode 100644 index 00000000..acccc12a --- /dev/null +++ b/cmake/modules/GetSVN.cmake @@ -0,0 +1,25 @@ +# CMake project that writes Subversion revision information to a header. +# +# Input variables: +# FIRST_SOURCE_DIR - First source directory +# FIRST_REPOSITORY - The macro to define to the first revision number. +# SECOND_SOURCE_DIR - Second source directory +# SECOND_REPOSITORY - The macro to define to the second revision number. +# HEADER_FILE - The header file to write +include(FindSubversion) +if (Subversion_FOUND AND EXISTS "${FIRST_SOURCE_DIR}/.svn") + # Repository information for the first repository. + Subversion_WC_INFO(${FIRST_SOURCE_DIR} MY) + file(WRITE ${HEADER_FILE}.txt "#define ${FIRST_REPOSITORY} \"${MY_WC_REVISION}\"\n") + + # Repository information for the second repository. + if (EXISTS "${SECOND_SOURCE_DIR}/.svn") + Subversion_WC_INFO(${SECOND_SOURCE_DIR} MY) + file(APPEND ${HEADER_FILE}.txt + "#define ${SECOND_REPOSITORY} \"${MY_WC_REVISION}\"\n") + endif () + + # Copy the file only if it has changed. + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${HEADER_FILE}.txt ${HEADER_FILE}) +endif() diff --git a/cmake/modules/HandleLLVMOptions.cmake b/cmake/modules/HandleLLVMOptions.cmake new file mode 100644 index 00000000..bb41a58d --- /dev/null +++ b/cmake/modules/HandleLLVMOptions.cmake @@ -0,0 +1,299 @@ +# This CMake module is responsible for interpreting the user defined LLVM_ +# options and executing the appropriate CMake commands to realize the users' +# selections. + +include(AddLLVMDefinitions) +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) + +if( CMAKE_COMPILER_IS_GNUCXX ) + set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON) +elseif( MSVC ) + set(LLVM_COMPILER_IS_GCC_COMPATIBLE OFF) +elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) + set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON) +endif() + +if( LLVM_ENABLE_ASSERTIONS ) + # MSVC doesn't like _DEBUG on release builds. See PR 4379. + if( NOT MSVC ) + add_definitions( -D_DEBUG ) + endif() + # On non-Debug builds cmake automatically defines NDEBUG, so we + # explicitly undefine it: + if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) + add_definitions( -UNDEBUG ) + # Also remove /D NDEBUG to avoid MSVC warnings about conflicting defines. + set(REGEXP_NDEBUG "(^| )[/-]D *NDEBUG($| )") + string (REGEX REPLACE "${REGEXP_NDEBUG}" " " + CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string (REGEX REPLACE "${REGEXP_NDEBUG}" " " + CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + string (REGEX REPLACE "${REGEXP_NDEBUG}" " " + CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}") + endif() +else() + if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + if( NOT MSVC_IDE AND NOT XCODE ) + add_definitions( -DNDEBUG ) + endif() + endif() +endif() + +if(WIN32) + if(CYGWIN) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + else(CYGWIN) + set(LLVM_ON_WIN32 1) + set(LLVM_ON_UNIX 0) + endif(CYGWIN) + set(LTDL_SHLIB_EXT ".dll") + set(EXEEXT ".exe") + # Maximum path length is 160 for non-unicode paths + set(MAXPATHLEN 160) +else(WIN32) + if(UNIX) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + if(APPLE) + set(LTDL_SHLIB_EXT ".dylib") + else(APPLE) + set(LTDL_SHLIB_EXT ".so") + endif(APPLE) + set(EXEEXT "") + # FIXME: Maximum path length is currently set to 'safe' fixed value + set(MAXPATHLEN 2024) + else(UNIX) + MESSAGE(SEND_ERROR "Unable to determine platform") + endif(UNIX) +endif(WIN32) + +function(add_flag_or_print_warning flag) + check_c_compiler_flag(${flag} C_SUPPORTS_FLAG) + check_cxx_compiler_flag(${flag} CXX_SUPPORTS_FLAG) + if (C_SUPPORTS_FLAG AND CXX_SUPPORTS_FLAG) + message(STATUS "Building with ${flag}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE) + else() + message(WARNING "${flag} is not supported.") + endif() +endfunction() + +function(append value) + foreach(variable ${ARGN}) + set(${variable} "${${variable}} ${value}" PARENT_SCOPE) + endforeach(variable) +endfunction() + +function(append_if condition value) + if (${condition}) + foreach(variable ${ARGN}) + set(${variable} "${${variable}} ${value}" PARENT_SCOPE) + endforeach(variable) + endif() +endfunction() + +macro(add_flag_if_supported flag) + check_c_compiler_flag(${flag} C_SUPPORTS_FLAG) + append_if(C_SUPPORTS_FLAG "${flag}" CMAKE_C_FLAGS) + check_cxx_compiler_flag(${flag} CXX_SUPPORTS_FLAG) + append_if(CXX_SUPPORTS_FLAG "${flag}" CMAKE_CXX_FLAGS) +endmacro() + +if( LLVM_ENABLE_PIC ) + if( XCODE ) + # Xcode has -mdynamic-no-pic on by default, which overrides -fPIC. I don't + # know how to disable this, so just force ENABLE_PIC off for now. + message(WARNING "-fPIC not supported with Xcode.") + elseif( WIN32 OR CYGWIN) + # On Windows all code is PIC. MinGW warns if -fPIC is used. + else() + add_flag_or_print_warning("-fPIC") + + if( WIN32 OR CYGWIN) + # MinGW warns if -fvisibility-inlines-hidden is used. + else() + check_cxx_compiler_flag("-fvisibility-inlines-hidden" SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG) + append_if(SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG "-fvisibility-inlines-hidden" CMAKE_CXX_FLAGS) + endif() + endif() +endif() + +if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) + # TODO: support other platforms and toolchains. + if( LLVM_BUILD_32_BITS ) + message(STATUS "Building 32 bits executables and libraries.") + add_llvm_definitions( -m32 ) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -m32") + endif( LLVM_BUILD_32_BITS ) +endif( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) + +# On Win32 using MS tools, provide an option to set the number of parallel jobs +# to use. +if( MSVC_IDE ) + set(LLVM_COMPILER_JOBS "0" CACHE STRING + "Number of parallel compiler jobs. 0 means use all processors. Default is 0.") + if( NOT LLVM_COMPILER_JOBS STREQUAL "1" ) + if( LLVM_COMPILER_JOBS STREQUAL "0" ) + add_llvm_definitions( /MP ) + else() + if (MSVC10) + message(FATAL_ERROR + "Due to a bug in CMake only 0 and 1 is supported for " + "LLVM_COMPILER_JOBS when generating for Visual Studio 2010") + else() + message(STATUS "Number of parallel compiler jobs set to " ${LLVM_COMPILER_JOBS}) + add_llvm_definitions( /MP${LLVM_COMPILER_JOBS} ) + endif() + endif() + else() + message(STATUS "Parallel compilation disabled") + endif() +endif() + +if( MSVC ) + include(ChooseMSVCCRT) + + if( NOT (${CMAKE_VERSION} VERSION_LESS 2.8.11) ) + # set stack reserved size to ~10MB + # CMake previously automatically set this value for MSVC builds, but the + # behavior was changed in CMake 2.8.11 (Issue 12437) to use the MSVC default + # value (1 MB) which is not enough for us in tasks such as parsing recursive + # C++ templates in Clang. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10000000") + endif() + + if( MSVC10 ) + # MSVC 10 will complain about headers in the STL not being exported, but + # will not complain in MSVC 11. + add_llvm_definitions( + -wd4275 # Suppress 'An exported class was derived from a class that was not exported.' + ) + elseif( MSVC11 ) + add_llvm_definitions(-D_VARIADIC_MAX=10) + endif() + + # Add definitions that make MSVC much less annoying. + add_llvm_definitions( + # For some reason MS wants to deprecate a bunch of standard functions... + -D_CRT_SECURE_NO_DEPRECATE + -D_CRT_SECURE_NO_WARNINGS + -D_CRT_NONSTDC_NO_DEPRECATE + -D_CRT_NONSTDC_NO_WARNINGS + -D_SCL_SECURE_NO_DEPRECATE + -D_SCL_SECURE_NO_WARNINGS + + # Disabled warnings. + -wd4146 # Suppress 'unary minus operator applied to unsigned type, result still unsigned' + -wd4180 # Suppress 'qualifier applied to function type has no meaning; ignored' + -wd4244 # Suppress ''argument' : conversion from 'type1' to 'type2', possible loss of data' + -wd4267 # Suppress ''var' : conversion from 'size_t' to 'type', possible loss of data' + -wd4345 # Suppress 'behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized' + -wd4351 # Suppress 'new behavior: elements of array 'array' will be default initialized' + -wd4355 # Suppress ''this' : used in base member initializer list' + -wd4503 # Suppress ''identifier' : decorated name length exceeded, name was truncated' + -wd4624 # Suppress ''derived class' : destructor could not be generated because a base class destructor is inaccessible' + -wd4800 # Suppress ''type' : forcing value to bool 'true' or 'false' (performance warning)' + -wd4291 # Suppress ''declaration' : no matching operator delete found; memory will not be freed if initialization throws an exception' + + # Promoted warnings. + -w14062 # Promote 'enumerator in switch of enum is not handled' to level 1 warning. + + # Promoted warnings to errors. + -we4238 # Promote 'nonstandard extension used : class rvalue used as lvalue' to error. + ) + + # Enable warnings + if (LLVM_ENABLE_WARNINGS) + add_llvm_definitions( /W4 ) + if (LLVM_ENABLE_PEDANTIC) + # No MSVC equivalent available + endif (LLVM_ENABLE_PEDANTIC) + endif (LLVM_ENABLE_WARNINGS) + if (LLVM_ENABLE_WERROR) + add_llvm_definitions( /WX ) + endif (LLVM_ENABLE_WERROR) +elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE ) + if (LLVM_ENABLE_WARNINGS) + append("-Wall -W -Wno-unused-parameter -Wwrite-strings" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + + # Turn off missing field initializer warnings for gcc to avoid noise from + # false positives with empty {}. Turn them on otherwise (they're off by + # default for clang). + check_cxx_compiler_flag("-Wmissing-field-initializers" CXX_SUPPORTS_MISSING_FIELD_INITIALIZERS_FLAG) + if (CXX_SUPPORTS_MISSING_FIELD_INITIALIZERS_FLAG) + if (CMAKE_COMPILER_IS_GNUCXX) + append("-Wno-missing-field-initializers" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + else() + append("-Wmissing-field-initializers" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + endif() + endif() + + append_if(LLVM_ENABLE_PEDANTIC "-pedantic -Wno-long-long" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + check_cxx_compiler_flag("-Werror -Wcovered-switch-default" CXX_SUPPORTS_COVERED_SWITCH_DEFAULT_FLAG) + append_if(CXX_SUPPORTS_COVERED_SWITCH_DEFAULT_FLAG "-Wcovered-switch-default" CMAKE_CXX_FLAGS) + check_c_compiler_flag("-Werror -Wcovered-switch-default" C_SUPPORTS_COVERED_SWITCH_DEFAULT_FLAG) + append_if(C_SUPPORTS_COVERED_SWITCH_DEFAULT_FLAG "-Wcovered-switch-default" CMAKE_C_FLAGS) + append_if(USE_NO_UNINITIALIZED "-Wno-uninitialized" CMAKE_CXX_FLAGS) + append_if(USE_NO_MAYBE_UNINITIALIZED "-Wno-maybe-uninitialized" CMAKE_CXX_FLAGS) + check_cxx_compiler_flag("-Werror -Wnon-virtual-dtor" CXX_SUPPORTS_NON_VIRTUAL_DTOR_FLAG) + append_if(CXX_SUPPORTS_NON_VIRTUAL_DTOR_FLAG "-Wnon-virtual-dtor" CMAKE_CXX_FLAGS) + endif (LLVM_ENABLE_WARNINGS) + if (LLVM_ENABLE_WERROR) + add_llvm_definitions( -Werror ) + endif (LLVM_ENABLE_WERROR) +endif( MSVC ) + +macro(append_common_sanitizer_flags) + # Append -fno-omit-frame-pointer and turn on debug info to get better + # stack traces. + add_flag_if_supported("-fno-omit-frame-pointer") + if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" AND + NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO") + add_flag_if_supported("-gline-tables-only") + endif() + # Use -O1 even in debug mode, otherwise sanitizers slowdown is too large. + if (uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + add_flag_if_supported("-O1") + endif() +endmacro() + +# Turn on sanitizers if necessary. +if(LLVM_USE_SANITIZER) + if (LLVM_ON_UNIX) + if (LLVM_USE_SANITIZER STREQUAL "Address") + append_common_sanitizer_flags() + add_flag_or_print_warning("-fsanitize=address") + elseif (LLVM_USE_SANITIZER MATCHES "Memory(WithOrigins)?") + append_common_sanitizer_flags() + add_flag_or_print_warning("-fsanitize=memory") + if(LLVM_USE_SANITIZER STREQUAL "MemoryWithOrigins") + add_flag_or_print_warning("-fsanitize-memory-track-origins") + endif() + else() + message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}") + endif() + else() + message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.") + endif() +endif() + +# Turn on -gsplit-dwarf if requested +if(LLVM_USE_SPLIT_DWARF) + add_llvm_definitions("-gsplit-dwarf") +endif() + +add_llvm_definitions( -D__STDC_CONSTANT_MACROS ) +add_llvm_definitions( -D__STDC_FORMAT_MACROS ) +add_llvm_definitions( -D__STDC_LIMIT_MACROS ) + +# clang doesn't print colored diagnostics when invoked from Ninja +if (UNIX AND + CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND + CMAKE_GENERATOR STREQUAL "Ninja") + append("-fcolor-diagnostics" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) +endif() diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake new file mode 100644 index 00000000..e26fabd1 --- /dev/null +++ b/cmake/modules/LLVM-Config.cmake @@ -0,0 +1,189 @@ +function(get_system_libs return_var) + # Returns in `return_var' a list of system libraries used by LLVM. + if( NOT MSVC ) + if( MINGW ) + set(system_libs ${system_libs} imagehlp psapi shell32) + elseif( CMAKE_HOST_UNIX ) + if( HAVE_LIBRT ) + set(system_libs ${system_libs} rt) + endif() + if( HAVE_LIBDL ) + set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) + endif() + if(LLVM_ENABLE_TERMINFO) + if(HAVE_TERMINFO) + set(system_libs ${system_libs} ${TERMINFO_LIBS}) + endif() + endif() + if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) + set(system_libs ${system_libs} pthread) + endif() + if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) + set(system_libs ${system_libs} z) + endif() + endif( MINGW ) + endif( NOT MSVC ) + set(${return_var} ${system_libs} PARENT_SCOPE) +endfunction(get_system_libs) + + +function(link_system_libs target) + get_system_libs(llvm_system_libs) + target_link_libraries(${target} ${llvm_system_libs}) +endfunction(link_system_libs) + + +function(is_llvm_target_library library return_var) + # Sets variable `return_var' to ON if `library' corresponds to a + # LLVM supported target. To OFF if it doesn't. + set(${return_var} OFF PARENT_SCOPE) + string(TOUPPER "${library}" capitalized_lib) + string(TOUPPER "${LLVM_ALL_TARGETS}" targets) + foreach(t ${targets}) + if( capitalized_lib STREQUAL t OR + capitalized_lib STREQUAL "LLVM${t}" OR + capitalized_lib STREQUAL "LLVM${t}CODEGEN" OR + capitalized_lib STREQUAL "LLVM${t}ASMPARSER" OR + capitalized_lib STREQUAL "LLVM${t}ASMPRINTER" OR + capitalized_lib STREQUAL "LLVM${t}DISASSEMBLER" OR + capitalized_lib STREQUAL "LLVM${t}INFO" ) + set(${return_var} ON PARENT_SCOPE) + break() + endif() + endforeach() +endfunction(is_llvm_target_library) + + +macro(llvm_config executable) + explicit_llvm_config(${executable} ${ARGN}) +endmacro(llvm_config) + + +function(explicit_llvm_config executable) + set( link_components ${ARGN} ) + + explicit_map_components_to_libraries(LIBRARIES ${link_components}) + target_link_libraries(${executable} ${LIBRARIES}) +endfunction(explicit_llvm_config) + + +# This is a variant intended for the final user: +function(llvm_map_components_to_libraries OUT_VAR) + explicit_map_components_to_libraries(result ${ARGN}) + get_system_libs(sys_result) + set( ${OUT_VAR} ${result} ${sys_result} PARENT_SCOPE ) +endfunction(llvm_map_components_to_libraries) + + +function(explicit_map_components_to_libraries out_libs) + set( link_components ${ARGN} ) + get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS) + string(TOUPPER "${llvm_libs}" capitalized_libs) + + # Expand some keywords: + list(FIND LLVM_TARGETS_TO_BUILD "${LLVM_NATIVE_ARCH}" have_native_backend) + list(FIND link_components "engine" engine_required) + if( NOT engine_required EQUAL -1 ) + list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" have_jit) + if( NOT have_native_backend EQUAL -1 AND NOT have_jit EQUAL -1 ) + list(APPEND link_components "jit") + list(APPEND link_components "native") + else() + list(APPEND link_components "interpreter") + endif() + endif() + list(FIND link_components "native" native_required) + if( NOT native_required EQUAL -1 ) + if( NOT have_native_backend EQUAL -1 ) + list(APPEND link_components ${LLVM_NATIVE_ARCH}) + endif() + endif() + + # Translate symbolic component names to real libraries: + foreach(c ${link_components}) + # add codegen, asmprinter, asmparser, disassembler + list(FIND LLVM_TARGETS_TO_BUILD ${c} idx) + if( NOT idx LESS 0 ) + list(FIND llvm_libs "LLVM${c}CodeGen" idx) + if( NOT idx LESS 0 ) + list(APPEND expanded_components "LLVM${c}CodeGen") + else() + list(FIND llvm_libs "LLVM${c}" idx) + if( NOT idx LESS 0 ) + list(APPEND expanded_components "LLVM${c}") + else() + message(FATAL_ERROR "Target ${c} is not in the set of libraries.") + endif() + endif() + list(FIND llvm_libs "LLVM${c}AsmPrinter" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}AsmPrinter") + endif() + list(FIND llvm_libs "LLVM${c}AsmParser" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}AsmParser") + endif() + list(FIND llvm_libs "LLVM${c}Info" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}Info") + endif() + list(FIND llvm_libs "LLVM${c}Disassembler" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}Disassembler") + endif() + elseif( c STREQUAL "native" ) + # already processed + elseif( c STREQUAL "nativecodegen" ) + list(APPEND expanded_components "LLVM${LLVM_NATIVE_ARCH}CodeGen") + elseif( c STREQUAL "backend" ) + # same case as in `native'. + elseif( c STREQUAL "engine" ) + # already processed + elseif( c STREQUAL "all" ) + list(APPEND expanded_components ${llvm_libs}) + else( NOT idx LESS 0 ) + # Canonize the component name: + string(TOUPPER "${c}" capitalized) + list(FIND capitalized_libs LLVM${capitalized} lib_idx) + if( lib_idx LESS 0 ) + # The component is unknown. Maybe is an omitted target? + is_llvm_target_library(${c} iltl_result) + if( NOT iltl_result ) + message(FATAL_ERROR "Library `${c}' not found in list of llvm libraries.") + endif() + else( lib_idx LESS 0 ) + list(GET llvm_libs ${lib_idx} canonical_lib) + list(APPEND expanded_components ${canonical_lib}) + endif( lib_idx LESS 0 ) + endif( NOT idx LESS 0 ) + endforeach(c) + # Expand dependencies while topologically sorting the list of libraries: + list(LENGTH expanded_components lst_size) + set(cursor 0) + set(processed) + while( cursor LESS lst_size ) + list(GET expanded_components ${cursor} lib) + get_property(lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${lib}) + list(APPEND expanded_components ${lib_deps}) + # Remove duplicates at the front: + list(REVERSE expanded_components) + list(REMOVE_DUPLICATES expanded_components) + list(REVERSE expanded_components) + list(APPEND processed ${lib}) + # Find the maximum index that doesn't have to be re-processed: + while(NOT "${expanded_components}" MATCHES "^${processed}.*" ) + list(REMOVE_AT processed -1) + endwhile() + list(LENGTH processed cursor) + list(LENGTH expanded_components lst_size) + endwhile( cursor LESS lst_size ) + # Return just the libraries included in this build: + set(result) + foreach(c ${expanded_components}) + list(FIND llvm_libs ${c} lib_idx) + if( NOT lib_idx LESS 0 ) + set(result ${result} ${c}) + endif() + endforeach(c) + set(${out_libs} ${result} PARENT_SCOPE) +endfunction(explicit_map_components_to_libraries) diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in new file mode 100644 index 00000000..68fe2969 --- /dev/null +++ b/cmake/modules/LLVMConfig.cmake.in @@ -0,0 +1,58 @@ +# This file provides information and services to the final user. + +set(LLVM_VERSION_MAJOR @LLVM_VERSION_MAJOR@) +set(LLVM_VERSION_MINOR @LLVM_VERSION_MINOR@) +set(LLVM_PACKAGE_VERSION @PACKAGE_VERSION@) + +set(LLVM_COMMON_DEPENDS @LLVM_COMMON_DEPENDS@) + +set_property( GLOBAL PROPERTY LLVM_LIBS "@llvm_libs@") + +set(LLVM_ALL_TARGETS @LLVM_ALL_TARGETS@) + +set(LLVM_TARGETS_TO_BUILD @LLVM_TARGETS_TO_BUILD@) + +set(LLVM_TARGETS_WITH_JIT @LLVM_TARGETS_WITH_JIT@) + +@all_llvm_lib_deps@ + +set(TARGET_TRIPLE "@TARGET_TRIPLE@") + +set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@) + +set(LLVM_ENABLE_TERMINFO @LLVM_ENABLE_TERMINFO@) + +set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@) + +set(LLVM_ENABLE_ZLIB @LLVM_ENABLE_ZLIB@) + +set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@) + +set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) + +set(HAVE_TERMINFO @HAVE_TERMINFO@) +set(TERMINFO_LIBS @TERMINFO_LIBS@) +set(HAVE_LIBDL @HAVE_LIBDL@) +set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD@) +set(HAVE_LIBZ @HAVE_LIBZ@) +set(LLVM_ON_UNIX @LLVM_ON_UNIX@) +set(LLVM_ON_WIN32 @LLVM_ON_WIN32@) + +set(LLVM_INSTALL_PREFIX "@LLVM_INSTALL_PREFIX@") +set(LLVM_INCLUDE_DIRS ${LLVM_INSTALL_PREFIX}/include) +set(LLVM_LIBRARY_DIRS ${LLVM_INSTALL_PREFIX}/lib) +set(LLVM_DEFINITIONS "-D__STDC_LIMIT_MACROS" "-D__STDC_CONSTANT_MACROS") + +# We try to include using the current setting of CMAKE_MODULE_PATH, +# which suppossedly was filled by the user with the directory where +# this file was installed: +include( LLVM-Config OPTIONAL RESULT_VARIABLE LLVMCONFIG_INCLUDED ) + +# If failed, we assume that this is an un-installed build: +if( NOT LLVMCONFIG_INCLUDED ) + set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "@LLVM_SOURCE_DIR@/cmake/modules") + include( LLVM-Config ) +endif() + diff --git a/cmake/modules/LLVMConfigVersion.cmake.in b/cmake/modules/LLVMConfigVersion.cmake.in new file mode 100644 index 00000000..add5aa9a --- /dev/null +++ b/cmake/modules/LLVMConfigVersion.cmake.in @@ -0,0 +1 @@ +set(PACKAGE_VERSION "@PACKAGE_VERSION@") \ No newline at end of file diff --git a/cmake/modules/LLVMParseArguments.cmake b/cmake/modules/LLVMParseArguments.cmake new file mode 100644 index 00000000..ce19be11 --- /dev/null +++ b/cmake/modules/LLVMParseArguments.cmake @@ -0,0 +1,80 @@ +# Copied from http://www.itk.org/Wiki/CMakeMacroParseArguments under +# http://creativecommons.org/licenses/by/2.5/. +# +# The PARSE_ARGUMENTS macro will take the arguments of another macro and define +# several variables. The first argument to PARSE_ARGUMENTS is a prefix to put on +# all variables it creates. The second argument is a list of names, and the +# third argument is a list of options. Both of these lists should be quoted. The +# rest of PARSE_ARGUMENTS are arguments from another macro to be parsed. +# +# PARSE_ARGUMENTS(prefix arg_names options arg1 arg2...) +# +# For each item in options, PARSE_ARGUMENTS will create a variable with that +# name, prefixed with prefix_. So, for example, if prefix is MY_MACRO and +# options is OPTION1;OPTION2, then PARSE_ARGUMENTS will create the variables +# MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These variables will be set to true if +# the option exists in the command line or false otherwise. +# +#For each item in arg_names, PARSE_ARGUMENTS will create a variable with that +#name, prefixed with prefix_. Each variable will be filled with the arguments +#that occur after the given arg_name is encountered up to the next arg_name or +#the end of the arguments. All options are removed from these +#lists. PARSE_ARGUMENTS also creates a prefix_DEFAULT_ARGS variable containing +#the list of all arguments up to the first arg_name encountered. +# +#Here is a simple, albeit impractical, example of using PARSE_ARGUMENTS that +#demonstrates its behavior. +# +# SET(arguments +# hello OPTION3 world +# LIST3 foo bar +# OPTION2 +# LIST1 fuz baz +# ) +# +# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments}) +# +# PARSE_ARGUMENTS creates 7 variables and sets them as follows: +# ARG_DEFAULT_ARGS: hello;world +# ARG_LIST1: fuz;baz +# ARG_LIST2: +# ARG_LIST3: foo;bar +# ARG_OPTION1: FALSE +# ARG_OPTION2: TRUE +# ARG_OPTION3: TRUE +# +# If you don't have any options, use an empty string in its place. +# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "" ${arguments}) +# Likewise if you have no lists. +# PARSE_ARGUMENTS(ARG "" "OPTION1;OPTION2;OPTION3" ${arguments}) + +MACRO(PARSE_ARGUMENTS prefix arg_names option_names) + SET(DEFAULT_ARGS) + FOREACH(arg_name ${arg_names}) + SET(${prefix}_${arg_name}) + ENDFOREACH(arg_name) + FOREACH(option ${option_names}) + SET(${prefix}_${option} FALSE) + ENDFOREACH(option) + + SET(current_arg_name DEFAULT_ARGS) + SET(current_arg_list) + FOREACH(arg ${ARGN}) + SET(larg_names ${arg_names}) + LIST(FIND larg_names "${arg}" is_arg_name) + IF (is_arg_name GREATER -1) + SET(${prefix}_${current_arg_name} ${current_arg_list}) + SET(current_arg_name ${arg}) + SET(current_arg_list) + ELSE (is_arg_name GREATER -1) + SET(loption_names ${option_names}) + LIST(FIND loption_names "${arg}" is_option) + IF (is_option GREATER -1) + SET(${prefix}_${arg} TRUE) + ELSE (is_option GREATER -1) + SET(current_arg_list ${current_arg_list} ${arg}) + ENDIF (is_option GREATER -1) + ENDIF (is_arg_name GREATER -1) + ENDFOREACH(arg) + SET(${prefix}_${current_arg_name} ${current_arg_list}) +ENDMACRO(PARSE_ARGUMENTS) diff --git a/cmake/modules/LLVMProcessSources.cmake b/cmake/modules/LLVMProcessSources.cmake new file mode 100644 index 00000000..2cef6cfc --- /dev/null +++ b/cmake/modules/LLVMProcessSources.cmake @@ -0,0 +1,94 @@ +include(AddFileDependencies) + +function(llvm_replace_compiler_option var old new) + # Replaces a compiler option or switch `old' in `var' by `new'. + # If `old' is not in `var', appends `new' to `var'. + # Example: llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELEASE "-O3" "-O2") + # If the option already is on the variable, don't add it: + if( "${${var}}" MATCHES "(^| )${new}($| )" ) + set(n "") + else() + set(n "${new}") + endif() + if( "${${var}}" MATCHES "(^| )${old}($| )" ) + string( REGEX REPLACE "(^| )${old}($| )" " ${n} " ${var} "${${var}}" ) + else() + set( ${var} "${${var}} ${n}" ) + endif() + set( ${var} "${${var}}" PARENT_SCOPE ) +endfunction(llvm_replace_compiler_option) + +macro(add_td_sources srcs) + file(GLOB tds *.td) + if( tds ) + source_group("TableGen descriptions" FILES ${tds}) + set_source_files_properties(${tds} PROPERTIES HEADER_FILE_ONLY ON) + list(APPEND ${srcs} ${tds}) + endif() +endmacro(add_td_sources) + + +macro(add_header_files srcs) + file(GLOB hds *.h) + if( hds ) + set_source_files_properties(${hds} PROPERTIES HEADER_FILE_ONLY ON) + list(APPEND ${srcs} ${hds}) + endif() +endmacro(add_header_files) + + +function(llvm_process_sources OUT_VAR) + set( sources ${ARGN} ) + llvm_check_source_file_list( ${sources} ) + # Create file dependencies on the tablegenned files, if any. Seems + # that this is not strictly needed, as dependencies of the .cpp + # sources on the tablegenned .inc files are detected and handled, + # but just in case... + foreach( s ${sources} ) + set( f ${CMAKE_CURRENT_SOURCE_DIR}/${s} ) + add_file_dependencies( ${f} ${TABLEGEN_OUTPUT} ) + endforeach(s) + if( MSVC_IDE OR XCODE ) + # This adds .td and .h files to the Visual Studio solution: + # FIXME: Shall we handle *.def here? + add_td_sources(sources) + add_header_files(sources) + endif() + + # Set common compiler options: + if( NOT LLVM_REQUIRES_EH ) + if( LLVM_COMPILER_IS_GCC_COMPATIBLE ) + add_definitions( -fno-exceptions ) + elseif( MSVC ) + llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/EHsc" "/EHs-c-") + add_definitions( /D_HAS_EXCEPTIONS=0 ) + endif() + endif() + if( NOT LLVM_REQUIRES_RTTI ) + if( LLVM_COMPILER_IS_GCC_COMPATIBLE ) + llvm_replace_compiler_option(CMAKE_CXX_FLAGS "-frtti" "-fno-rtti") + elseif( MSVC ) + llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/GR" "/GR-") + endif() + endif() + + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE ) + set( ${OUT_VAR} ${sources} PARENT_SCOPE ) +endfunction(llvm_process_sources) + + +function(llvm_check_source_file_list) + set(listed ${ARGN}) + file(GLOB globbed *.cpp) + foreach(g ${globbed}) + get_filename_component(fn ${g} NAME) + list(FIND LLVM_OPTIONAL_SOURCES ${fn} idx) + if( idx LESS 0 ) + list(FIND listed ${fn} idx) + if( idx LESS 0 ) + message(SEND_ERROR "Found unknown source file ${g} +Please update ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt\n") + endif() + endif() + endforeach() +endfunction(llvm_check_source_file_list) diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake new file mode 100644 index 00000000..c17e67e4 --- /dev/null +++ b/cmake/modules/TableGen.cmake @@ -0,0 +1,143 @@ +# LLVM_TARGET_DEFINITIONS must contain the name of the .td file to process. +# Extra parameters for `tblgen' may come after `ofn' parameter. +# Adds the name of the generated file to TABLEGEN_OUTPUT. + +macro(tablegen project ofn) + file(GLOB local_tds "*.td") + file(GLOB_RECURSE global_tds "${LLVM_MAIN_SRC_DIR}/include/llvm/*.td") + + if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) + set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) + else() + set(LLVM_TARGET_DEFINITIONS_ABSOLUTE + ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS}) + endif() + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + # Generate tablegen output in a temporary file. + COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${LLVM_MAIN_SRC_DIR}/lib/Target -I ${LLVM_MAIN_INCLUDE_DIR} + ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} + -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + # The file in LLVM_TARGET_DEFINITIONS may be not in the current + # directory and local_tds may not contain it, so we must + # explicitly list it here: + DEPENDS ${${project}_TABLEGEN_EXE} ${local_tds} ${global_tds} + ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} + COMMENT "Building ${ofn}..." + ) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} + # Only update the real output file if there are any differences. + # This prevents recompilation of all the files depending on it if there + # aren't any. + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + ${CMAKE_CURRENT_BINARY_DIR}/${ofn} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + COMMENT "" + ) + + # `make clean' must remove all those generated files: + set_property(DIRECTORY APPEND + PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${ofn}.tmp ${ofn}) + + set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn} + PROPERTIES GENERATED 1) +endmacro(tablegen) + +function(add_public_tablegen_target target) + # Creates a target for publicly exporting tablegen dependencies. + if( TABLEGEN_OUTPUT ) + add_custom_target(${target} + DEPENDS ${TABLEGEN_OUTPUT}) + if (LLVM_COMMON_DEPENDS) + add_dependencies(${target} ${LLVM_COMMON_DEPENDS}) + endif () + set_target_properties(${target} PROPERTIES FOLDER "Tablegenning") + endif( TABLEGEN_OUTPUT ) +endfunction() + +if(CMAKE_CROSSCOMPILING) + set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native") + + add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR} + COMMENT "Creating ${CX_NATIVE_TG_DIR}...") + + add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt + COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release + -DLLVM_BUILD_POLLY=OFF + -G "${CMAKE_GENERATOR}" ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CX_NATIVE_TG_DIR} + DEPENDS ${CX_NATIVE_TG_DIR} + COMMENT "Configuring native TableGen...") + + add_custom_target(ConfigureNativeTableGen DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt) + + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR}) +endif() + +macro(add_tablegen target project) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR}) + + set(${target}_OLD_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS}) + set(LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} TableGen) + add_llvm_utility(${target} ${ARGN}) + set(LLVM_LINK_COMPONENTS ${${target}_OLD_LLVM_LINK_COMPONENTS}) + + # For Xcode builds, symlink bin/ to bin// so that + # a separately-configured Clang project can still find llvm-tblgen. + if (XCODE) + add_custom_target(${target}-top ALL + ${CMAKE_COMMAND} -E create_symlink + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${target}${CMAKE_EXECUTABLE_SUFFIX} + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${target}${CMAKE_EXECUTABLE_SUFFIX} + DEPENDS ${target}) + endif () + + set(${project}_TABLEGEN "${target}" CACHE + STRING "Native TableGen executable. Saves building one when cross-compiling.") + + # Upgrade existing LLVM_TABLEGEN setting. + if(${project} STREQUAL LLVM) + if(${LLVM_TABLEGEN} STREQUAL tblgen) + set(LLVM_TABLEGEN "${target}" CACHE + STRING "Native TableGen executable. Saves building one when cross-compiling." + FORCE) + endif() + endif() + + # Effective tblgen executable to be used: + set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN} PARENT_SCOPE) + + if(CMAKE_CROSSCOMPILING) + if( ${${project}_TABLEGEN} STREQUAL "${target}" ) + set(${project}_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/${target}") + set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN_EXE} PARENT_SCOPE) + + add_custom_command(OUTPUT ${${project}_TABLEGEN_EXE} + COMMAND ${CMAKE_BUILD_TOOL} ${target} + DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt + WORKING_DIRECTORY ${CX_NATIVE_TG_DIR} + COMMENT "Building native TableGen...") + add_custom_target(${project}NativeTableGen DEPENDS ${${project}_TABLEGEN_EXE}) + add_dependencies(${project}NativeTableGen ConfigureNativeTableGen) + + add_dependencies(${target} ${project}NativeTableGen) + endif() + endif() + + if( MINGW ) + target_link_libraries(${target} imagehlp psapi shell32) + if(CMAKE_SIZEOF_VOID_P MATCHES "8") + set_target_properties(${target} PROPERTIES LINK_FLAGS -Wl,--stack,16777216) + endif(CMAKE_SIZEOF_VOID_P MATCHES "8") + endif( MINGW ) + if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS ) + target_link_libraries(${target} pthread) + endif() + + if (${project} STREQUAL LLVM AND NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(TARGETS ${target} RUNTIME DESTINATION bin) + endif() +endmacro() diff --git a/cmake/modules/VersionFromVCS.cmake b/cmake/modules/VersionFromVCS.cmake new file mode 100644 index 00000000..26314d41 --- /dev/null +++ b/cmake/modules/VersionFromVCS.cmake @@ -0,0 +1,72 @@ +# Adds version control information to the variable VERS. For +# determining the Version Control System used (if any) it inspects the +# existence of certain subdirectories under CMAKE_CURRENT_SOURCE_DIR. + +function(add_version_info_from_vcs VERS) + string(REPLACE "svn" "" result "${${VERS}}") + if( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn" ) + set(result "${result}svn") + # FindSubversion does not work with symlinks. See PR 8437 + if( NOT IS_SYMLINK "${CMAKE_CURRENT_SOURCE_DIR}" ) + find_package(Subversion) + endif() + if( Subversion_FOUND ) + subversion_wc_info( ${CMAKE_CURRENT_SOURCE_DIR} Project ) + if( Project_WC_REVISION ) + set(SVN_REVISION ${Project_WC_REVISION} PARENT_SCOPE) + set(result "${result}-r${Project_WC_REVISION}") + endif() + endif() + elseif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git ) + set(result "${result}git") + # Try to get a ref-id + if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git/svn ) + find_program(git_executable NAMES git git.exe git.cmd) + if( git_executable ) + set(is_git_svn_rev_exact false) + execute_process(COMMAND ${git_executable} svn log --limit=1 --oneline + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if( git_result EQUAL 0 ) + string(REGEX MATCH r[0-9]+ git_svn_rev ${git_output}) + string(LENGTH "${git_svn_rev}" rev_length) + math(EXPR rev_length "${rev_length}-1") + string(SUBSTRING "${git_svn_rev}" 1 ${rev_length} git_svn_rev_number) + set(SVN_REVISION ${git_svn_rev_number} PARENT_SCOPE) + set(git_svn_rev "-svn-${git_svn_rev}") + + # Determine if the HEAD points directly at a subversion revision. + execute_process(COMMAND ${git_executable} svn find-rev HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if( git_result EQUAL 0 ) + string(STRIP "${git_output}" git_head_svn_rev_number) + if( git_head_svn_rev_number EQUAL git_svn_rev_number ) + set(is_git_svn_rev_exact true) + endif() + endif() + else() + set(git_svn_rev "") + endif() + execute_process(COMMAND + ${git_executable} rev-parse --short HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if( git_result EQUAL 0 AND NOT is_git_svn_rev_exact ) + string(STRIP "${git_output}" git_ref_id) + set(GIT_COMMIT ${git_ref_id} PARENT_SCOPE) + set(result "${result}${git_svn_rev}-${git_ref_id}") + else() + set(result "${result}${git_svn_rev}") + endif() + endif() + endif() + endif() + set(${VERS} ${result} PARENT_SCOPE) +endfunction(add_version_info_from_vcs) diff --git a/cmake/nsis_logo.bmp b/cmake/nsis_logo.bmp new file mode 100644 index 00000000..5fcb3cec Binary files /dev/null and b/cmake/nsis_logo.bmp differ diff --git a/cmake/platforms/Android.cmake b/cmake/platforms/Android.cmake new file mode 100644 index 00000000..35df5ebd --- /dev/null +++ b/cmake/platforms/Android.cmake @@ -0,0 +1,28 @@ +# Toolchain config for Android NDK. +# This is expected to be used with a standalone Android toolchain (see +# docs/STANDALONE-TOOLCHAIN.html in the NDK on how to get one). +# +# Usage: +# mkdir build; cd build +# cmake ..; make +# mkdir android; cd android +# cmake -DLLVM_ANDROID_TOOLCHAIN_DIR=/path/to/android/ndk \ +# -DCMAKE_TOOLCHAIN_FILE=../../cmake/platforms/Android.cmake ../.. +# make + +SET(CMAKE_SYSTEM_NAME Linux) + +IF(NOT CMAKE_C_COMPILER) + SET(CMAKE_C_COMPILER ${CMAKE_BINARY_DIR}/../bin/clang) +ENDIF() + +IF(NOT CMAKE_CXX_COMPILER) + SET(CMAKE_CXX_COMPILER ${CMAKE_BINARY_DIR}/../bin/clang++) +ENDIF() + +SET(ANDROID "1" CACHE STRING "ANDROID" FORCE) + +SET(ANDROID_COMMON_FLAGS "-target arm-linux-androideabi --sysroot=${LLVM_ANDROID_TOOLCHAIN_DIR}/sysroot -B${LLVM_ANDROID_TOOLCHAIN_DIR} -mllvm -arm-enable-ehabi") +SET(CMAKE_C_FLAGS "${ANDROID_COMMON_FLAGS}" CACHE STRING "toolchain_cflags" FORCE) +SET(CMAKE_CXX_FLAGS "${ANDROID_COMMON_FLAGS}" CACHE STRING "toolchain_cxxflags" FORCE) +SET(CMAKE_LINK_FLAGS "${ANDROID_COMMON_FLAGS}" CACHE STRING "toolchain_linkflags" FORCE) diff --git a/configure b/configure new file mode 100755 index 00000000..cbda923c --- /dev/null +++ b/configure @@ -0,0 +1,23947 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.60 for LLVM 3.4.1. +# +# Report bugs to . +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# +# Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='LLVM' +PACKAGE_TARNAME='llvm' +PACKAGE_VERSION='3.4.1' +PACKAGE_STRING='LLVM 3.4.1' +PACKAGE_BUGREPORT='http://llvm.org/bugs/' + +ac_unique_file="lib/IR/Module.cpp" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +LLVM_VERSION_MAJOR +LLVM_VERSION_MINOR +LLVM_VERSION_PATCH +LLVM_VERSION_SUFFIX +LLVM_COPYRIGHT +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +CXX +CXXFLAGS +ac_ct_CXX +CPP +subdirs +ENABLE_POLLY +LLVM_HAS_POLLY +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +target +target_cpu +target_vendor +target_os +OS +HOST_OS +TARGET_OS +LINKALL +NOLINKALL +LLVM_ON_UNIX +LLVM_ON_WIN32 +ARCH +HOST_ARCH +ENDIAN +GREP +EGREP +LLVM_CROSS_COMPILING +BUILD_CC +BUILD_EXEEXT +BUILD_CXX +CVSBUILD +ENABLE_LIBCPP +ENABLE_CXX11 +ENABLE_SPLIT_DWARF +ENABLE_CLANG_ARCMT +ENABLE_CLANG_STATIC_ANALYZER +ENABLE_CLANG_REWRITER +ENABLE_OPTIMIZED +ENABLE_PROFILING +DISABLE_ASSERTIONS +ENABLE_WERROR +ENABLE_EXPENSIVE_CHECKS +EXPENSIVE_CHECKS +DEBUG_RUNTIME +DEBUG_SYMBOLS +KEEP_SYMBOLS +JIT +TARGET_HAS_JIT +ENABLE_DOCS +ENABLE_DOXYGEN +LLVM_ENABLE_THREADS +ENABLE_PTHREADS +LLVM_ENABLE_ZLIB +ENABLE_PIC +ENABLE_SHARED +ENABLE_EMBED_STDCXX +ENABLE_TIMESTAMPS +TARGETS_TO_BUILD +LLVM_ENUM_TARGETS +LLVM_ENUM_ASM_PRINTERS +LLVM_ENUM_ASM_PARSERS +LLVM_ENUM_DISASSEMBLERS +OPTIMIZE_OPTION +EXTRA_OPTIONS +EXTRA_LD_OPTIONS +CLANG_SRC_ROOT +BINUTILS_INCDIR +INTERNAL_PREFIX +NM +ifGNUmake +LN_S +CMP +CP +DATE +FIND +MKDIR +MV +RANLIB +AR +RM +SED +TAR +BINPWD +GRAPHVIZ +DOT +FDP +NEATO +TWOPI +CIRCO +GV +DOTTY +XDOT +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +BZIP2 +CAT +DOXYGEN +GROFF +GZIPBIN +PDFROFF +ZIP +OCAMLC +OCAMLOPT +OCAMLDEP +OCAMLDOC +GAS +HAVE_LINK_VERSION_SCRIPT +INSTALL_LTDL_TRUE +INSTALL_LTDL_FALSE +CONVENIENCE_LTDL_TRUE +CONVENIENCE_LTDL_FALSE +LIBADD_DL +NO_VARIADIC_MACROS +NO_MISSING_FIELD_INITIALIZERS +COVERED_SWITCH_DEFAULT +NO_MAYBE_UNINITIALIZED +NO_UNINITIALIZED +PYTHON +USE_UDIS86 +USE_OPROFILE +USE_INTEL_JITEVENTS +XML2CONFIG +LIBXML2_LIBS +LIBXML2_INC +CXXCPP +HAVE_PTHREAD +HAVE_LIBZ +HUGE_VAL_SANITY +MMAP_FILE +SHLIBEXT +SHLIBPATH_VAR +LLVM_PREFIX +LLVM_BINDIR +LLVM_DATADIR +LLVM_DOCSDIR +LLVM_ETCDIR +LLVM_INCLUDEDIR +LLVM_INFODIR +LLVM_MANDIR +LLVM_CONFIGTIME +BINDINGS_TO_BUILD +ALL_BINDINGS +OCAML_LIBDIR +ENABLE_VISIBILITY_INLINES_HIDDEN +RPATH +RDYNAMIC +program_prefix +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +CPPFLAGS +CXX +CXXFLAGS +CCC +CPP +CXXCPP' +ac_subdirs_all='projects/llvm-gcc +projects/test-suite +projects/llvm-test +projects/poolalloc +projects/llvm-poolalloc +projects/sample +projects/privbracket +projects/llvm-stacker +projects/llvm-reopt +projects/llvm-java +projects/llvm-tv +projects/safecode +projects/llvm-kernel +tools/polly' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures LLVM 3.4.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/llvm] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of LLVM 3.4.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-polly Use polly if available (default is YES) + --enable-libcpp Use libc++ if available (default is NO) + --enable-cxx11 Use c++11 if available (default is NO) + --enable-split-dwarf Use split-dwarf if available (default is NO) + --enable-clang-arcmt Enable building of clang ARCMT (default is YES) + --enable-clang-static-analyzer + Enable building of clang Static Analyzer (default is + YES) + --enable-clang-rewriter Enable building of clang rewriter (default is YES) + --enable-optimized Compile with optimizations enabled (default is NO) + --enable-profiling Compile with profiling enabled (default is NO) + --enable-assertions Compile with assertion checks enabled (default is + YES) + --enable-werror Compile with -Werror enabled (default is NO) + --enable-expensive-checks + Compile with expensive debug checks enabled (default + is NO) + --enable-debug-runtime Build runtime libs with debug symbols (default is + NO) + --enable-debug-symbols Build compiler with debug symbols (default is NO if + optimization is on and YES if it's off) + --enable-keep-symbols Do not strip installed executables) + --enable-jit Enable Just In Time Compiling (default is YES) + --enable-docs Build documents (default is YES) + --enable-doxygen Build doxygen documentation (default is NO) + --enable-threads Use threads if available (default is YES) + --enable-pthreads Use pthreads if available (default is YES) + --enable-zlib Use zlib for compression/decompression if available + (default is YES) + --enable-pic Build LLVM with Position Independent Code (default + is YES) + --enable-shared Build a shared library and link tools against it + (default is NO) + --enable-embed-stdcxx Build a shared library with embedded libstdc++ for + Win32 DLL (default is NO) + --enable-timestamps Enable embedding timestamp information in build + (default is YES) + --enable-backtraces Enable embedding backtraces on crash (default is + YES) + --enable-crash-overrides + Enable crash handling overrides (default is YES) + --enable-targets Build specific host targets: all or + target1,target2,... Valid targets are: host, x86, + x86_64, sparc, powerpc, arm, aarch64, mips, hexagon, + xcore, msp430, nvptx, systemz, r600, and cpp + (default=all) + --enable-experimental-targets + Build experimental host targets: disable or + target1,target2,... (default=disable) + --enable-bindings Build specific language bindings: + all,auto,none,{binding-name} (default=auto) + --enable-terminfo Query the terminfo database if available (default is + YES) + --enable-libffi Check for the presence of libffi (default is NO) + --enable-ltdl-install install libltdl + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-optimize-option Select the compiler options to use for optimized + builds + --with-extra-options Specify additional options to compile LLVM with + --with-extra-ld-options Specify additional options to link LLVM with + --with-ocaml-libdir Specify install location for ocaml bindings (default + is stdlib) + --with-clang-srcdir Directory to the out-of-tree Clang source + --with-clang-resource-dir + Relative directory from the Clang binary for + resource files + --with-c-include-dirs Colon separated list of directories clang will + search for headers + --with-gcc-toolchain Directory where gcc is installed. + --with-default-sysroot Add --sysroot= to all compiler invocations. + --with-binutils-include Specify path to binutils/include/ containing + plugin-api.h file for gold plugin. + --with-bug-report-url Specify the URL where bug reports should be + submitted (default=http://llvm.org/bugs/) + --with-internal-prefix Installation directory for internal files + --with-python path to python + --with-udis86= Use udis86 external x86 disassembler library + --with-oprofile= + Tell OProfile >= 0.9.4 how to symbolize JIT output + --with-intel-jitevents Notify Intel JIT profiling API of generated code + + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +LLVM configure 3.4.1 +generated by GNU Autoconf 2.60 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + +Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by LLVM $as_me 3.4.1, which was +generated by GNU Autoconf 2.60. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +LLVM_VERSION_MAJOR=3 +LLVM_VERSION_MINOR=4 +LLVM_VERSION_PATCH=1 +LLVM_VERSION_SUFFIX= + + +cat >>confdefs.h <<_ACEOF +#define LLVM_VERSION_MAJOR $LLVM_VERSION_MAJOR +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_VERSION_MINOR $LLVM_VERSION_MINOR +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_VERSION_PATCH $LLVM_VERSION_PATCH +_ACEOF + + + + + + + +LLVM_COPYRIGHT="Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign." + + + + + + + +ac_aux_dir= +for ac_dir in autoconf "$srcdir"/autoconf; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +if test ${srcdir} != "." ; then + if test -f ${srcdir}/include/llvm/Config/config.h ; then + { { echo "$as_me:$LINENO: error: Already configured in ${srcdir}" >&5 +echo "$as_me: error: Already configured in ${srcdir}" >&2;} + { (exit 1); exit 1; }; } + fi +fi + +: ${CFLAGS=} +: ${CXXFLAGS=} + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in clang llvm-gcc gcc + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in clang llvm-gcc gcc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in clang++ llvm-g++ g++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in clang++ llvm-g++ g++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +if test "$CXX" = "clang++" ; then + { echo "$as_me:$LINENO: checking whether clang works" >&5 +echo $ECHO_N "checking whether clang works... $ECHO_C" >&6; } + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if __has_include () +#include +#endif +#if __has_include () +#include +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler ./configure ..." >&5 +echo "$as_me: error: Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler ./configure ..." >&2;} + { (exit 1); exit 1; }; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi + + + +if test -d ${srcdir}/projects/llvm-gcc ; then + subdirs="$subdirs projects/llvm-gcc" + +fi + +if test -d ${srcdir}/projects/test-suite ; then + subdirs="$subdirs projects/test-suite" + +fi + +if test -d ${srcdir}/projects/llvm-test ; then + subdirs="$subdirs projects/llvm-test" + +fi + +if test -d ${srcdir}/projects/poolalloc ; then + subdirs="$subdirs projects/poolalloc" + +fi + +if test -d ${srcdir}/projects/llvm-poolalloc ; then + subdirs="$subdirs projects/llvm-poolalloc" + +fi + +for i in `ls ${srcdir}/projects` +do + if test -d ${srcdir}/projects/${i} ; then + case ${i} in + sample) subdirs="$subdirs projects/sample" + ;; + privbracket) subdirs="$subdirs projects/privbracket" + ;; + llvm-stacker) subdirs="$subdirs projects/llvm-stacker" + ;; + llvm-reopt) subdirs="$subdirs projects/llvm-reopt" +;; + llvm-java) subdirs="$subdirs projects/llvm-java" + ;; + llvm-tv) subdirs="$subdirs projects/llvm-tv" + ;; + safecode) subdirs="$subdirs projects/safecode" + ;; + llvm-kernel) subdirs="$subdirs projects/llvm-kernel" + ;; + compiler-rt) ;; + llvm-gcc) ;; + test-suite) ;; + llvm-test) ;; + poolalloc) ;; + llvm-poolalloc) ;; + *) + { echo "$as_me:$LINENO: WARNING: Unknown project (${i}) won't be configured automatically" >&5 +echo "$as_me: WARNING: Unknown project (${i}) won't be configured automatically" >&2;} + ;; + esac + fi +done + +# Check whether --enable-polly was given. +if test "${enable_polly+set}" = set; then + enableval=$enable_polly; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_POLLY=1 + ;; + no) ENABLE_POLLY=0 + ;; + default) ENABLE_POLLY=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +if (test -d ${srcdir}/tools/polly) && (test $ENABLE_POLLY -eq 1) ; then + LLVM_HAS_POLLY=1 + + subdirs="$subdirs tools/polly" + +fi + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6; } +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 +echo "$as_me: error: invalid value of canonical target" >&2;} + { (exit 1); exit 1; }; };; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +{ echo "$as_me:$LINENO: checking type of operating system we're going to host on" >&5 +echo $ECHO_N "checking type of operating system we're going to host on... $ECHO_C" >&6; } +if test "${llvm_cv_os_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $host in + *-*-aix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="AIX" + llvm_cv_platform_type="Unix" ;; + *-*-irix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="IRIX" + llvm_cv_platform_type="Unix" ;; + *-*-cygwin*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Cygwin" + llvm_cv_platform_type="Unix" ;; + *-*-darwin*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Darwin" + llvm_cv_platform_type="Unix" ;; + *-*-minix*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Minix" + llvm_cv_platform_type="Unix" ;; + *-*-freebsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="FreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-kfreebsd-gnu) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="GNU/kFreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-openbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="OpenBSD" + llvm_cv_platform_type="Unix" ;; + *-*-netbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="NetBSD" + llvm_cv_platform_type="Unix" ;; + *-*-dragonfly*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="DragonFly" + llvm_cv_platform_type="Unix" ;; + *-*-hpux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="HP-UX" + llvm_cv_platform_type="Unix" ;; + *-*-interix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Interix" + llvm_cv_platform_type="Unix" ;; + *-*-linux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Linux" + llvm_cv_platform_type="Unix" ;; + *-*-gnu*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="GNU" + llvm_cv_platform_type="Unix" ;; + *-*-solaris*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_no_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="SunOS" + llvm_cv_platform_type="Unix" ;; + *-*-auroraux*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="AuroraUX" + llvm_cv_platform_type="Unix" ;; + *-*-win32*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Win32" + llvm_cv_platform_type="Win32" ;; + *-*-mingw*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="MingW" + llvm_cv_platform_type="Win32" ;; + *-*-haiku*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Haiku" + llvm_cv_platform_type="Unix" ;; + *-unknown-eabi*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *-unknown-elf*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *) + llvm_cv_link_all_option="" + llvm_cv_no_link_all_option="" + llvm_cv_os_type="Unknown" + llvm_cv_platform_type="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_os_type" >&5 +echo "${ECHO_T}$llvm_cv_os_type" >&6; } + +{ echo "$as_me:$LINENO: checking type of operating system we're going to target" >&5 +echo $ECHO_N "checking type of operating system we're going to target... $ECHO_C" >&6; } +if test "${llvm_cv_target_os_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $target in + *-*-aix*) + llvm_cv_target_os_type="AIX" ;; + *-*-irix*) + llvm_cv_target_os_type="IRIX" ;; + *-*-cygwin*) + llvm_cv_target_os_type="Cygwin" ;; + *-*-darwin*) + llvm_cv_target_os_type="Darwin" ;; + *-*-minix*) + llvm_cv_target_os_type="Minix" ;; + *-*-freebsd*) + llvm_cv_target_os_type="FreeBSD" ;; + *-*-kfreebsd-gnu) + llvm_cv_target_os_type="GNU/kFreeBSD" ;; + *-*-openbsd*) + llvm_cv_target_os_type="OpenBSD" ;; + *-*-netbsd*) + llvm_cv_target_os_type="NetBSD" ;; + *-*-dragonfly*) + llvm_cv_target_os_type="DragonFly" ;; + *-*-hpux*) + llvm_cv_target_os_type="HP-UX" ;; + *-*-interix*) + llvm_cv_target_os_type="Interix" ;; + *-*-linux*) + llvm_cv_target_os_type="Linux" ;; + *-*-gnu*) + llvm_cv_target_os_type="GNU" ;; + *-*-solaris*) + llvm_cv_target_os_type="SunOS" ;; + *-*-auroraux*) + llvm_cv_target_os_type="AuroraUX" ;; + *-*-win32*) + llvm_cv_target_os_type="Win32" ;; + *-*-mingw*) + llvm_cv_target_os_type="MingW" ;; + *-*-haiku*) + llvm_cv_target_os_type="Haiku" ;; + *-*-rtems*) + llvm_cv_target_os_type="RTEMS" ;; + *-*-nacl*) + llvm_cv_target_os_type="NativeClient" ;; + *-unknown-eabi*) + llvm_cv_target_os_type="Freestanding" ;; + *) + llvm_cv_target_os_type="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_target_os_type" >&5 +echo "${ECHO_T}$llvm_cv_target_os_type" >&6; } + +if test "$llvm_cv_os_type" = "Unknown" ; then + { { echo "$as_me:$LINENO: error: Operating system is unknown, configure can't continue" >&5 +echo "$as_me: error: Operating system is unknown, configure can't continue" >&2;} + { (exit 1); exit 1; }; } +fi + +OS=$llvm_cv_os_type + +HOST_OS=$llvm_cv_os_type + +TARGET_OS=$llvm_cv_target_os_type + + +LINKALL=$llvm_cv_link_all_option + +NOLINKALL=$llvm_cv_no_link_all_option + + +case $llvm_cv_platform_type in + Unix) + +cat >>confdefs.h <<\_ACEOF +#define LLVM_ON_UNIX 1 +_ACEOF + + LLVM_ON_UNIX=1 + + LLVM_ON_WIN32=0 + + ;; + Win32) + +cat >>confdefs.h <<\_ACEOF +#define LLVM_ON_WIN32 1 +_ACEOF + + LLVM_ON_UNIX=0 + + LLVM_ON_WIN32=1 + + ;; +esac + +{ echo "$as_me:$LINENO: checking target architecture" >&5 +echo $ECHO_N "checking target architecture... $ECHO_C" >&6; } +if test "${llvm_cv_target_arch+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $target in + i?86-*) llvm_cv_target_arch="x86" ;; + amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;; + sparc*-*) llvm_cv_target_arch="Sparc" ;; + powerpc*-*) llvm_cv_target_arch="PowerPC" ;; + arm*-*) llvm_cv_target_arch="ARM" ;; + aarch64*-*) llvm_cv_target_arch="AArch64" ;; + mips-* | mips64-*) llvm_cv_target_arch="Mips" ;; + mipsel-* | mips64el-*) llvm_cv_target_arch="Mips" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; + msp430-*) llvm_cv_target_arch="MSP430" ;; + hexagon-*) llvm_cv_target_arch="Hexagon" ;; + nvptx-*) llvm_cv_target_arch="NVPTX" ;; + s390x-*) llvm_cv_target_arch="SystemZ" ;; + *) llvm_cv_target_arch="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_target_arch" >&5 +echo "${ECHO_T}$llvm_cv_target_arch" >&6; } + +if test "$llvm_cv_target_arch" = "Unknown" ; then + { echo "$as_me:$LINENO: WARNING: Configuring LLVM for an unknown target archicture" >&5 +echo "$as_me: WARNING: Configuring LLVM for an unknown target archicture" >&2;} +fi + +case "$llvm_cv_target_arch" in + x86) LLVM_NATIVE_ARCH="X86" ;; + x86_64) LLVM_NATIVE_ARCH="X86" ;; + *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;; +esac + +ARCH=$llvm_cv_target_arch + + +case $host in + i?86-*) host_arch="x86" ;; + amd64-* | x86_64-*) host_arch="x86_64" ;; + sparc*-*) host_arch="Sparc" ;; + powerpc*-*) host_arch="PowerPC" ;; + arm*-*) host_arch="ARM" ;; + aarch64*-*) host_arch="AArch64" ;; + mips-* | mips64-*) host_arch="Mips" ;; + mipsel-* | mips64el-*) host_arch="Mips" ;; + xcore-*) host_arch="XCore" ;; + msp430-*) host_arch="MSP430" ;; + hexagon-*) host_arch="Hexagon" ;; + s390x-*) host_arch="SystemZ" ;; + *) host_arch="Unknown" ;; +esac + +if test "$host_arch" = "Unknown" ; then + { echo "$as_me:$LINENO: WARNING: Configuring LLVM for an unknown host archicture" >&5 +echo "$as_me: WARNING: Configuring LLVM for an unknown host archicture" >&2;} +fi + +HOST_ARCH=$host_arch + + + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_bigendian=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } +case $ac_cv_c_bigendian in + yes) + ENDIAN=big + ;; + no) + ENDIAN=little + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +if test "$cross_compiling" = yes; then + LLVM_CROSS_COMPILING=1 + + +{ echo "$as_me:$LINENO: checking for executable suffix on build platform" >&5 +echo $ECHO_N "checking for executable suffix on build platform... $ECHO_C" >&6; } +if test "${ac_cv_build_exeext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_build_exeext=.exe +else + ac_build_prefix=${build_alias}- + + # Extract the first word of "${ac_build_prefix}gcc", so it can be a program name with args. +set dummy ${ac_build_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CC="${ac_build_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CC"; then + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_BUILD_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_BUILD_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set BUILD_CC to just the basename; use the full file name. + shift + ac_cv_prog_BUILD_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi + fi + test -z "$BUILD_CC" && { { echo "$as_me:$LINENO: error: no acceptable cc found in \$PATH" >&5 +echo "$as_me: error: no acceptable cc found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + ac_build_link='${BUILD_CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_build_exeext= + if { (eval echo "$as_me:$LINENO: \"$ac_build_link\"") >&5 + (eval $ac_build_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.dSYM) ;; + *) ac_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { { echo "$as_me:$LINENO: error: installation or configuration problem: compiler cannot create executables." >&5 +echo "$as_me: error: installation or configuration problem: compiler cannot create executables." >&2;} + { (exit 1); exit 1; }; } + fi + rm -f conftest* + test x"${ac_cv_build_exeext}" = x && ac_cv_build_exeext=blank +fi +fi + +BUILD_EXEEXT="" +test x"${ac_cv_build_exeext}" != xblank && BUILD_EXEEXT=${ac_cv_build_exeext} +{ echo "$as_me:$LINENO: result: ${ac_cv_build_exeext}" >&5 +echo "${ECHO_T}${ac_cv_build_exeext}" >&6; } +ac_build_exeext=$BUILD_EXEEXT + + ac_build_prefix=${build_alias}- + # Extract the first word of "${ac_build_prefix}g++", so it can be a program name with args. +set dummy ${ac_build_prefix}g++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CXX="${ac_build_prefix}g++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CXX"; then + # Extract the first word of "g++", so it can be a program name with args. +set dummy g++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CXX="g++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CXX"; then + # Extract the first word of "c++", so it can be a program name with args. +set dummy c++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/c++"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_BUILD_CXX="c++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_BUILD_CXX + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set BUILD_CXX to just the basename; use the full file name. + shift + ac_cv_prog_BUILD_CXX="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi + fi +else + LLVM_CROSS_COMPILING=0 + +fi + +if test -d ".svn" -o -d "${srcdir}/.svn" -o -d ".git" -o -d "${srcdir}/.git"; then + cvsbuild="yes" + optimize="no" + CVSBUILD=CVSBUILD=1 + +else + cvsbuild="no" + optimize="yes" +fi + + +# Check whether --enable-libcpp was given. +if test "${enable_libcpp+set}" = set; then + enableval=$enable_libcpp; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_LIBCPP=1 + ;; + no) ENABLE_LIBCPP=0 + ;; + default) ENABLE_LIBCPP=0 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-libcpp. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-libcpp. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-cxx11 was given. +if test "${enable_cxx11+set}" = set; then + enableval=$enable_cxx11; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_CXX11=1 + ;; + no) ENABLE_CXX11=0 + ;; + default) ENABLE_CXX11=0 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-cxx11. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-cxx11. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-split-dwarf was given. +if test "${enable_split_dwarf+set}" = set; then + enableval=$enable_split_dwarf; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_SPLIT_DWARF=1 + ;; + no) ENABLE_SPLIT_DWARF=0 + ;; + default) ENABLE_SPLIT_DWARF=0 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-split-dwarf. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-split-dwarf. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +clang_arcmt="yes" +# Check whether --enable-clang-arcmt was given. +if test "${enable_clang_arcmt+set}" = set; then + enableval=$enable_clang_arcmt; clang_arcmt="$enableval" +else + enableval="yes" +fi + +case "$enableval" in + yes) ENABLE_CLANG_ARCMT=1 + ;; + no) ENABLE_CLANG_ARCMT=0 + ;; + default) ENABLE_CLANG_ARCMT=1 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-clang-arcmt. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-clang-arcmt. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +clang_static_analyzer="yes" +# Check whether --enable-clang-static-analyzer was given. +if test "${enable_clang_static_analyzer+set}" = set; then + enableval=$enable_clang_static_analyzer; clang_static_analyzer="$enableval" +else + enableval="yes" +fi + +case "$enableval" in + yes) ENABLE_CLANG_STATIC_ANALYZER=1 + ;; + no) + if test ${clang_arcmt} != "no" ; then + { { echo "$as_me:$LINENO: error: Cannot enable clang ARC Migration Tool while disabling static analyzer." >&5 +echo "$as_me: error: Cannot enable clang ARC Migration Tool while disabling static analyzer." >&2;} + { (exit 1); exit 1; }; } + fi + ENABLE_CLANG_STATIC_ANALYZER=0 + + ;; + default) ENABLE_CLANG_STATIC_ANALYZER=1 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-clang-static-analyzer. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-clang-static-analyzer. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-clang-rewriter was given. +if test "${enable_clang_rewriter+set}" = set; then + enableval=$enable_clang_rewriter; +else + enableval="yes" +fi + +case "$enableval" in + yes) ENABLE_CLANG_REWRITER=1 + ;; + no) + if test ${clang_arcmt} != "no" ; then + { { echo "$as_me:$LINENO: error: Cannot enable clang ARC Migration Tool while disabling rewriter." >&5 +echo "$as_me: error: Cannot enable clang ARC Migration Tool while disabling rewriter." >&2;} + { (exit 1); exit 1; }; } + fi + if test ${clang_static_analyzer} != "no" ; then + { { echo "$as_me:$LINENO: error: Cannot enable clang static analyzer while disabling rewriter." >&5 +echo "$as_me: error: Cannot enable clang static analyzer while disabling rewriter." >&2;} + { (exit 1); exit 1; }; } + fi + ENABLE_CLANG_REWRITER=0 + + ;; + default) ENABLE_CLANG_REWRITER=1 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-clang-rewriter. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-clang-rewriter. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-optimized was given. +if test "${enable_optimized+set}" = set; then + enableval=$enable_optimized; +else + enableval=$optimize +fi + +if test ${enableval} = "no" ; then + ENABLE_OPTIMIZED= + +else + ENABLE_OPTIMIZED=ENABLE_OPTIMIZED=1 + +fi + +# Check whether --enable-profiling was given. +if test "${enable_profiling+set}" = set; then + enableval=$enable_profiling; +else + enableval="no" +fi + +if test ${enableval} = "no" ; then + ENABLE_PROFILING= + +else + ENABLE_PROFILING=ENABLE_PROFILING=1 + +fi + +# Check whether --enable-assertions was given. +if test "${enable_assertions+set}" = set; then + enableval=$enable_assertions; +else + enableval="yes" +fi + +if test ${enableval} = "yes" ; then + DISABLE_ASSERTIONS= + +else + DISABLE_ASSERTIONS=DISABLE_ASSERTIONS=1 + +fi + +# Check whether --enable-werror was given. +if test "${enable_werror+set}" = set; then + enableval=$enable_werror; +else + enableval="no" +fi + +case "$enableval" in + yes) ENABLE_WERROR=1 + ;; + no) ENABLE_WERROR=0 + ;; + default) ENABLE_WERROR=0 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-werror. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-werror. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-expensive-checks was given. +if test "${enable_expensive_checks+set}" = set; then + enableval=$enable_expensive_checks; +else + enableval="no" +fi + +if test ${enableval} = "yes" ; then + ENABLE_EXPENSIVE_CHECKS=ENABLE_EXPENSIVE_CHECKS=1 + + EXPENSIVE_CHECKS=yes + +else + ENABLE_EXPENSIVE_CHECKS= + + EXPENSIVE_CHECKS=no + +fi + +# Check whether --enable-debug-runtime was given. +if test "${enable_debug_runtime+set}" = set; then + enableval=$enable_debug_runtime; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + DEBUG_RUNTIME= + +else + DEBUG_RUNTIME=DEBUG_RUNTIME=1 + +fi + +# Check whether --enable-debug-symbols was given. +if test "${enable_debug_symbols+set}" = set; then + enableval=$enable_debug_symbols; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + DEBUG_SYMBOLS= + +else + DEBUG_SYMBOLS=DEBUG_SYMBOLS=1 + +fi + +# Check whether --enable-keep-symbols was given. +if test "${enable_keep_symbols+set}" = set; then + enableval=$enable_keep_symbols; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + KEEP_SYMBOLS= + +else + KEEP_SYMBOLS=KEEP_SYMBOLS=1 + +fi + +# Check whether --enable-jit was given. +if test "${enable_jit+set}" = set; then + enableval=$enable_jit; +else + enableval=default +fi + +if test ${enableval} = "no" +then + JIT= + +else + case "$llvm_cv_target_arch" in + x86) TARGET_HAS_JIT=1 + ;; + Sparc) TARGET_HAS_JIT=0 + ;; + PowerPC) TARGET_HAS_JIT=1 + ;; + x86_64) TARGET_HAS_JIT=1 + ;; + ARM) TARGET_HAS_JIT=1 + ;; + AArch64) TARGET_HAS_JIT=0 + ;; + Mips) TARGET_HAS_JIT=1 + ;; + XCore) TARGET_HAS_JIT=0 + ;; + MSP430) TARGET_HAS_JIT=0 + ;; + Hexagon) TARGET_HAS_JIT=0 + ;; + NVPTX) TARGET_HAS_JIT=0 + ;; + SystemZ) TARGET_HAS_JIT=1 + ;; + *) TARGET_HAS_JIT=0 + ;; + esac +fi + +# Check whether --enable-docs was given. +if test "${enable_docs+set}" = set; then + enableval=$enable_docs; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_DOCS=1 + ;; + no) ENABLE_DOCS=0 + ;; + default) ENABLE_DOCS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-docs. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-docs. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-doxygen was given. +if test "${enable_doxygen+set}" = set; then + enableval=$enable_doxygen; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_DOXYGEN=1 + ;; + no) ENABLE_DOXYGEN=0 + ;; + default) ENABLE_DOXYGEN=0 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-doxygen. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-doxygen. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then + enableval=$enable_threads; +else + enableval=default +fi + +case "$enableval" in + yes) LLVM_ENABLE_THREADS=1 + ;; + no) LLVM_ENABLE_THREADS=0 + ;; + default) LLVM_ENABLE_THREADS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-threads. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-threads. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define LLVM_ENABLE_THREADS $LLVM_ENABLE_THREADS +_ACEOF + + +# Check whether --enable-pthreads was given. +if test "${enable_pthreads+set}" = set; then + enableval=$enable_pthreads; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_PTHREADS=1 + ;; + no) ENABLE_PTHREADS=0 + ;; + default) ENABLE_PTHREADS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-pthreads. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-pthreads. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-zlib was given. +if test "${enable_zlib+set}" = set; then + enableval=$enable_zlib; +else + enableval=default +fi + +case "$enableval" in + yes) LLVM_ENABLE_ZLIB=1 + ;; + no) LLVM_ENABLE_ZLIB=0 + ;; + default) LLVM_ENABLE_ZLIB=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-zlib. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-zlib. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define LLVM_ENABLE_ZLIB $LLVM_ENABLE_ZLIB +_ACEOF + + +# Check whether --enable-pic was given. +if test "${enable_pic+set}" = set; then + enableval=$enable_pic; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_PIC=1 + ;; + no) ENABLE_PIC=0 + ;; + default) ENABLE_PIC=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-pic. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-pic. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_PIC $ENABLE_PIC +_ACEOF + + +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_SHARED=1 + ;; + no) ENABLE_SHARED=0 + ;; + default) ENABLE_SHARED=0 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-shared. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-shared. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-embed-stdcxx was given. +if test "${enable_embed_stdcxx+set}" = set; then + enableval=$enable_embed_stdcxx; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_EMBED_STDCXX=1 + ;; + no) ENABLE_EMBED_STDCXX=0 + ;; + default) ENABLE_EMBED_STDCXX=0 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-embed-stdcxx. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-embed-stdcxx. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-timestamps was given. +if test "${enable_timestamps+set}" = set; then + enableval=$enable_timestamps; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_TIMESTAMPS=1 + ;; + no) ENABLE_TIMESTAMPS=0 + ;; + default) ENABLE_TIMESTAMPS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-timestamps. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-timestamps. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_TIMESTAMPS $ENABLE_TIMESTAMPS +_ACEOF + + +# Check whether --enable-backtraces was given. +if test "${enable_backtraces+set}" = set; then + enableval=$enable_backtraces; case "$enableval" in + yes) llvm_cv_enable_backtraces="yes" ;; + no) llvm_cv_enable_backtraces="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-backtraces. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-backtraces. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; + esac +else + llvm_cv_enable_backtraces="yes" +fi + +if test "$llvm_cv_enable_backtraces" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_BACKTRACES 1 +_ACEOF + +fi + +# Check whether --enable-crash-overrides was given. +if test "${enable_crash_overrides+set}" = set; then + enableval=$enable_crash_overrides; case "$enableval" in + yes) llvm_cv_enable_crash_overrides="yes" ;; + no) llvm_cv_enable_crash_overrides="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-crash-overrides. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-crash-overrides. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; + esac +else + llvm_cv_enable_crash_overrides="yes" +fi + +if test "$llvm_cv_enable_crash_overrides" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_CRASH_OVERRIDES 1 +_ACEOF + +fi + +TARGETS_TO_BUILD="" +# Check whether --enable-targets was given. +if test "${enable_targets+set}" = set; then + enableval=$enable_targets; +else + enableval=all +fi + +if test "$enableval" = host-only ; then + enableval=host +fi +case "$enableval" in + all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;; + *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_target" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + powerpc) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + aarch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;; + arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + mipsel) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + mips64) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + mips64el) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; + nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; + systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;; + host) case "$llvm_cv_target_arch" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + Sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + PowerPC) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + AArch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;; + ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; + NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; + SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 +echo "$as_me: error: Can not set target to build" >&2;} + { (exit 1); exit 1; }; } ;; + esac ;; + *) { { echo "$as_me:$LINENO: error: Unrecognized target $a_target" >&5 +echo "$as_me: error: Unrecognized target $a_target" >&2;} + { (exit 1); exit 1; }; } ;; + esac + done + ;; +esac + +# Check whether --enable-experimental-targets was given. +if test "${enable_experimental_targets+set}" = set; then + enableval=$enable_experimental_targets; +else + enableval=disable +fi + + +if test ${enableval} != "disable" +then + TARGETS_TO_BUILD="$enableval $TARGETS_TO_BUILD" +fi + +TARGETS_TO_BUILD=$TARGETS_TO_BUILD + + +for a_target in $TARGETS_TO_BUILD; do + if test "$a_target" = "$LLVM_NATIVE_ARCH"; then + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_ARCH $LLVM_NATIVE_ARCH +_ACEOF + + LLVM_NATIVE_TARGET="LLVMInitialize${LLVM_NATIVE_ARCH}Target" + LLVM_NATIVE_TARGETINFO="LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo" + LLVM_NATIVE_TARGETMC="LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC" + LLVM_NATIVE_ASMPRINTER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter" + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then + LLVM_NATIVE_ASMPARSER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser" + fi + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/Disassembler/Makefile ; then + LLVM_NATIVE_DISASSEMBLER="LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler" + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_TARGET $LLVM_NATIVE_TARGET +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_TARGETINFO $LLVM_NATIVE_TARGETINFO +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_TARGETMC $LLVM_NATIVE_TARGETMC +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_ASMPRINTER $LLVM_NATIVE_ASMPRINTER +_ACEOF + + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_ASMPARSER $LLVM_NATIVE_ASMPARSER +_ACEOF + + fi + if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/Disassembler/Makefile ; then + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_DISASSEMBLER $LLVM_NATIVE_DISASSEMBLER +_ACEOF + + fi + fi +done + +LLVM_ENUM_TARGETS="" +LLVM_ENUM_ASM_PRINTERS="" +LLVM_ENUM_ASM_PARSERS="" +LLVM_ENUM_DISASSEMBLERS="" +for target_to_build in $TARGETS_TO_BUILD; do + LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS" + if test -f ${srcdir}/lib/Target/${target_to_build}/*AsmPrinter.cpp ; then + LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmParser/Makefile ; then + LLVM_ENUM_ASM_PARSERS="LLVM_ASM_PARSER($target_to_build) $LLVM_ENUM_ASM_PARSERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/Disassembler/Makefile ; then + LLVM_ENUM_DISASSEMBLERS="LLVM_DISASSEMBLER($target_to_build) $LLVM_ENUM_DISASSEMBLERS"; + fi +done + + + + + + +# Check whether --with-optimize-option was given. +if test "${with_optimize_option+set}" = set; then + withval=$with_optimize_option; +else + withval=default +fi + +{ echo "$as_me:$LINENO: checking optimization flags" >&5 +echo $ECHO_N "checking optimization flags... $ECHO_C" >&6; } +case "$withval" in + default) + case "$llvm_cv_os_type" in + FreeBSD) optimize_option=-O2 ;; + MingW) optimize_option=-O2 ;; + *) optimize_option=-O3 ;; + esac ;; + *) optimize_option="$withval" ;; +esac +OPTIMIZE_OPTION=$optimize_option + +{ echo "$as_me:$LINENO: result: $optimize_option" >&5 +echo "${ECHO_T}$optimize_option" >&6; } + + +# Check whether --with-extra-options was given. +if test "${with_extra_options+set}" = set; then + withval=$with_extra_options; +else + withval=default +fi + +case "$withval" in + default) EXTRA_OPTIONS= ;; + *) EXTRA_OPTIONS=$withval ;; +esac +EXTRA_OPTIONS=$EXTRA_OPTIONS + + + +# Check whether --with-extra-ld-options was given. +if test "${with_extra_ld_options+set}" = set; then + withval=$with_extra_ld_options; +else + withval=default +fi + +case "$withval" in + default) EXTRA_LD_OPTIONS= ;; + *) EXTRA_LD_OPTIONS=$withval ;; +esac +EXTRA_LD_OPTIONS=$EXTRA_LD_OPTIONS + + +# Check whether --enable-bindings was given. +if test "${enable_bindings+set}" = set; then + enableval=$enable_bindings; +else + enableval=default +fi + +BINDINGS_TO_BUILD="" +case "$enableval" in + yes | default | auto) BINDINGS_TO_BUILD="auto" ;; + all ) BINDINGS_TO_BUILD="ocaml" ;; + none | no) BINDINGS_TO_BUILD="" ;; + *)for a_binding in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_binding" in + ocaml) BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" ;; + *) { { echo "$as_me:$LINENO: error: Unrecognized binding $a_binding" >&5 +echo "$as_me: error: Unrecognized binding $a_binding" >&2;} + { (exit 1); exit 1; }; } ;; + esac + done + ;; +esac + + +# Check whether --with-ocaml-libdir was given. +if test "${with_ocaml_libdir+set}" = set; then + withval=$with_ocaml_libdir; +else + withval=auto +fi + +case "$withval" in + auto) with_ocaml_libdir="$withval" ;; + /* | [A-Za-z]:[\\/]*) with_ocaml_libdir="$withval" ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-ocaml-libdir. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-ocaml-libdir. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +# Check whether --with-clang-srcdir was given. +if test "${with_clang_srcdir+set}" = set; then + withval=$with_clang_srcdir; +else + withval="-" +fi + +case "$withval" in + -) clang_src_root="" ;; + /* | [A-Za-z]:[\\/]*) clang_src_root="$withval" ;; + *) clang_src_root="$ac_pwd/$withval" ;; +esac +CLANG_SRC_ROOT=$clang_src_root + + + +# Check whether --with-clang-resource-dir was given. +if test "${with_clang_resource_dir+set}" = set; then + withval=$with_clang_resource_dir; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CLANG_RESOURCE_DIR "$withval" +_ACEOF + + + +# Check whether --with-c-include-dirs was given. +if test "${with_c_include_dirs+set}" = set; then + withval=$with_c_include_dirs; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define C_INCLUDE_DIRS "$withval" +_ACEOF + + +# Clang normally uses the system c++ headers and libraries. With this option, +# clang will use the ones provided by a gcc installation instead. This option should +# be passed the same value that was used with --prefix when configuring gcc. + +# Check whether --with-gcc-toolchain was given. +if test "${with_gcc_toolchain+set}" = set; then + withval=$with_gcc_toolchain; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define GCC_INSTALL_PREFIX "$withval" +_ACEOF + + + +# Check whether --with-default-sysroot was given. +if test "${with_default_sysroot+set}" = set; then + withval=$with_default_sysroot; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_SYSROOT "$withval" +_ACEOF + + + +# Check whether --with-binutils-include was given. +if test "${with_binutils_include+set}" = set; then + withval=$with_binutils_include; +else + withval=default +fi + +case "$withval" in + default) WITH_BINUTILS_INCDIR=default ;; + /* | [A-Za-z]:[\\/]*) WITH_BINUTILS_INCDIR=$withval ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-binutils-include. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-binutils-include. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac +if test "x$WITH_BINUTILS_INCDIR" != xdefault ; then + BINUTILS_INCDIR=$WITH_BINUTILS_INCDIR + + if test ! -f "$WITH_BINUTILS_INCDIR/plugin-api.h"; then + echo "$WITH_BINUTILS_INCDIR/plugin-api.h" + { { echo "$as_me:$LINENO: error: Invalid path to directory containing plugin-api.h." >&5 +echo "$as_me: error: Invalid path to directory containing plugin-api.h." >&2;} + { (exit 1); exit 1; }; }; + fi +fi + + +# Check whether --with-bug-report-url was given. +if test "${with_bug_report_url+set}" = set; then + withval=$with_bug_report_url; +else + withval="http://llvm.org/bugs/" +fi + + +cat >>confdefs.h <<_ACEOF +#define BUG_REPORT_URL "$withval" +_ACEOF + + +# Check whether --enable-terminfo was given. +if test "${enable_terminfo+set}" = set; then + enableval=$enable_terminfo; case "$enableval" in + yes) llvm_cv_enable_terminfo="yes" ;; + no) llvm_cv_enable_terminfo="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; + esac +else + llvm_cv_enable_terminfo="yes" +fi + + +# Check whether --enable-libffi was given. +if test "${enable_libffi+set}" = set; then + enableval=$enable_libffi; case "$enableval" in + yes) llvm_cv_enable_libffi="yes" ;; + no) llvm_cv_enable_libffi="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; + esac +else + llvm_cv_enable_libffi=no +fi + + + +# Check whether --with-internal-prefix was given. +if test "${with_internal_prefix+set}" = set; then + withval=$with_internal_prefix; +else + withval="" +fi + +INTERNAL_PREFIX=$withval + + + +{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6; } +NM="$lt_cv_path_NM" + + + +{ echo "$as_me:$LINENO: checking for GNU make" >&5 +echo $ECHO_N "checking for GNU make... $ECHO_C" >&6; } +if test "${llvm_cv_gnu_make_command+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + llvm_cv_gnu_make_command='' + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) + then + llvm_cv_gnu_make_command=$a ; + break; + fi + done +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_gnu_make_command" >&5 +echo "${ECHO_T}$llvm_cv_gnu_make_command" >&6; } + if test "x$llvm_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + else + ifGNUmake='#' ; + { echo "$as_me:$LINENO: result: \"Not found\"" >&5 +echo "${ECHO_T}\"Not found\"" >&6; }; + fi + + +{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6; } +fi + +# Extract the first word of "cmp", so it can be a program name with args. +set dummy cmp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CMP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CMP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CMP="$CMP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CMP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CMP" && ac_cv_path_CMP="cmp" + ;; +esac +fi +CMP=$ac_cv_path_CMP +if test -n "$CMP"; then + { echo "$as_me:$LINENO: result: $CMP" >&5 +echo "${ECHO_T}$CMP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "cp", so it can be a program name with args. +set dummy cp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CP="$CP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CP" && ac_cv_path_CP="cp" + ;; +esac +fi +CP=$ac_cv_path_CP +if test -n "$CP"; then + { echo "$as_me:$LINENO: result: $CP" >&5 +echo "${ECHO_T}$CP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "date", so it can be a program name with args. +set dummy date; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DATE+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DATE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DATE="$DATE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DATE="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DATE" && ac_cv_path_DATE="date" + ;; +esac +fi +DATE=$ac_cv_path_DATE +if test -n "$DATE"; then + { echo "$as_me:$LINENO: result: $DATE" >&5 +echo "${ECHO_T}$DATE" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "find", so it can be a program name with args. +set dummy find; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FIND+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FIND in + [\\/]* | ?:[\\/]*) + ac_cv_path_FIND="$FIND" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FIND="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FIND" && ac_cv_path_FIND="find" + ;; +esac +fi +FIND=$ac_cv_path_FIND +if test -n "$FIND"; then + { echo "$as_me:$LINENO: result: $FIND" >&5 +echo "${ECHO_T}$FIND" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "grep", so it can be a program name with args. +set dummy grep; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GREP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GREP="$GREP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GREP" && ac_cv_path_GREP="grep" + ;; +esac +fi +GREP=$ac_cv_path_GREP +if test -n "$GREP"; then + { echo "$as_me:$LINENO: result: $GREP" >&5 +echo "${ECHO_T}$GREP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "mkdir", so it can be a program name with args. +set dummy mkdir; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_MKDIR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MKDIR in + [\\/]* | ?:[\\/]*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_MKDIR" && ac_cv_path_MKDIR="mkdir" + ;; +esac +fi +MKDIR=$ac_cv_path_MKDIR +if test -n "$MKDIR"; then + { echo "$as_me:$LINENO: result: $MKDIR" >&5 +echo "${ECHO_T}$MKDIR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "mv", so it can be a program name with args. +set dummy mv; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_MV+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MV in + [\\/]* | ?:[\\/]*) + ac_cv_path_MV="$MV" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_MV" && ac_cv_path_MV="mv" + ;; +esac +fi +MV=$ac_cv_path_MV +if test -n "$MV"; then + { echo "$as_me:$LINENO: result: $MV" >&5 +echo "${ECHO_T}$MV" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_RM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RM in + [\\/]* | ?:[\\/]*) + ac_cv_path_RM="$RM" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm" + ;; +esac +fi +RM=$ac_cv_path_RM +if test -n "$RM"; then + { echo "$as_me:$LINENO: result: $RM" >&5 +echo "${ECHO_T}$RM" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $SED in + [\\/]* | ?:[\\/]*) + ac_cv_path_SED="$SED" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SED" && ac_cv_path_SED="sed" + ;; +esac +fi +SED=$ac_cv_path_SED +if test -n "$SED"; then + { echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "tar", so it can be a program name with args. +set dummy tar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TAR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TAR in + [\\/]* | ?:[\\/]*) + ac_cv_path_TAR="$TAR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_TAR" && ac_cv_path_TAR="gtar" + ;; +esac +fi +TAR=$ac_cv_path_TAR +if test -n "$TAR"; then + { echo "$as_me:$LINENO: result: $TAR" >&5 +echo "${ECHO_T}$TAR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pwd", so it can be a program name with args. +set dummy pwd; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_BINPWD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $BINPWD in + [\\/]* | ?:[\\/]*) + ac_cv_path_BINPWD="$BINPWD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_BINPWD="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_BINPWD" && ac_cv_path_BINPWD="pwd" + ;; +esac +fi +BINPWD=$ac_cv_path_BINPWD +if test -n "$BINPWD"; then + { echo "$as_me:$LINENO: result: $BINPWD" >&5 +echo "${ECHO_T}$BINPWD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +# Extract the first word of "Graphviz", so it can be a program name with args. +set dummy Graphviz; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GRAPHVIZ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GRAPHVIZ in + [\\/]* | ?:[\\/]*) + ac_cv_path_GRAPHVIZ="$GRAPHVIZ" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GRAPHVIZ="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GRAPHVIZ" && ac_cv_path_GRAPHVIZ="echo Graphviz" + ;; +esac +fi +GRAPHVIZ=$ac_cv_path_GRAPHVIZ +if test -n "$GRAPHVIZ"; then + { echo "$as_me:$LINENO: result: $GRAPHVIZ" >&5 +echo "${ECHO_T}$GRAPHVIZ" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$GRAPHVIZ" != "echo Graphviz" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GRAPHVIZ 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + GRAPHVIZ=`echo $GRAPHVIZ | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_GRAPHVIZ "$GRAPHVIZ${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "dot", so it can be a program name with args. +set dummy dot; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOT in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOT="$DOT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOT" && ac_cv_path_DOT="echo dot" + ;; +esac +fi +DOT=$ac_cv_path_DOT +if test -n "$DOT"; then + { echo "$as_me:$LINENO: result: $DOT" >&5 +echo "${ECHO_T}$DOT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$DOT" != "echo dot" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOT 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + DOT=`echo $DOT | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_DOT "$DOT${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "fdp", so it can be a program name with args. +set dummy fdp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FDP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FDP in + [\\/]* | ?:[\\/]*) + ac_cv_path_FDP="$FDP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FDP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FDP" && ac_cv_path_FDP="echo fdp" + ;; +esac +fi +FDP=$ac_cv_path_FDP +if test -n "$FDP"; then + { echo "$as_me:$LINENO: result: $FDP" >&5 +echo "${ECHO_T}$FDP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$FDP" != "echo fdp" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FDP 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + FDP=`echo $FDP | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_FDP "$FDP${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "neato", so it can be a program name with args. +set dummy neato; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_NEATO+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $NEATO in + [\\/]* | ?:[\\/]*) + ac_cv_path_NEATO="$NEATO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_NEATO="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_NEATO" && ac_cv_path_NEATO="echo neato" + ;; +esac +fi +NEATO=$ac_cv_path_NEATO +if test -n "$NEATO"; then + { echo "$as_me:$LINENO: result: $NEATO" >&5 +echo "${ECHO_T}$NEATO" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$NEATO" != "echo neato" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NEATO 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + NEATO=`echo $NEATO | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_NEATO "$NEATO${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "twopi", so it can be a program name with args. +set dummy twopi; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TWOPI+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TWOPI in + [\\/]* | ?:[\\/]*) + ac_cv_path_TWOPI="$TWOPI" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TWOPI="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_TWOPI" && ac_cv_path_TWOPI="echo twopi" + ;; +esac +fi +TWOPI=$ac_cv_path_TWOPI +if test -n "$TWOPI"; then + { echo "$as_me:$LINENO: result: $TWOPI" >&5 +echo "${ECHO_T}$TWOPI" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$TWOPI" != "echo twopi" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TWOPI 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + TWOPI=`echo $TWOPI | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_TWOPI "$TWOPI${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "circo", so it can be a program name with args. +set dummy circo; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CIRCO+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CIRCO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CIRCO="$CIRCO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CIRCO="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CIRCO" && ac_cv_path_CIRCO="echo circo" + ;; +esac +fi +CIRCO=$ac_cv_path_CIRCO +if test -n "$CIRCO"; then + { echo "$as_me:$LINENO: result: $CIRCO" >&5 +echo "${ECHO_T}$CIRCO" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$CIRCO" != "echo circo" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CIRCO 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + CIRCO=`echo $CIRCO | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_CIRCO "$CIRCO${EXEEXT}" +_ACEOF + +fi +for ac_prog in gv gsview32 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GV+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GV in + [\\/]* | ?:[\\/]*) + ac_cv_path_GV="$GV" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GV="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GV=$ac_cv_path_GV +if test -n "$GV"; then + { echo "$as_me:$LINENO: result: $GV" >&5 +echo "${ECHO_T}$GV" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$GV" && break +done +test -n "$GV" || GV="echo gv" + +if test "$GV" != "echo gv" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GV 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + GV=`echo $GV | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_GV "$GV${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "dotty", so it can be a program name with args. +set dummy dotty; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOTTY+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOTTY in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOTTY="$DOTTY" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOTTY="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOTTY" && ac_cv_path_DOTTY="echo dotty" + ;; +esac +fi +DOTTY=$ac_cv_path_DOTTY +if test -n "$DOTTY"; then + { echo "$as_me:$LINENO: result: $DOTTY" >&5 +echo "${ECHO_T}$DOTTY" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$DOTTY" != "echo dotty" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOTTY 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + DOTTY=`echo $DOTTY | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_DOTTY "$DOTTY${EXEEXT}" +_ACEOF + +fi +for ac_prog in xdot xdot.py +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_XDOT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $XDOT in + [\\/]* | ?:[\\/]*) + ac_cv_path_XDOT="$XDOT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_XDOT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +XDOT=$ac_cv_path_XDOT +if test -n "$XDOT"; then + { echo "$as_me:$LINENO: result: $XDOT" >&5 +echo "${ECHO_T}$XDOT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$XDOT" && break +done +test -n "$XDOT" || XDOT="echo xdot" + +if test "$XDOT" != "echo xdot" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_XDOT 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + XDOT=`echo $XDOT | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_XDOT "$XDOT${EXEEXT}" +_ACEOF + +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +case "$INSTALL" in + [\\/$]* | ?:[\\/]* ) ;; + *) INSTALL="\\\$(TOPSRCDIR)/$INSTALL" ;; +esac + +# Extract the first word of "bzip2", so it can be a program name with args. +set dummy bzip2; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_BZIP2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $BZIP2 in + [\\/]* | ?:[\\/]*) + ac_cv_path_BZIP2="$BZIP2" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_BZIP2="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +BZIP2=$ac_cv_path_BZIP2 +if test -n "$BZIP2"; then + { echo "$as_me:$LINENO: result: $BZIP2" >&5 +echo "${ECHO_T}$BZIP2" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "cat", so it can be a program name with args. +set dummy cat; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CAT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CAT in + [\\/]* | ?:[\\/]*) + ac_cv_path_CAT="$CAT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CAT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +CAT=$ac_cv_path_CAT +if test -n "$CAT"; then + { echo "$as_me:$LINENO: result: $CAT" >&5 +echo "${ECHO_T}$CAT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOXYGEN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOXYGEN in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +DOXYGEN=$ac_cv_path_DOXYGEN +if test -n "$DOXYGEN"; then + { echo "$as_me:$LINENO: result: $DOXYGEN" >&5 +echo "${ECHO_T}$DOXYGEN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "groff", so it can be a program name with args. +set dummy groff; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GROFF+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GROFF=$ac_cv_path_GROFF +if test -n "$GROFF"; then + { echo "$as_me:$LINENO: result: $GROFF" >&5 +echo "${ECHO_T}$GROFF" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "gzip", so it can be a program name with args. +set dummy gzip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GZIPBIN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GZIPBIN in + [\\/]* | ?:[\\/]*) + ac_cv_path_GZIPBIN="$GZIPBIN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GZIPBIN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GZIPBIN=$ac_cv_path_GZIPBIN +if test -n "$GZIPBIN"; then + { echo "$as_me:$LINENO: result: $GZIPBIN" >&5 +echo "${ECHO_T}$GZIPBIN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pdfroff", so it can be a program name with args. +set dummy pdfroff; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PDFROFF+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PDFROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_PDFROFF="$PDFROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PDFROFF="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +PDFROFF=$ac_cv_path_PDFROFF +if test -n "$PDFROFF"; then + { echo "$as_me:$LINENO: result: $PDFROFF" >&5 +echo "${ECHO_T}$PDFROFF" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "zip", so it can be a program name with args. +set dummy zip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_ZIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +ZIP=$ac_cv_path_ZIP +if test -n "$ZIP"; then + { echo "$as_me:$LINENO: result: $ZIP" >&5 +echo "${ECHO_T}$ZIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +for ac_prog in ocamlc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLC in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLC="$OCAMLC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLC=$ac_cv_path_OCAMLC +if test -n "$OCAMLC"; then + { echo "$as_me:$LINENO: result: $OCAMLC" >&5 +echo "${ECHO_T}$OCAMLC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLC" && break +done + +for ac_prog in ocamlopt +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLOPT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLOPT in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLOPT="$OCAMLOPT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLOPT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLOPT=$ac_cv_path_OCAMLOPT +if test -n "$OCAMLOPT"; then + { echo "$as_me:$LINENO: result: $OCAMLOPT" >&5 +echo "${ECHO_T}$OCAMLOPT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLOPT" && break +done + +for ac_prog in ocamldep +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLDEP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLDEP in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLDEP="$OCAMLDEP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLDEP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLDEP=$ac_cv_path_OCAMLDEP +if test -n "$OCAMLDEP"; then + { echo "$as_me:$LINENO: result: $OCAMLDEP" >&5 +echo "${ECHO_T}$OCAMLDEP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLDEP" && break +done + +for ac_prog in ocamldoc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLDOC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLDOC in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLDOC="$OCAMLDOC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLDOC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLDOC=$ac_cv_path_OCAMLDOC +if test -n "$OCAMLDOC"; then + { echo "$as_me:$LINENO: result: $OCAMLDOC" >&5 +echo "${ECHO_T}$OCAMLDOC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLDOC" && break +done + +for ac_prog in gas as +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GAS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GAS in + [\\/]* | ?:[\\/]*) + ac_cv_path_GAS="$GAS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GAS="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GAS=$ac_cv_path_GAS +if test -n "$GAS"; then + { echo "$as_me:$LINENO: result: $GAS" >&5 +echo "${ECHO_T}$GAS" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$GAS" && break +done + + +{ echo "$as_me:$LINENO: checking for linker version" >&5 +echo $ECHO_N "checking for linker version... $ECHO_C" >&6; } +if test "${llvm_cv_link_version+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + version_string="$(ld -v 2>&1 | head -1)" + + # Check for ld64. + if (echo "$version_string" | grep -q "ld64"); then + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#.*ld64-\([^ ]*\)\( (.*)\)\{0,1\}#\1#") + else + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#[^0-9]*\([0-9.]*\).*#\1#") + fi + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_version" >&5 +echo "${ECHO_T}$llvm_cv_link_version" >&6; } + +cat >>confdefs.h <<_ACEOF +#define HOST_LINK_VERSION "$llvm_cv_link_version" +_ACEOF + + + +{ echo "$as_me:$LINENO: checking for compiler -Wl,-R option" >&5 +echo $ECHO_N "checking for compiler -Wl,-R option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_r+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-R." + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_r=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_r=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_r" >&5 +echo "${ECHO_T}$llvm_cv_link_use_r" >&6; } +if test "$llvm_cv_link_use_r" = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LINK_R 1 +_ACEOF + + fi + + +{ echo "$as_me:$LINENO: checking for compiler -rdynamic option" >&5 +echo $ECHO_N "checking for compiler -rdynamic option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_export_dynamic+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -rdynamic" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_export_dynamic=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_export_dynamic=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_export_dynamic" >&5 +echo "${ECHO_T}$llvm_cv_link_use_export_dynamic" >&6; } +if test "$llvm_cv_link_use_export_dynamic" = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LINK_EXPORT_DYNAMIC 1 +_ACEOF + + fi + + +{ echo "$as_me:$LINENO: checking for compiler -Wl,--version-script option" >&5 +echo $ECHO_N "checking for compiler -Wl,--version-script option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_version_script+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + + # The following code is from the autoconf manual, + # "11.13: Limitations of Usual Tools". + # Create a temporary directory $tmp in $TMPDIR (default /tmp). + # Use mktemp if possible; otherwise fall back on mkdir, + # with $RANDOM to make collisions less likely. + : ${TMPDIR=/tmp} + { + tmp=` + (umask 077 && mktemp -d "$TMPDIR/fooXXXXXX") 2>/dev/null + ` && + test -n "$tmp" && test -d "$tmp" + } || { + tmp=$TMPDIR/foo$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || exit $? + + echo "{" > "$tmp/export.map" + echo " global: main;" >> "$tmp/export.map" + echo " local: *;" >> "$tmp/export.map" + echo "};" >> "$tmp/export.map" + + CFLAGS="$CFLAGS -Wl,--version-script=$tmp/export.map" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_version_script=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_version_script=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + rm "$tmp/export.map" + rmdir "$tmp" + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_version_script" >&5 +echo "${ECHO_T}$llvm_cv_link_use_version_script" >&6; } +if test "$llvm_cv_link_use_version_script" = yes ; then + HAVE_LINK_VERSION_SCRIPT=1 + + fi + + + + +{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !x[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +# Check whether --enable-ltdl-install was given. +if test "${enable_ltdl_install+set}" = set; then + enableval=$enable_ltdl_install; +fi + + + + +if test x"${enable_ltdl_install-no}" != xno; then + INSTALL_LTDL_TRUE= + INSTALL_LTDL_FALSE='#' +else + INSTALL_LTDL_TRUE='#' + INSTALL_LTDL_FALSE= +fi + + + +if test x"${enable_ltdl_convenience-no}" != xno; then + CONVENIENCE_LTDL_TRUE= + CONVENIENCE_LTDL_FALSE='#' +else + CONVENIENCE_LTDL_TRUE='#' + CONVENIENCE_LTDL_FALSE= +fi + + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1.*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + + +{ echo "$as_me:$LINENO: checking which extension is used for loadable modules" >&5 +echo $ECHO_N "checking which extension is used for loadable modules... $ECHO_C" >&6; } +if test "${libltdl_cv_shlibext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibext" >&5 +echo "${ECHO_T}$libltdl_cv_shlibext" >&6; } +if test -n "$libltdl_cv_shlibext"; then + +cat >>confdefs.h <<_ACEOF +#define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for the default library search path" >&5 +echo $ECHO_N "checking for the default library search path... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_search_path+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec" +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_search_path" >&5 +echo "${ECHO_T}$libltdl_cv_sys_search_path" >&6; } +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + +cat >>confdefs.h <<_ACEOF +#define LTDL_SYSSEARCHPATH "$sys_search_path" +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${libltdl_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_objdir" >&5 +echo "${ECHO_T}$libltdl_cv_objdir" >&6; } + +cat >>confdefs.h <<_ACEOF +#define LTDL_OBJDIR "$libltdl_cv_objdir/" +_ACEOF + + + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } +else + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + + +{ echo "$as_me:$LINENO: checking whether libtool supports -dlopen/-dlpreopen" >&5 +echo $ECHO_N "checking whether libtool supports -dlopen/-dlpreopen... $ECHO_C" >&6; } +if test "${libltdl_cv_preloaded_symbols+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_preloaded_symbols" >&5 +echo "${ECHO_T}$libltdl_cv_preloaded_symbols" >&6; } +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PRELOADED_SYMBOLS 1 +_ACEOF + +fi + +LIBADD_DL= + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case declares shl_load. + For example, HP-UX 11i declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_DLFCN_H +# include +#endif + +int +main () +{ +dlopen(0, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + libltdl_cv_func_dlopen="yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for _dyld_func_lookup" >&5 +echo $ECHO_N "checking for _dyld_func_lookup... $ECHO_C" >&6; } +if test "${ac_cv_func__dyld_func_lookup+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define _dyld_func_lookup to an innocuous variant, in case declares _dyld_func_lookup. + For example, HP-UX 11i declares gettimeofday. */ +#define _dyld_func_lookup innocuous__dyld_func_lookup + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char _dyld_func_lookup (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef _dyld_func_lookup + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _dyld_func_lookup (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub__dyld_func_lookup || defined __stub____dyld_func_lookup +choke me +#endif + +int +main () +{ +return _dyld_func_lookup (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func__dyld_func_lookup=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func__dyld_func_lookup=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5 +echo "${ECHO_T}$ac_cv_func__dyld_func_lookup" >&6; } +if test $ac_cv_func__dyld_func_lookup = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DYLD 1 +_ACEOF + +fi + + +fi + + +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + + +fi + + +fi + + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + +for ac_func in dlerror +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS="$lt_save_LIBS" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +{ echo "$as_me:$LINENO: checking for _ prefix in compiled symbols" >&5 +echo $ECHO_N "checking for _ prefix in compiled symbols... $ECHO_C" >&6; } +if test "${ac_cv_sys_symbol_underscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&5 + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -rf conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_sys_symbol_underscore" >&5 +echo "${ECHO_T}$ac_cv_sys_symbol_underscore" >&6; } + + +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + { echo "$as_me:$LINENO: checking whether we have to add an underscore for dlsym" >&5 +echo $ECHO_N "checking whether we have to add an underscore for dlsym... $ECHO_C" >&6; } +if test "${libltdl_cv_need_uscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + if test "$cross_compiling" = yes; then : + libltdl_cv_need_uscore=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; + x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; + x$lt_dlunknown|x*) ;; + esac + else : + # compilation failed + + fi +fi +rm -fr conftest* + + LIBS="$save_LIBS" + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_need_uscore" >&5 +echo "${ECHO_T}$libltdl_cv_need_uscore" >&6; } + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define NEED_USCORE 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking whether deplibs are loaded by dlopen" >&5 +echo $ECHO_N "checking whether deplibs are loaded by dlopen... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_dlopen_deplibs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[45]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[12345]*|irix6.[01]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[1234]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explicitly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_dlopen_deplibs" >&5 +echo "${ECHO_T}$libltdl_cv_sys_dlopen_deplibs" >&6; } +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + +cat >>confdefs.h <<\_ACEOF +#define LTDL_DLOPEN_DEPLIBS 1 +_ACEOF + +fi + + +for ac_header in argz.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking for error_t" >&5 +echo $ECHO_N "checking for error_t... $ECHO_C" >&6; } +if test "${ac_cv_type_error_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_ARGZ_H +# include +#endif + +typedef error_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_error_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_error_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_error_t" >&5 +echo "${ECHO_T}$ac_cv_type_error_t" >&6; } +if test $ac_cv_type_error_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_ERROR_T 1 +_ACEOF + + +else + +cat >>confdefs.h <<\_ACEOF +#define error_t int +_ACEOF + +fi + + + + + + + +for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + + + + + + + + + + + + + + + + + +for ac_header in errno.h malloc.h memory.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in mach-o/dyld.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_func in closedir opendir readdir +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +{ echo "$as_me:$LINENO: checking tool compatibility" >&5 +echo $ECHO_N "checking tool compatibility... $ECHO_C" >&6; } + +ICC=no +IXX=no +case $CC in + icc*|icpc*) + ICC=yes + IXX=yes + ;; + *) + ;; +esac + +if test "$GCC" != "yes" && test "$ICC" != "yes" +then + { { echo "$as_me:$LINENO: error: gcc|icc required but not found" >&5 +echo "$as_me: error: gcc|icc required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +if test "$GXX" != "yes" && test "$IXX" != "yes" +then + { { echo "$as_me:$LINENO: error: g++|clang++|icc required but not found" >&5 +echo "$as_me: error: g++|clang++|icc required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +if test "$GCC" = "yes" +then + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #if !defined(__GNUC__) || __GNUC__ < 3 + #error Unsupported GCC version + #endif + + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { { echo "$as_me:$LINENO: error: gcc 3.x required, but you have a lower version" >&5 +echo "$as_me: error: gcc 3.x required, but you have a lower version" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if test -z "$llvm_cv_gnu_make_command" +then + { { echo "$as_me:$LINENO: error: GNU Make required but not found" >&5 +echo "$as_me: error: GNU Make required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } + +{ echo "$as_me:$LINENO: checking optional compiler flags" >&5 +echo $ECHO_N "checking optional compiler flags... $ECHO_C" >&6; } +NO_VARIADIC_MACROS=`$CXX -Werror -Wvariadic-macros -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-variadic-macros` + +NO_MISSING_FIELD_INITIALIZERS=`$CXX -Werror -Wmissing-field-initializers -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-missing-field-initializers` + +COVERED_SWITCH_DEFAULT=`$CXX -Werror -Wcovered-switch-default -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wcovered-switch-default` + + +NO_UNINITIALIZED= +NO_MAYBE_UNINITIALIZED= +if test "$GXX" = "yes" +then + NO_MAYBE_UNINITIALIZED=`$CXX -Werror -Wmaybe-uninitialized -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-maybe-uninitialized` + + if test -z "$NO_MAYBE_UNINITIALIZED" + then + NO_UNINITIALIZED=`$CXX -Werror -Wuninitialized -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-uninitialized` + + fi +fi +{ echo "$as_me:$LINENO: result: $NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS $COVERED_SWITCH_DEFAULT $NO_UNINITIALIZED $NO_MAYBE_UNINITIALIZED" >&5 +echo "${ECHO_T}$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS $COVERED_SWITCH_DEFAULT $NO_UNINITIALIZED $NO_MAYBE_UNINITIALIZED" >&6; } + + +# Check whether --with-python was given. +if test "${with_python+set}" = set; then + withval=$with_python; PYTHON="$withval" +fi + + +if test -n "$PYTHON" && test -x "$PYTHON" ; then + { echo "$as_me:$LINENO: checking for python" >&5 +echo $ECHO_N "checking for python... $ECHO_C" >&6; } + { echo "$as_me:$LINENO: result: user defined: $with_python" >&5 +echo "${ECHO_T}user defined: $with_python" >&6; } +else + if test -n "$PYTHON" ; then + { echo "$as_me:$LINENO: WARNING: specified python ($PYTHON) is not usable, searching path" >&5 +echo "$as_me: WARNING: specified python ($PYTHON) is not usable, searching path" >&2;} + fi + + # Extract the first word of "python python2 python26", so it can be a program name with args. +set dummy python python2 python26; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PYTHON+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PYTHON" && ac_cv_path_PYTHON="{ echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; } + { { echo "$as_me:$LINENO: error: could not find python 2.5 or higher" >&5 +echo "$as_me: error: could not find python 2.5 or higher" >&2;} + { (exit 1); exit 1; }; }" + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { echo "$as_me:$LINENO: result: $PYTHON" >&5 +echo "${ECHO_T}$PYTHON" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi + +{ echo "$as_me:$LINENO: checking for python >= 2.5" >&5 +echo $ECHO_N "checking for python >= 2.5... $ECHO_C" >&6; } +ac_python_version=`$PYTHON -V 2>&1 | cut -d' ' -f2` +ac_python_version_major=`echo $ac_python_version | cut -d'.' -f1` +ac_python_version_minor=`echo $ac_python_version | cut -d'.' -f2` +ac_python_version_patch=`echo $ac_python_version | cut -d'.' -f3` +if test "$ac_python_version_major" -gt "2" || \ + (test "$ac_python_version_major" -eq "2" && \ + test "$ac_python_version_minor" -ge "5") ; then + { echo "$as_me:$LINENO: result: $PYTHON ($ac_python_version)" >&5 +echo "${ECHO_T}$PYTHON ($ac_python_version)" >&6; } +else + { echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; } + { { echo "$as_me:$LINENO: error: found python $ac_python_version ($PYTHON); required >= 2.5 +See \`config.log' for more details." >&5 +echo "$as_me: error: found python $ac_python_version ($PYTHON); required >= 2.5 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + + + +{ echo "$as_me:$LINENO: checking for sin in -lm" >&5 +echo $ECHO_N "checking for sin in -lm... $ECHO_C" >&6; } +if test "${ac_cv_lib_m_sin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sin (); +int +main () +{ +return sin (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_sin=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_m_sin=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_sin" >&5 +echo "${ECHO_T}$ac_cv_lib_m_sin" >&6; } +if test $ac_cv_lib_m_sin = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + +if test "$llvm_cv_os_type" = "MingW" ; then + +{ echo "$as_me:$LINENO: checking for main in -limagehlp" >&5 +echo $ECHO_N "checking for main in -limagehlp... $ECHO_C" >&6; } +if test "${ac_cv_lib_imagehlp_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-limagehlp $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_imagehlp_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_imagehlp_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_imagehlp_main" >&5 +echo "${ECHO_T}$ac_cv_lib_imagehlp_main" >&6; } +if test $ac_cv_lib_imagehlp_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBIMAGEHLP 1 +_ACEOF + + LIBS="-limagehlp $LIBS" + +fi + + +{ echo "$as_me:$LINENO: checking for main in -lpsapi" >&5 +echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; } +if test "${ac_cv_lib_psapi_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpsapi $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_psapi_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_psapi_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_psapi_main" >&5 +echo "${ECHO_T}$ac_cv_lib_psapi_main" >&6; } +if test $ac_cv_lib_psapi_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPSAPI 1 +_ACEOF + + LIBS="-lpsapi $LIBS" + +fi + + +{ echo "$as_me:$LINENO: checking for main in -lshell32" >&5 +echo $ECHO_N "checking for main in -lshell32... $ECHO_C" >&6; } +if test "${ac_cv_lib_shell32_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lshell32 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_shell32_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_shell32_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_shell32_main" >&5 +echo "${ECHO_T}$ac_cv_lib_shell32_main" >&6; } +if test $ac_cv_lib_shell32_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSHELL32 1 +_ACEOF + + LIBS="-lshell32 $LIBS" + +fi + +fi + +{ echo "$as_me:$LINENO: checking for library containing dlopen" >&5 +echo $ECHO_N "checking for library containing dlopen... $ECHO_C" >&6; } +if test "${ac_cv_search_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_dlopen=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_dlopen+set}" = set; then + break +fi +done +if test "${ac_cv_search_dlopen+set}" = set; then + : +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5 +echo "${ECHO_T}$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLOPEN 1 +_ACEOF + +else + { echo "$as_me:$LINENO: WARNING: dlopen() not found - disabling plugin support" >&5 +echo "$as_me: WARNING: dlopen() not found - disabling plugin support" >&2;} +fi + + +{ echo "$as_me:$LINENO: checking for library containing clock_gettime" >&5 +echo $ECHO_N "checking for library containing clock_gettime... $ECHO_C" >&6; } +if test "${ac_cv_search_clock_gettime+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_clock_gettime=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_clock_gettime+set}" = set; then + break +fi +done +if test "${ac_cv_search_clock_gettime+set}" = set; then + : +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_clock_gettime" >&5 +echo "${ECHO_T}$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +if test "$llvm_cv_enable_terminfo" = "yes" ; then + { echo "$as_me:$LINENO: checking for library containing setupterm" >&5 +echo $ECHO_N "checking for library containing setupterm... $ECHO_C" >&6; } +if test "${ac_cv_search_setupterm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char setupterm (); +int +main () +{ +return setupterm (); + ; + return 0; +} +_ACEOF +for ac_lib in '' tinfo terminfo curses ncurses ncursesw; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_setupterm=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_setupterm+set}" = set; then + break +fi +done +if test "${ac_cv_search_setupterm+set}" = set; then + : +else + ac_cv_search_setupterm=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_setupterm" >&5 +echo "${ECHO_T}$ac_cv_search_setupterm" >&6; } +ac_res=$ac_cv_search_setupterm +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TERMINFO 1 +_ACEOF + +fi + +fi + +if test "$llvm_cv_enable_libffi" = "yes" ; then + { echo "$as_me:$LINENO: checking for library containing ffi_call" >&5 +echo $ECHO_N "checking for library containing ffi_call... $ECHO_C" >&6; } +if test "${ac_cv_search_ffi_call+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ffi_call (); +int +main () +{ +return ffi_call (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ffi; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_ffi_call=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_ffi_call+set}" = set; then + break +fi +done +if test "${ac_cv_search_ffi_call+set}" = set; then + : +else + ac_cv_search_ffi_call=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_ffi_call" >&5 +echo "${ECHO_T}$ac_cv_search_ffi_call" >&6; } +ac_res=$ac_cv_search_ffi_call +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FFI_CALL 1 +_ACEOF + +else + { { echo "$as_me:$LINENO: error: libffi not found - configure without --enable-libffi to compile without it" >&5 +echo "$as_me: error: libffi not found - configure without --enable-libffi to compile without it" >&2;} + { (exit 1); exit 1; }; } +fi + +fi + +{ echo "$as_me:$LINENO: checking for library containing mallinfo" >&5 +echo $ECHO_N "checking for library containing mallinfo... $ECHO_C" >&6; } +if test "${ac_cv_search_mallinfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char mallinfo (); +int +main () +{ +return mallinfo (); + ; + return 0; +} +_ACEOF +for ac_lib in '' malloc; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_mallinfo=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_mallinfo+set}" = set; then + break +fi +done +if test "${ac_cv_search_mallinfo+set}" = set; then + : +else + ac_cv_search_mallinfo=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_mallinfo" >&5 +echo "${ECHO_T}$ac_cv_search_mallinfo" >&6; } +ac_res=$ac_cv_search_mallinfo +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MALLINFO 1 +_ACEOF + +fi + + +if test "$LLVM_ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + +{ echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6; } +if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_pthread_pthread_mutex_init=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6; } +if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_mutex_lock" >&5 +echo $ECHO_N "checking for library containing pthread_mutex_lock... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_lock (); +int +main () +{ +return pthread_mutex_lock (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_mutex_lock=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + : +else + ac_cv_search_pthread_mutex_lock=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_mutex_lock" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_mutex_lock" >&6; } +ac_res=$ac_cv_search_pthread_mutex_lock +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_MUTEX_LOCK 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_rwlock_init" >&5 +echo $ECHO_N "checking for library containing pthread_rwlock_init... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_rwlock_init (); +int +main () +{ +return pthread_rwlock_init (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_rwlock_init=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + : +else + ac_cv_search_pthread_rwlock_init=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_rwlock_init" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_rwlock_init" >&6; } +ac_res=$ac_cv_search_pthread_rwlock_init +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_RWLOCK_INIT 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_getspecific" >&5 +echo $ECHO_N "checking for library containing pthread_getspecific... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_getspecific+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_getspecific (); +int +main () +{ +return pthread_getspecific (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_getspecific=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_getspecific+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_getspecific+set}" = set; then + : +else + ac_cv_search_pthread_getspecific=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_getspecific" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_getspecific" >&6; } +ac_res=$ac_cv_search_pthread_getspecific +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_GETSPECIFIC 1 +_ACEOF + +fi + +fi + +if test "$LLVM_ENABLE_ZLIB" -eq 1 ; then + +{ echo "$as_me:$LINENO: checking for compress2 in -lz" >&5 +echo $ECHO_N "checking for compress2 in -lz... $ECHO_C" >&6; } +if test "${ac_cv_lib_z_compress2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char compress2 (); +int +main () +{ +return compress2 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_compress2=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_z_compress2=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_compress2" >&5 +echo "${ECHO_T}$ac_cv_lib_z_compress2" >&6; } +if test $ac_cv_lib_z_compress2 = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +fi + +fi + + +# Check whether --with-udis86 was given. +if test "${with_udis86+set}" = set; then + withval=$with_udis86; + USE_UDIS86=1 + + case "$withval" in + /usr/lib|yes) ;; + *) LDFLAGS="$LDFLAGS -L${withval}" ;; + esac + +{ echo "$as_me:$LINENO: checking for ud_init in -ludis86" >&5 +echo $ECHO_N "checking for ud_init in -ludis86... $ECHO_C" >&6; } +if test "${ac_cv_lib_udis86_ud_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ludis86 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ud_init (); +int +main () +{ +return ud_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_udis86_ud_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_udis86_ud_init=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_udis86_ud_init" >&5 +echo "${ECHO_T}$ac_cv_lib_udis86_ud_init" >&6; } +if test $ac_cv_lib_udis86_ud_init = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUDIS86 1 +_ACEOF + + LIBS="-ludis86 $LIBS" + +else + + echo "Error! You need to have libudis86 around." + exit -1 + +fi + + +else + USE_UDIS86=0 + +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_UDIS86 $USE_UDIS86 +_ACEOF + + + +# Check whether --with-oprofile was given. +if test "${with_oprofile+set}" = set; then + withval=$with_oprofile; + USE_OPROFILE=1 + + case "$withval" in + /usr|yes) llvm_cv_oppath=/usr/lib/oprofile ;; + no) llvm_cv_oppath= + USE_OPROFILE=0 + ;; + *) llvm_cv_oppath="${withval}/lib/oprofile" + CPPFLAGS="-I${withval}/include";; + esac + case $llvm_cv_os_type in + Linux) + if test -n "$llvm_cv_oppath" ; then + LIBS="$LIBS -lopagent -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}" + { echo "$as_me:$LINENO: checking for library containing bfd_init" >&5 +echo $ECHO_N "checking for library containing bfd_init... $ECHO_C" >&6; } +if test "${ac_cv_search_bfd_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_init (); +int +main () +{ +return bfd_init (); + ; + return 0; +} +_ACEOF +for ac_lib in '' bfd; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_bfd_init=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_bfd_init+set}" = set; then + break +fi +done +if test "${ac_cv_search_bfd_init+set}" = set; then + : +else + ac_cv_search_bfd_init=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_bfd_init" >&5 +echo "${ECHO_T}$ac_cv_search_bfd_init" >&6; } +ac_res=$ac_cv_search_bfd_init +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for library containing op_open_agent" >&5 +echo $ECHO_N "checking for library containing op_open_agent... $ECHO_C" >&6; } +if test "${ac_cv_search_op_open_agent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char op_open_agent (); +int +main () +{ +return op_open_agent (); + ; + return 0; +} +_ACEOF +for ac_lib in '' opagent; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_op_open_agent=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_op_open_agent+set}" = set; then + break +fi +done +if test "${ac_cv_search_op_open_agent+set}" = set; then + : +else + ac_cv_search_op_open_agent=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_op_open_agent" >&5 +echo "${ECHO_T}$ac_cv_search_op_open_agent" >&6; } +ac_res=$ac_cv_search_op_open_agent +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + + echo "Error! You need to have libopagent around." + exit -1 + +fi + + if test "${ac_cv_header_opagent_h+set}" = set; then + { echo "$as_me:$LINENO: checking for opagent.h" >&5 +echo $ECHO_N "checking for opagent.h... $ECHO_C" >&6; } +if test "${ac_cv_header_opagent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_opagent_h" >&5 +echo "${ECHO_T}$ac_cv_header_opagent_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking opagent.h usability" >&5 +echo $ECHO_N "checking opagent.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking opagent.h presence" >&5 +echo $ECHO_N "checking opagent.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: opagent.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: opagent.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: opagent.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: opagent.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: opagent.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: opagent.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: opagent.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: opagent.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: opagent.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: opagent.h: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for opagent.h" >&5 +echo $ECHO_N "checking for opagent.h... $ECHO_C" >&6; } +if test "${ac_cv_header_opagent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_opagent_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_opagent_h" >&5 +echo "${ECHO_T}$ac_cv_header_opagent_h" >&6; } + +fi +if test $ac_cv_header_opagent_h = yes; then + : +else + + echo "Error! You need to have opagent.h around." + exit -1 + +fi + + + fi ;; + *) + { { echo "$as_me:$LINENO: error: OProfile support is available on Linux only." >&5 +echo "$as_me: error: OProfile support is available on Linux only." >&2;} + { (exit 1); exit 1; }; } ;; + esac + +else + + USE_OPROFILE=0 + + +fi + + +cat >>confdefs.h <<_ACEOF +#define LLVM_USE_OPROFILE $USE_OPROFILE +_ACEOF + + + +# Check whether --with-intel-jitevents was given. +if test "${with_intel_jitevents+set}" = set; then + withval=$with_intel_jitevents; + case "$withval" in + yes) USE_INTEL_JITEVENTS=1 +;; + no) USE_INTEL_JITEVENTS=0 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --with-intel-jitevents. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --with-intel-jitevents. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; };; + esac + + case $llvm_cv_os_type in + Linux|Win32|Cygwin|MingW) ;; + *) { { echo "$as_me:$LINENO: error: Intel JIT API support is available on Linux and Windows only." >&5 +echo "$as_me: error: Intel JIT API support is available on Linux and Windows only." >&2;} + { (exit 1); exit 1; }; };; + esac + + case "$llvm_cv_target_arch" in + x86|x86_64) ;; + *) { { echo "$as_me:$LINENO: error: Target architecture $llvm_cv_target_arch does not support Intel JIT Events API." >&5 +echo "$as_me: error: Target architecture $llvm_cv_target_arch does not support Intel JIT Events API." >&2;} + { (exit 1); exit 1; }; };; + esac + +else + + USE_INTEL_JITEVENTS=0 + + +fi + + +cat >>confdefs.h <<_ACEOF +#define LLVM_USE_INTEL_JITEVENTS $USE_INTEL_JITEVENTS +_ACEOF + + +for ac_prog in xml2-config +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_XML2CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$XML2CONFIG"; then + ac_cv_prog_XML2CONFIG="$XML2CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_XML2CONFIG="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +XML2CONFIG=$ac_cv_prog_XML2CONFIG +if test -n "$XML2CONFIG"; then + { echo "$as_me:$LINENO: result: $XML2CONFIG" >&5 +echo "${ECHO_T}$XML2CONFIG" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$XML2CONFIG" && break +done + + +{ echo "$as_me:$LINENO: checking for libxml2 includes" >&5 +echo $ECHO_N "checking for libxml2 includes... $ECHO_C" >&6; } +if test "x$XML2CONFIG" = "x"; then + { echo "$as_me:$LINENO: result: xml2-config not found" >&5 +echo "${ECHO_T}xml2-config not found" >&6; } +else + LIBXML2_INC=`$XML2CONFIG --cflags` + { echo "$as_me:$LINENO: result: $LIBXML2_INC" >&5 +echo "${ECHO_T}$LIBXML2_INC" >&6; } + { echo "$as_me:$LINENO: checking for xmlReadFile in -lxml2" >&5 +echo $ECHO_N "checking for xmlReadFile in -lxml2... $ECHO_C" >&6; } +if test "${ac_cv_lib_xml2_xmlReadFile+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxml2 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xmlReadFile (); +int +main () +{ +return xmlReadFile (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_xml2_xmlReadFile=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_xml2_xmlReadFile=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_xml2_xmlReadFile" >&5 +echo "${ECHO_T}$ac_cv_lib_xml2_xmlReadFile" >&6; } +if test $ac_cv_lib_xml2_xmlReadFile = yes; then + +cat >>confdefs.h <<\_ACEOF +#define CLANG_HAVE_LIBXML 1 +_ACEOF + + LIBXML2_LIBS="-lxml2" +fi + +fi + + + + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ echo "$as_me:$LINENO: checking for MAP_ANONYMOUS vs. MAP_ANON" >&5 +echo $ECHO_N "checking for MAP_ANONYMOUS vs. MAP_ANON... $ECHO_C" >&6; } +if test "${ac_cv_header_mmap_anon+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +int +main () +{ +mmap (0, 1, PROT_READ, MAP_ANONYMOUS, -1, 0); return (0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_mmap_anon=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_mmap_anon=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_mmap_anon" >&5 +echo "${ECHO_T}$ac_cv_header_mmap_anon" >&6; } +if test "$ac_cv_header_mmap_anon" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP_ANONYMOUS 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether stat file-mode macros are broken" >&5 +echo $ECHO_N "checking whether stat file-mode macros are broken... $ECHO_C" >&6; } +if test "${ac_cv_header_stat_broken+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +#if defined S_ISBLK && defined S_IFDIR +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined S_ISBLK && defined S_IFCHR +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined S_ISLNK && defined S_IFREG +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined S_ISSOCK && defined S_IFREG +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "You lose" >/dev/null 2>&1; then + ac_cv_header_stat_broken=yes +else + ac_cv_header_stat_broken=no +fi +rm -f conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stat_broken" >&5 +echo "${ECHO_T}$ac_cv_header_stat_broken" >&6; } +if test $ac_cv_header_stat_broken = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STAT_MACROS_BROKEN 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; } +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_sys_wait_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_sys_wait_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_WAIT_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; } +if test "${ac_cv_header_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_time=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +echo "${ECHO_T}$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +for ac_header in cxxabi.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + +for ac_header in dlfcn.h execinfo.h fcntl.h inttypes.h link.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + +for ac_header in malloc.h setjmp.h signal.h stdint.h termios.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in utime.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + +for ac_header in sys/mman.h sys/param.h sys/resource.h sys/time.h sys/uio.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +for ac_header in sys/ioctl.h malloc/malloc.h mach/mach.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in valgrind/valgrind.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in fenv.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ echo "$as_me:$LINENO: checking whether FE_ALL_EXCEPT is declared" >&5 +echo $ECHO_N "checking whether FE_ALL_EXCEPT is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_FE_ALL_EXCEPT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef FE_ALL_EXCEPT + char *p = (char *) FE_ALL_EXCEPT; + return !p; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_FE_ALL_EXCEPT=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_decl_FE_ALL_EXCEPT=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_FE_ALL_EXCEPT" >&5 +echo "${ECHO_T}$ac_cv_have_decl_FE_ALL_EXCEPT" >&6; } +if test $ac_cv_have_decl_FE_ALL_EXCEPT = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FE_ALL_EXCEPT 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FE_ALL_EXCEPT 0 +_ACEOF + + +fi +{ echo "$as_me:$LINENO: checking whether FE_INEXACT is declared" >&5 +echo $ECHO_N "checking whether FE_INEXACT is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_FE_INEXACT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef FE_INEXACT + char *p = (char *) FE_INEXACT; + return !p; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_FE_INEXACT=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_decl_FE_INEXACT=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_FE_INEXACT" >&5 +echo "${ECHO_T}$ac_cv_have_decl_FE_INEXACT" >&6; } +if test $ac_cv_have_decl_FE_INEXACT = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FE_INEXACT 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FE_INEXACT 0 +_ACEOF + + +fi + + +if test "$LLVM_ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + +for ac_header in pthread.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + HAVE_PTHREAD=1 + +else + HAVE_PTHREAD=0 + +fi + +done + +else + HAVE_PTHREAD=0 + +fi +if test "$LLVM_ENABLE_ZLIB" -eq 1 ; then + +for ac_header in zlib.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + HAVE_LIBZ=1 + +else + HAVE_LIBZ=0 + +fi + +done + +else + HAVE_LIBZ=0 + +fi + +if test "$llvm_cv_enable_libffi" = "yes" ; then + + +for ac_header in ffi.h ffi/ffi.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +fi + + +for ac_header in CrashReporterClient.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking __crashreporter_info__" >&5 +echo $ECHO_N "checking __crashreporter_info__... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + extern const char *__crashreporter_info__; + int main() { + __crashreporter_info__ = "test"; + return 0; + } + + +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CRASHREPORTER_INFO 1 +_ACEOF + + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CRASHREPORTER_INFO 0 +_ACEOF + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + + + { echo "$as_me:$LINENO: checking for HUGE_VAL sanity" >&5 +echo $ECHO_N "checking for HUGE_VAL sanity... $ECHO_C" >&6; } +if test "${ac_cv_huge_val_sanity+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + ac_save_CXXFLAGS=$CXXFLAGS + CXXFLAGS="$CXXFLAGS -pedantic" + if test "$cross_compiling" = yes; then + ac_cv_huge_val_sanity=yes +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +double x = HUGE_VAL; return x != x; + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_huge_val_sanity=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_huge_val_sanity=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + CXXFLAGS=$ac_save_CXXFLAGS + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_huge_val_sanity" >&5 +echo "${ECHO_T}$ac_cv_huge_val_sanity" >&6; } + HUGE_VAL_SANITY=$ac_cv_huge_val_sanity + + +{ echo "$as_me:$LINENO: checking for pid_t" >&5 +echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; } +if test "${ac_cv_type_pid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef pid_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_pid_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_pid_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +echo "${ECHO_T}$ac_cv_type_pid_t" >&6; } +if test $ac_cv_type_pid_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6; } +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef size_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_size_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6; } +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE void +_ACEOF + +{ echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 +echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; } +if test "${ac_cv_struct_tm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm *tp; tp->tm_sec; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_struct_tm=time.h +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_struct_tm=sys/time.h +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 +echo "${ECHO_T}$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +cat >>confdefs.h <<\_ACEOF +#define TM_IN_SYS_TIME 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for int64_t" >&5 +echo $ECHO_N "checking for int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_int64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_int64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_int64_t" >&6; } +if test $ac_cv_type_int64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INT64_T 1 +_ACEOF + + +else + { { echo "$as_me:$LINENO: error: Type int64_t required but not found" >&5 +echo "$as_me: error: Type int64_t required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: checking for uint64_t" >&5 +echo $ECHO_N "checking for uint64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_uint64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef uint64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_uint64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_uint64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_uint64_t" >&5 +echo "${ECHO_T}$ac_cv_type_uint64_t" >&6; } +if test $ac_cv_type_uint64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT64_T 1 +_ACEOF + + +else + { echo "$as_me:$LINENO: checking for u_int64_t" >&5 +echo $ECHO_N "checking for u_int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_u_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef u_int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_u_int64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_u_int64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_u_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_int64_t" >&6; } +if test $ac_cv_type_u_int64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_U_INT64_T 1 +_ACEOF + + +else + { { echo "$as_me:$LINENO: error: Type uint64_t or u_int64_t required but not found" >&5 +echo "$as_me: error: Type uint64_t or u_int64_t required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +fi + + + + + + + + + + +for ac_func in backtrace ceilf floorf roundf rintf nearbyintf getcwd +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in powf fmodf strtof round +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + +for ac_func in log log2 log10 exp exp2 +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + +for ac_func in getpagesize getrusage getrlimit setrlimit gettimeofday +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in isatty mkdtemp mkstemp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + +for ac_func in mktemp posix_spawn pread realpath sbrk setrlimit +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in strerror strerror_r setenv arc4random +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in strtoll strtoq sysconf malloc_zone_statistics +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + +for ac_func in setjmp longjmp sigsetjmp siglongjmp writev +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +for ac_func in futimes futimens +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ echo "$as_me:$LINENO: checking if printf has the %a format character" >&5 +echo $ECHO_N "checking if printf has the %a format character... $ECHO_C" >&6; } +if test "${llvm_cv_c_printf_a+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test "$cross_compiling" = yes; then + llvmac_cv_c_printf_a=no +else + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + +volatile double A, B; +char Buffer[100]; +A = 1; +A /= 10.0; +sprintf(Buffer, "%a", A); +B = atof(Buffer); +if (A != B) + return (1); +if (A != 0x1.999999999999ap-4) + return (1); +return (0); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_c_printf_a=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +llvmac_cv_c_printf_a=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_c_printf_a" >&5 +echo "${ECHO_T}$llvm_cv_c_printf_a" >&6; } + if test "$llvm_cv_c_printf_a" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PRINTF_A 1 +_ACEOF + + fi + + + + { echo "$as_me:$LINENO: checking for srand48/lrand48/drand48 in " >&5 +echo $ECHO_N "checking for srand48/lrand48/drand48 in ... $ECHO_C" >&6; } +if test "${ac_cv_func_rand48+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +srand48(0);lrand48();drand48(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_rand48=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_rand48=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_rand48" >&5 +echo "${ECHO_T}$ac_cv_func_rand48" >&6; } + +if test "$ac_cv_func_rand48" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_RAND48 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking whether strerror_s is declared" >&5 +echo $ECHO_N "checking whether strerror_s is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_strerror_s+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +#ifndef strerror_s + char *p = (char *) strerror_s; + return !p; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_strerror_s=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_decl_strerror_s=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_strerror_s" >&5 +echo "${ECHO_T}$ac_cv_have_decl_strerror_s" >&6; } +if test $ac_cv_have_decl_strerror_s = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRERROR_S 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRERROR_S 0 +_ACEOF + + +fi + + + +if test "$llvm_cv_os_type" = "MingW" ; then + { echo "$as_me:$LINENO: checking for _alloca in -lgcc" >&5 +echo $ECHO_N "checking for _alloca in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc__alloca+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _alloca (); +int +main () +{ +return _alloca (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc__alloca=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc__alloca=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc__alloca" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc__alloca" >&6; } +if test $ac_cv_lib_gcc__alloca = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE__ALLOCA 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __alloca in -lgcc" >&5 +echo $ECHO_N "checking for __alloca in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___alloca+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __alloca (); +int +main () +{ +return __alloca (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___alloca=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___alloca=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___alloca" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___alloca" >&6; } +if test $ac_cv_lib_gcc___alloca = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___ALLOCA 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __chkstk in -lgcc" >&5 +echo $ECHO_N "checking for __chkstk in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___chkstk+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __chkstk (); +int +main () +{ +return __chkstk (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___chkstk=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___chkstk=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___chkstk" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___chkstk" >&6; } +if test $ac_cv_lib_gcc___chkstk = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___CHKSTK 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for ___chkstk in -lgcc" >&5 +echo $ECHO_N "checking for ___chkstk in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc____chkstk+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ___chkstk (); +int +main () +{ +return ___chkstk (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc____chkstk=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc____chkstk=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc____chkstk" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc____chkstk" >&6; } +if test $ac_cv_lib_gcc____chkstk = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE____CHKSTK 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for __ashldi3 in -lgcc" >&5 +echo $ECHO_N "checking for __ashldi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___ashldi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __ashldi3 (); +int +main () +{ +return __ashldi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___ashldi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___ashldi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___ashldi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___ashldi3" >&6; } +if test $ac_cv_lib_gcc___ashldi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___ASHLDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __ashrdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __ashrdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___ashrdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __ashrdi3 (); +int +main () +{ +return __ashrdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___ashrdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___ashrdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___ashrdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___ashrdi3" >&6; } +if test $ac_cv_lib_gcc___ashrdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___ASHRDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __divdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __divdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___divdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __divdi3 (); +int +main () +{ +return __divdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___divdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___divdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___divdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___divdi3" >&6; } +if test $ac_cv_lib_gcc___divdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___DIVDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __fixdfdi in -lgcc" >&5 +echo $ECHO_N "checking for __fixdfdi in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___fixdfdi+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __fixdfdi (); +int +main () +{ +return __fixdfdi (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___fixdfdi=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___fixdfdi=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___fixdfdi" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___fixdfdi" >&6; } +if test $ac_cv_lib_gcc___fixdfdi = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___FIXDFDI 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __fixsfdi in -lgcc" >&5 +echo $ECHO_N "checking for __fixsfdi in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___fixsfdi+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __fixsfdi (); +int +main () +{ +return __fixsfdi (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___fixsfdi=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___fixsfdi=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___fixsfdi" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___fixsfdi" >&6; } +if test $ac_cv_lib_gcc___fixsfdi = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___FIXSFDI 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __floatdidf in -lgcc" >&5 +echo $ECHO_N "checking for __floatdidf in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___floatdidf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __floatdidf (); +int +main () +{ +return __floatdidf (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___floatdidf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___floatdidf=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___floatdidf" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___floatdidf" >&6; } +if test $ac_cv_lib_gcc___floatdidf = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___FLOATDIDF 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __lshrdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __lshrdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___lshrdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __lshrdi3 (); +int +main () +{ +return __lshrdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___lshrdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___lshrdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___lshrdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___lshrdi3" >&6; } +if test $ac_cv_lib_gcc___lshrdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___LSHRDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __moddi3 in -lgcc" >&5 +echo $ECHO_N "checking for __moddi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___moddi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __moddi3 (); +int +main () +{ +return __moddi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___moddi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___moddi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___moddi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___moddi3" >&6; } +if test $ac_cv_lib_gcc___moddi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___MODDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __udivdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __udivdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___udivdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __udivdi3 (); +int +main () +{ +return __udivdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___udivdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___udivdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___udivdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___udivdi3" >&6; } +if test $ac_cv_lib_gcc___udivdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___UDIVDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __umoddi3 in -lgcc" >&5 +echo $ECHO_N "checking for __umoddi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___umoddi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __umoddi3 (); +int +main () +{ +return __umoddi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___umoddi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___umoddi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___umoddi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___umoddi3" >&6; } +if test $ac_cv_lib_gcc___umoddi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___UMODDI3 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for __main in -lgcc" >&5 +echo $ECHO_N "checking for __main in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __main (); +int +main () +{ +return __main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___main" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___main" >&6; } +if test $ac_cv_lib_gcc___main = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___MAIN 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __cmpdi2 in -lgcc" >&5 +echo $ECHO_N "checking for __cmpdi2 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___cmpdi2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __cmpdi2 (); +int +main () +{ +return __cmpdi2 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___cmpdi2=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___cmpdi2=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___cmpdi2" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___cmpdi2" >&6; } +if test $ac_cv_lib_gcc___cmpdi2 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___CMPDI2 1 +_ACEOF + +fi + +fi + +if test "$llvm_cv_os_type" = "MingW" ; then + { echo "$as_me:$LINENO: checking whether EnumerateLoadedModules() accepts new decl" >&5 +echo $ECHO_N "checking whether EnumerateLoadedModules() accepts new decl... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + #include + extern void foo(PENUMLOADED_MODULES_CALLBACK); + extern void foo(BOOL(CALLBACK*)(PCSTR,ULONG_PTR,ULONG,PVOID)); + + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + llvm_cv_win32_elmcb_pcstr="PCSTR" + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + llvm_cv_win32_elmcb_pcstr="PSTR" + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +cat >>confdefs.h <<_ACEOF +#define WIN32_ELMCB_PCSTR $llvm_cv_win32_elmcb_pcstr +_ACEOF + +fi + + + + { echo "$as_me:$LINENO: checking for isnan in " >&5 +echo $ECHO_N "checking for isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isnan_in_math_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isnan_in_math_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isnan_in_math_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isnan_in_math_h" >&5 +echo "${ECHO_T}$ac_cv_func_isnan_in_math_h" >&6; } + + +if test "$ac_cv_func_isnan_in_math_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISNAN_IN_MATH_H 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for isnan in " >&5 +echo $ECHO_N "checking for isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isnan_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isnan_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isnan_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isnan_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_isnan_in_cmath" >&6; } + +if test "$ac_cv_func_isnan_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISNAN_IN_CMATH 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for std::isnan in " >&5 +echo $ECHO_N "checking for std::isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_std_isnan_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; std::isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_std_isnan_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_std_isnan_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_std_isnan_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_std_isnan_in_cmath" >&6; } + +if test "$ac_cv_func_std_isnan_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ISNAN_IN_CMATH 1 +_ACEOF + +fi + + + + + { echo "$as_me:$LINENO: checking for isinf in " >&5 +echo $ECHO_N "checking for isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isinf_in_math_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isinf(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isinf_in_math_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isinf_in_math_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isinf_in_math_h" >&5 +echo "${ECHO_T}$ac_cv_func_isinf_in_math_h" >&6; } + +if test "$ac_cv_func_isinf_in_math_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISINF_IN_MATH_H 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for isinf in " >&5 +echo $ECHO_N "checking for isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isinf_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isinf(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isinf_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isinf_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isinf_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_isinf_in_cmath" >&6; } + +if test "$ac_cv_func_isinf_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISINF_IN_CMATH 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for std::isinf in " >&5 +echo $ECHO_N "checking for std::isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_std_isinf_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; std::isinf(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_std_isinf_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_std_isinf_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_std_isinf_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_std_isinf_in_cmath" >&6; } + +if test "$ac_cv_func_std_isinf_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ISINF_IN_CMATH 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for finite in " >&5 +echo $ECHO_N "checking for finite in ... $ECHO_C" >&6; } +if test "${ac_cv_func_finite_in_ieeefp_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; finite(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_finite_in_ieeefp_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_finite_in_ieeefp_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_finite_in_ieeefp_h" >&5 +echo "${ECHO_T}$ac_cv_func_finite_in_ieeefp_h" >&6; } + +if test "$ac_cv_func_finite_in_ieeefp_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FINITE_IN_IEEEFP_H 1 +_ACEOF + +fi + + + +if test "$llvm_cv_platform_type" = "Unix" ; then + + +for ac_header in stdlib.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in getpagesize +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ echo "$as_me:$LINENO: checking for working mmap" >&5 +echo $ECHO_N "checking for working mmap... $ECHO_C" >&6; } +if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include +#include + +#if !STDC_HEADERS && !HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#if !HAVE_GETPAGESIZE +/* Assume that all systems that can run configure have sys/param.h. */ +# if !HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# if HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 1; + if (write (fd, data, pagesize) != pagesize) + return 1; + close (fd); + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 1; + data2 = (char *) malloc (2 * pagesize); + if (!data2) + return 1; + data2 += (pagesize - ((long int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 1; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 1; + if (read (fd, data3, pagesize) != pagesize) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 1; + close (fd); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_fixed_mapped=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP 1 +_ACEOF + +fi +rm -f conftest.mmap + + { echo "$as_me:$LINENO: checking for mmap of files" >&5 +echo $ECHO_N "checking for mmap of files... $ECHO_C" >&6; } +if test "${ac_cv_func_mmap_file+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_file=no +else + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + + int fd; + fd = creat ("foo",0777); + fd = (int) mmap (0, 1, PROT_READ, MAP_SHARED, fd, 0); + unlink ("foo"); + return (fd != (int) MAP_FAILED); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_file=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_file=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_file" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_file" >&6; } +if test "$ac_cv_func_mmap_file" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP_FILE +_ACEOF + + MMAP_FILE=yes + +fi + + { echo "$as_me:$LINENO: checking if /dev/zero is needed for mmap" >&5 +echo $ECHO_N "checking if /dev/zero is needed for mmap... $ECHO_C" >&6; } +if test "${ac_cv_need_dev_zero_for_mmap+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$llvm_cv_os_type" = "Interix" ; then + ac_cv_need_dev_zero_for_mmap=yes + else + ac_cv_need_dev_zero_for_mmap=no + fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_need_dev_zero_for_mmap" >&5 +echo "${ECHO_T}$ac_cv_need_dev_zero_for_mmap" >&6; } +if test "$ac_cv_need_dev_zero_for_mmap" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define NEED_DEV_ZERO_FOR_MMAP 1 +_ACEOF + +fi + + if test "$ac_cv_func_mmap_fixed_mapped" = "no" + then + { echo "$as_me:$LINENO: WARNING: mmap() of a fixed address required but not supported" >&5 +echo "$as_me: WARNING: mmap() of a fixed address required but not supported" >&2;} + fi + if test "$ac_cv_func_mmap_file" = "no" + then + { echo "$as_me:$LINENO: WARNING: mmap() of files required but not found" >&5 +echo "$as_me: WARNING: mmap() of files required but not found" >&2;} + fi +fi + +{ echo "$as_me:$LINENO: checking for GCC atomic builtins" >&5 +echo $ECHO_N "checking for GCC atomic builtins... $ECHO_C" >&6; } +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } + + +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define LLVM_HAS_ATOMICS 1 +_ACEOF + + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define LLVM_HAS_ATOMICS 0 +_ACEOF + + { echo "$as_me:$LINENO: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&5 +echo "$as_me: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&2;} + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then + { echo "$as_me:$LINENO: checking for 32-bit userspace on 64-bit system" >&5 +echo $ECHO_N "checking for 32-bit userspace on 64-bit system... $ECHO_C" >&6; } +if test "${llvm_cv_linux_mixed+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef __x86_64__ + error: Not x86-64 even if uname says so! + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_linux_mixed=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_linux_mixed=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_linux_mixed" >&5 +echo "${ECHO_T}$llvm_cv_linux_mixed" >&6; } + + if test "$llvm_cv_linux_mixed" = "yes"; then + llvm_cv_target_arch="x86" + ARCH="x86" + fi +fi + + +for ac_func in __dso_handle +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +SHLIBEXT=$libltdl_cv_shlibext + + +SHLIBPATH_VAR=$libltdl_cv_shlibpath_var + + +if test "${prefix}" = "NONE" ; then + prefix="/usr/local" +fi +eval LLVM_PREFIX="${prefix}"; +eval LLVM_BINDIR="${prefix}/bin"; +eval LLVM_DATADIR="${prefix}/share/llvm"; +eval LLVM_DOCSDIR="${prefix}/share/doc/llvm"; +eval LLVM_ETCDIR="${prefix}/etc/llvm"; +eval LLVM_INCLUDEDIR="${prefix}/include"; +eval LLVM_INFODIR="${prefix}/info"; +eval LLVM_MANDIR="${prefix}/man"; +LLVM_CONFIGTIME=`date` + + + + + + + + + + +if test "${ENABLE_TIMESTAMPS}" = "0"; then + LLVM_CONFIGTIME="(timestamp not enabled)" +fi + + +cat >>confdefs.h <<_ACEOF +#define LLVM_PREFIX "$LLVM_PREFIX" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_BINDIR "$LLVM_BINDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_DATADIR "$LLVM_DATADIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_DOCSDIR "$LLVM_DOCSDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_ETCDIR "$LLVM_ETCDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_INCLUDEDIR "$LLVM_INCLUDEDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_INFODIR "$LLVM_INFODIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_MANDIR "$LLVM_MANDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_CONFIGTIME "$LLVM_CONFIGTIME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_HOST_TRIPLE "$host" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_DEFAULT_TARGET_TRIPLE "$target" +_ACEOF + + +if test "$BINDINGS_TO_BUILD" = auto ; then + BINDINGS_TO_BUILD="" + if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" + fi +fi +BINDINGS_TO_BUILD=$BINDINGS_TO_BUILD + + +ALL_BINDINGS=ocaml + + +binding_prereqs_failed=0 +for a_binding in $BINDINGS_TO_BUILD ; do + case "$a_binding" in + ocaml) + if test "x$OCAMLC" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&2;} + binding_prereqs_failed=1 + fi + if test "x$OCAMLDEP" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&2;} + binding_prereqs_failed=1 + fi + if test "x$OCAMLOPT" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&2;} + fi + if test "x$with_ocaml_libdir" != xauto ; then + OCAML_LIBDIR=$with_ocaml_libdir + + else + ocaml_stdlib="`"$OCAMLC" -where`" + if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" + then + # ocaml stdlib is beneath our prefix; use stdlib + OCAML_LIBDIR=$ocaml_stdlib + + else + # ocaml stdlib is outside our prefix; use libdir/ocaml + OCAML_LIBDIR=${prefix}/lib/ocaml + + fi + fi + ;; + esac +done +if test "$binding_prereqs_failed" = 1 ; then + { { echo "$as_me:$LINENO: error: Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings." >&5 +echo "$as_me: error: Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings." >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: checking for compiler -fvisibility-inlines-hidden option" >&5 +echo $ECHO_N "checking for compiler -fvisibility-inlines-hidden option... $ECHO_C" >&6; } +if test "${llvm_cv_cxx_visibility_inlines_hidden+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + oldcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -O0 -fvisibility-inlines-hidden -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +template struct X { void __attribute__((noinline)) f() {} }; +int +main () +{ +X().f(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_cxx_visibility_inlines_hidden=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_cxx_visibility_inlines_hidden=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXXFLAGS="$oldcxxflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_cxx_visibility_inlines_hidden" >&5 +echo "${ECHO_T}$llvm_cv_cxx_visibility_inlines_hidden" >&6; } +if test "$llvm_cv_cxx_visibility_inlines_hidden" = yes ; then + ENABLE_VISIBILITY_INLINES_HIDDEN=1 + +else + ENABLE_VISIBILITY_INLINES_HIDDEN=0 + +fi + + +if test "$llvm_cv_link_use_r" = "yes" ; then + RPATH="-Wl,-R" +else + RPATH="-Wl,-rpath" +fi + + +if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then + RDYNAMIC="-rdynamic" +else + RDYNAMIC="" +fi + + + +ac_config_headers="$ac_config_headers include/llvm/Config/config.h include/llvm/Config/llvm-config.h" + + + + + + +ac_config_files="$ac_config_files include/llvm/Config/Targets.def" + +ac_config_files="$ac_config_files include/llvm/Config/AsmPrinters.def" + +ac_config_files="$ac_config_files include/llvm/Config/AsmParsers.def" + +ac_config_files="$ac_config_files include/llvm/Config/Disassemblers.def" + +ac_config_headers="$ac_config_headers include/llvm/Support/DataTypes.h" + + +ac_config_files="$ac_config_files Makefile.config" + + +ac_config_files="$ac_config_files llvm.spec" + + +ac_config_files="$ac_config_files docs/doxygen.cfg" + + +if test "${clang_src_root}" = ""; then + clang_src_root="$srcdir/tools/clang" +fi +if test -f ${clang_src_root}/README.txt; then + configh="include/clang/Config/config.h" + doxy="docs/doxygen.cfg" + ac_config_headers="$ac_config_headers tools/clang/${configh}:${clang_src_root}/${configh}.in" + + ac_config_files="$ac_config_files tools/clang/${doxy}:${clang_src_root}/${doxy}.in" + +fi + +ac_config_files="$ac_config_files bindings/ocaml/llvm/META.llvm" + + +test "x$program_prefix" = "xNONE" && program_prefix="" + + + +ac_config_commands="$ac_config_commands setup" + +ac_config_commands="$ac_config_commands Makefile" + + +ac_config_commands="$ac_config_commands Makefile.common" + + +ac_config_commands="$ac_config_commands examples/Makefile" + + +ac_config_commands="$ac_config_commands lib/Makefile" + + +ac_config_commands="$ac_config_commands test/Makefile" + + +ac_config_commands="$ac_config_commands test/Makefile.tests" + + +ac_config_commands="$ac_config_commands unittests/Makefile" + + +ac_config_commands="$ac_config_commands tools/Makefile" + + +ac_config_commands="$ac_config_commands utils/Makefile" + + +ac_config_commands="$ac_config_commands projects/Makefile" + + +ac_config_commands="$ac_config_commands bindings/Makefile" + + +ac_config_commands="$ac_config_commands bindings/ocaml/Makefile.ocaml" + + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by LLVM $as_me 3.4.1, which was +generated by GNU Autoconf 2.60. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +LLVM config.status 3.4.1 +configured by $0, generated by GNU Autoconf 2.60, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS +# +llvm_src="${srcdir}" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "include/llvm/Config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/config.h" ;; + "include/llvm/Config/llvm-config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/llvm-config.h" ;; + "include/llvm/Config/Targets.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Targets.def" ;; + "include/llvm/Config/AsmPrinters.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmPrinters.def" ;; + "include/llvm/Config/AsmParsers.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmParsers.def" ;; + "include/llvm/Config/Disassemblers.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Disassemblers.def" ;; + "include/llvm/Support/DataTypes.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Support/DataTypes.h" ;; + "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;; + "llvm.spec") CONFIG_FILES="$CONFIG_FILES llvm.spec" ;; + "docs/doxygen.cfg") CONFIG_FILES="$CONFIG_FILES docs/doxygen.cfg" ;; + "tools/clang/${configh}") CONFIG_HEADERS="$CONFIG_HEADERS tools/clang/${configh}:${clang_src_root}/${configh}.in" ;; + "tools/clang/${doxy}") CONFIG_FILES="$CONFIG_FILES tools/clang/${doxy}:${clang_src_root}/${doxy}.in" ;; + "bindings/ocaml/llvm/META.llvm") CONFIG_FILES="$CONFIG_FILES bindings/ocaml/llvm/META.llvm" ;; + "setup") CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;; + "Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile" ;; + "Makefile.common") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile.common" ;; + "examples/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS examples/Makefile" ;; + "lib/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS lib/Makefile" ;; + "test/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS test/Makefile" ;; + "test/Makefile.tests") CONFIG_COMMANDS="$CONFIG_COMMANDS test/Makefile.tests" ;; + "unittests/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS unittests/Makefile" ;; + "tools/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS tools/Makefile" ;; + "utils/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS utils/Makefile" ;; + "projects/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS projects/Makefile" ;; + "bindings/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS bindings/Makefile" ;; + "bindings/ocaml/Makefile.ocaml") CONFIG_COMMANDS="$CONFIG_COMMANDS bindings/ocaml/Makefile.ocaml" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +LLVM_VERSION_MAJOR!$LLVM_VERSION_MAJOR$ac_delim +LLVM_VERSION_MINOR!$LLVM_VERSION_MINOR$ac_delim +LLVM_VERSION_PATCH!$LLVM_VERSION_PATCH$ac_delim +LLVM_VERSION_SUFFIX!$LLVM_VERSION_SUFFIX$ac_delim +LLVM_COPYRIGHT!$LLVM_COPYRIGHT$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +CPP!$CPP$ac_delim +subdirs!$subdirs$ac_delim +ENABLE_POLLY!$ENABLE_POLLY$ac_delim +LLVM_HAS_POLLY!$LLVM_HAS_POLLY$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +target!$target$ac_delim +target_cpu!$target_cpu$ac_delim +target_vendor!$target_vendor$ac_delim +target_os!$target_os$ac_delim +OS!$OS$ac_delim +HOST_OS!$HOST_OS$ac_delim +TARGET_OS!$TARGET_OS$ac_delim +LINKALL!$LINKALL$ac_delim +NOLINKALL!$NOLINKALL$ac_delim +LLVM_ON_UNIX!$LLVM_ON_UNIX$ac_delim +LLVM_ON_WIN32!$LLVM_ON_WIN32$ac_delim +ARCH!$ARCH$ac_delim +HOST_ARCH!$HOST_ARCH$ac_delim +ENDIAN!$ENDIAN$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LLVM_CROSS_COMPILING!$LLVM_CROSS_COMPILING$ac_delim +BUILD_CC!$BUILD_CC$ac_delim +BUILD_EXEEXT!$BUILD_EXEEXT$ac_delim +BUILD_CXX!$BUILD_CXX$ac_delim +CVSBUILD!$CVSBUILD$ac_delim +ENABLE_LIBCPP!$ENABLE_LIBCPP$ac_delim +ENABLE_CXX11!$ENABLE_CXX11$ac_delim +ENABLE_SPLIT_DWARF!$ENABLE_SPLIT_DWARF$ac_delim +ENABLE_CLANG_ARCMT!$ENABLE_CLANG_ARCMT$ac_delim +ENABLE_CLANG_STATIC_ANALYZER!$ENABLE_CLANG_STATIC_ANALYZER$ac_delim +ENABLE_CLANG_REWRITER!$ENABLE_CLANG_REWRITER$ac_delim +ENABLE_OPTIMIZED!$ENABLE_OPTIMIZED$ac_delim +ENABLE_PROFILING!$ENABLE_PROFILING$ac_delim +DISABLE_ASSERTIONS!$DISABLE_ASSERTIONS$ac_delim +ENABLE_WERROR!$ENABLE_WERROR$ac_delim +ENABLE_EXPENSIVE_CHECKS!$ENABLE_EXPENSIVE_CHECKS$ac_delim +EXPENSIVE_CHECKS!$EXPENSIVE_CHECKS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +DEBUG_RUNTIME!$DEBUG_RUNTIME$ac_delim +DEBUG_SYMBOLS!$DEBUG_SYMBOLS$ac_delim +KEEP_SYMBOLS!$KEEP_SYMBOLS$ac_delim +JIT!$JIT$ac_delim +TARGET_HAS_JIT!$TARGET_HAS_JIT$ac_delim +ENABLE_DOCS!$ENABLE_DOCS$ac_delim +ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim +LLVM_ENABLE_THREADS!$LLVM_ENABLE_THREADS$ac_delim +ENABLE_PTHREADS!$ENABLE_PTHREADS$ac_delim +LLVM_ENABLE_ZLIB!$LLVM_ENABLE_ZLIB$ac_delim +ENABLE_PIC!$ENABLE_PIC$ac_delim +ENABLE_SHARED!$ENABLE_SHARED$ac_delim +ENABLE_EMBED_STDCXX!$ENABLE_EMBED_STDCXX$ac_delim +ENABLE_TIMESTAMPS!$ENABLE_TIMESTAMPS$ac_delim +TARGETS_TO_BUILD!$TARGETS_TO_BUILD$ac_delim +LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim +LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim +LLVM_ENUM_ASM_PARSERS!$LLVM_ENUM_ASM_PARSERS$ac_delim +LLVM_ENUM_DISASSEMBLERS!$LLVM_ENUM_DISASSEMBLERS$ac_delim +OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim +EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim +EXTRA_LD_OPTIONS!$EXTRA_LD_OPTIONS$ac_delim +CLANG_SRC_ROOT!$CLANG_SRC_ROOT$ac_delim +BINUTILS_INCDIR!$BINUTILS_INCDIR$ac_delim +INTERNAL_PREFIX!$INTERNAL_PREFIX$ac_delim +NM!$NM$ac_delim +ifGNUmake!$ifGNUmake$ac_delim +LN_S!$LN_S$ac_delim +CMP!$CMP$ac_delim +CP!$CP$ac_delim +DATE!$DATE$ac_delim +FIND!$FIND$ac_delim +MKDIR!$MKDIR$ac_delim +MV!$MV$ac_delim +RANLIB!$RANLIB$ac_delim +AR!$AR$ac_delim +RM!$RM$ac_delim +SED!$SED$ac_delim +TAR!$TAR$ac_delim +BINPWD!$BINPWD$ac_delim +GRAPHVIZ!$GRAPHVIZ$ac_delim +DOT!$DOT$ac_delim +FDP!$FDP$ac_delim +NEATO!$NEATO$ac_delim +TWOPI!$TWOPI$ac_delim +CIRCO!$CIRCO$ac_delim +GV!$GV$ac_delim +DOTTY!$DOTTY$ac_delim +XDOT!$XDOT$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +BZIP2!$BZIP2$ac_delim +CAT!$CAT$ac_delim +DOXYGEN!$DOXYGEN$ac_delim +GROFF!$GROFF$ac_delim +GZIPBIN!$GZIPBIN$ac_delim +PDFROFF!$PDFROFF$ac_delim +ZIP!$ZIP$ac_delim +OCAMLC!$OCAMLC$ac_delim +OCAMLOPT!$OCAMLOPT$ac_delim +OCAMLDEP!$OCAMLDEP$ac_delim +OCAMLDOC!$OCAMLDOC$ac_delim +GAS!$GAS$ac_delim +HAVE_LINK_VERSION_SCRIPT!$HAVE_LINK_VERSION_SCRIPT$ac_delim +INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim +INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim +CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim +CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim +LIBADD_DL!$LIBADD_DL$ac_delim +NO_VARIADIC_MACROS!$NO_VARIADIC_MACROS$ac_delim +NO_MISSING_FIELD_INITIALIZERS!$NO_MISSING_FIELD_INITIALIZERS$ac_delim +COVERED_SWITCH_DEFAULT!$COVERED_SWITCH_DEFAULT$ac_delim +NO_MAYBE_UNINITIALIZED!$NO_MAYBE_UNINITIALIZED$ac_delim +NO_UNINITIALIZED!$NO_UNINITIALIZED$ac_delim +PYTHON!$PYTHON$ac_delim +USE_UDIS86!$USE_UDIS86$ac_delim +USE_OPROFILE!$USE_OPROFILE$ac_delim +USE_INTEL_JITEVENTS!$USE_INTEL_JITEVENTS$ac_delim +XML2CONFIG!$XML2CONFIG$ac_delim +LIBXML2_LIBS!$LIBXML2_LIBS$ac_delim +LIBXML2_INC!$LIBXML2_INC$ac_delim +CXXCPP!$CXXCPP$ac_delim +HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim +HAVE_LIBZ!$HAVE_LIBZ$ac_delim +HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim +MMAP_FILE!$MMAP_FILE$ac_delim +SHLIBEXT!$SHLIBEXT$ac_delim +SHLIBPATH_VAR!$SHLIBPATH_VAR$ac_delim +LLVM_PREFIX!$LLVM_PREFIX$ac_delim +LLVM_BINDIR!$LLVM_BINDIR$ac_delim +LLVM_DATADIR!$LLVM_DATADIR$ac_delim +LLVM_DOCSDIR!$LLVM_DOCSDIR$ac_delim +LLVM_ETCDIR!$LLVM_ETCDIR$ac_delim +LLVM_INCLUDEDIR!$LLVM_INCLUDEDIR$ac_delim +LLVM_INFODIR!$LLVM_INFODIR$ac_delim +LLVM_MANDIR!$LLVM_MANDIR$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +LLVM_CONFIGTIME!$LLVM_CONFIGTIME$ac_delim +BINDINGS_TO_BUILD!$BINDINGS_TO_BUILD$ac_delim +ALL_BINDINGS!$ALL_BINDINGS$ac_delim +OCAML_LIBDIR!$OCAML_LIBDIR$ac_delim +ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim +RPATH!$RPATH$ac_delim +RDYNAMIC!$RDYNAMIC$ac_delim +program_prefix!$program_prefix$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 10; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-3.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" | sed -f "$tmp/subs-3.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" + ;; + + :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 +echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/Makefile Makefile ;; + "Makefile.common":C) ${llvm_src}/autoconf/mkinstalldirs `dirname Makefile.common` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/Makefile.common Makefile.common ;; + "examples/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname examples/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/examples/Makefile examples/Makefile ;; + "lib/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/lib/Makefile lib/Makefile ;; + "test/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname test/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/test/Makefile test/Makefile ;; + "test/Makefile.tests":C) ${llvm_src}/autoconf/mkinstalldirs `dirname test/Makefile.tests` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/test/Makefile.tests test/Makefile.tests ;; + "unittests/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname unittests/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/unittests/Makefile unittests/Makefile ;; + "tools/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname tools/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/tools/Makefile tools/Makefile ;; + "utils/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname utils/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/utils/Makefile utils/Makefile ;; + "projects/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname projects/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/projects/Makefile projects/Makefile ;; + "bindings/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname bindings/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/bindings/Makefile bindings/Makefile ;; + "bindings/ocaml/Makefile.ocaml":C) ${llvm_src}/autoconf/mkinstalldirs `dirname bindings/ocaml/Makefile.ocaml` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/bindings/ocaml/Makefile.ocaml bindings/ocaml/Makefile.ocaml ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="$ac_sub_configure_args '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="$ac_arg $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + echo "$as_me:$LINENO: $ac_msg" >&5 + echo "$ac_msg" >&6 + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5 +echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { echo "$as_me:$LINENO: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5 +echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;} + { (exit 1); exit 1; }; } + fi + + cd "$ac_popdir" + done +fi + diff --git a/docs/AliasAnalysis.rst b/docs/AliasAnalysis.rst new file mode 100644 index 00000000..712d57d1 --- /dev/null +++ b/docs/AliasAnalysis.rst @@ -0,0 +1,699 @@ +================================== +LLVM Alias Analysis Infrastructure +================================== + +.. contents:: + :local: + +Introduction +============ + +Alias Analysis (aka Pointer Analysis) is a class of techniques which attempt to +determine whether or not two pointers ever can point to the same object in +memory. There are many different algorithms for alias analysis and many +different ways of classifying them: flow-sensitive vs. flow-insensitive, +context-sensitive vs. context-insensitive, field-sensitive +vs. field-insensitive, unification-based vs. subset-based, etc. Traditionally, +alias analyses respond to a query with a `Must, May, or No`_ alias response, +indicating that two pointers always point to the same object, might point to the +same object, or are known to never point to the same object. + +The LLVM `AliasAnalysis +`__ class is the +primary interface used by clients and implementations of alias analyses in the +LLVM system. This class is the common interface between clients of alias +analysis information and the implementations providing it, and is designed to +support a wide range of implementations and clients (but currently all clients +are assumed to be flow-insensitive). In addition to simple alias analysis +information, this class exposes Mod/Ref information from those implementations +which can provide it, allowing for powerful analyses and transformations to work +well together. + +This document contains information necessary to successfully implement this +interface, use it, and to test both sides. It also explains some of the finer +points about what exactly results mean. If you feel that something is unclear +or should be added, please `let me know `_. + +``AliasAnalysis`` Class Overview +================================ + +The `AliasAnalysis `__ +class defines the interface that the various alias analysis implementations +should support. This class exports two important enums: ``AliasResult`` and +``ModRefResult`` which represent the result of an alias query or a mod/ref +query, respectively. + +The ``AliasAnalysis`` interface exposes information about memory, represented in +several different ways. In particular, memory objects are represented as a +starting address and size, and function calls are represented as the actual +``call`` or ``invoke`` instructions that performs the call. The +``AliasAnalysis`` interface also exposes some helper methods which allow you to +get mod/ref information for arbitrary instructions. + +All ``AliasAnalysis`` interfaces require that in queries involving multiple +values, values which are not `constants `_ are all +defined within the same function. + +Representation of Pointers +-------------------------- + +Most importantly, the ``AliasAnalysis`` class provides several methods which are +used to query whether or not two memory objects alias, whether function calls +can modify or read a memory object, etc. For all of these queries, memory +objects are represented as a pair of their starting address (a symbolic LLVM +``Value*``) and a static size. + +Representing memory objects as a starting address and a size is critically +important for correct Alias Analyses. For example, consider this (silly, but +possible) C code: + +.. code-block:: c++ + + int i; + char C[2]; + char A[10]; + /* ... */ + for (i = 0; i != 10; ++i) { + C[0] = A[i]; /* One byte store */ + C[1] = A[9-i]; /* One byte store */ + } + +In this case, the ``basicaa`` pass will disambiguate the stores to ``C[0]`` and +``C[1]`` because they are accesses to two distinct locations one byte apart, and +the accesses are each one byte. In this case, the Loop Invariant Code Motion +(LICM) pass can use store motion to remove the stores from the loop. In +constrast, the following code: + +.. code-block:: c++ + + int i; + char C[2]; + char A[10]; + /* ... */ + for (i = 0; i != 10; ++i) { + ((short*)C)[0] = A[i]; /* Two byte store! */ + C[1] = A[9-i]; /* One byte store */ + } + +In this case, the two stores to C do alias each other, because the access to the +``&C[0]`` element is a two byte access. If size information wasn't available in +the query, even the first case would have to conservatively assume that the +accesses alias. + +.. _alias: + +The ``alias`` method +-------------------- + +The ``alias`` method is the primary interface used to determine whether or not +two memory objects alias each other. It takes two memory objects as input and +returns MustAlias, PartialAlias, MayAlias, or NoAlias as appropriate. + +Like all ``AliasAnalysis`` interfaces, the ``alias`` method requires that either +the two pointer values be defined within the same function, or at least one of +the values is a `constant `_. + +.. _Must, May, or No: + +Must, May, and No Alias Responses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``NoAlias`` response may be used when there is never an immediate dependence +between any memory reference *based* on one pointer and any memory reference +*based* the other. The most obvious example is when the two pointers point to +non-overlapping memory ranges. Another is when the two pointers are only ever +used for reading memory. Another is when the memory is freed and reallocated +between accesses through one pointer and accesses through the other --- in this +case, there is a dependence, but it's mediated by the free and reallocation. + +As an exception to this is with the `noalias `_ keyword; +the "irrelevant" dependencies are ignored. + +The ``MayAlias`` response is used whenever the two pointers might refer to the +same object. + +The ``PartialAlias`` response is used when the two memory objects are known to +be overlapping in some way, but do not start at the same address. + +The ``MustAlias`` response may only be returned if the two memory objects are +guaranteed to always start at exactly the same location. A ``MustAlias`` +response implies that the pointers compare equal. + +The ``getModRefInfo`` methods +----------------------------- + +The ``getModRefInfo`` methods return information about whether the execution of +an instruction can read or modify a memory location. Mod/Ref information is +always conservative: if an instruction **might** read or write a location, +``ModRef`` is returned. + +The ``AliasAnalysis`` class also provides a ``getModRefInfo`` method for testing +dependencies between function calls. This method takes two call sites (``CS1`` +& ``CS2``), returns ``NoModRef`` if neither call writes to memory read or +written by the other, ``Ref`` if ``CS1`` reads memory written by ``CS2``, +``Mod`` if ``CS1`` writes to memory read or written by ``CS2``, or ``ModRef`` if +``CS1`` might read or write memory written to by ``CS2``. Note that this +relation is not commutative. + +Other useful ``AliasAnalysis`` methods +-------------------------------------- + +Several other tidbits of information are often collected by various alias +analysis implementations and can be put to good use by various clients. + +The ``pointsToConstantMemory`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``pointsToConstantMemory`` method returns true if and only if the analysis +can prove that the pointer only points to unchanging memory locations +(functions, constant global variables, and the null pointer). This information +can be used to refine mod/ref information: it is impossible for an unchanging +memory location to be modified. + +.. _never access memory or only read memory: + +The ``doesNotAccessMemory`` and ``onlyReadsMemory`` methods +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These methods are used to provide very simple mod/ref information for function +calls. The ``doesNotAccessMemory`` method returns true for a function if the +analysis can prove that the function never reads or writes to memory, or if the +function only reads from constant memory. Functions with this property are +side-effect free and only depend on their input arguments, allowing them to be +eliminated if they form common subexpressions or be hoisted out of loops. Many +common functions behave this way (e.g., ``sin`` and ``cos``) but many others do +not (e.g., ``acos``, which modifies the ``errno`` variable). + +The ``onlyReadsMemory`` method returns true for a function if analysis can prove +that (at most) the function only reads from non-volatile memory. Functions with +this property are side-effect free, only depending on their input arguments and +the state of memory when they are called. This property allows calls to these +functions to be eliminated and moved around, as long as there is no store +instruction that changes the contents of memory. Note that all functions that +satisfy the ``doesNotAccessMemory`` method also satisfies ``onlyReadsMemory``. + +Writing a new ``AliasAnalysis`` Implementation +============================================== + +Writing a new alias analysis implementation for LLVM is quite straight-forward. +There are already several implementations that you can use for examples, and the +following information should help fill in any details. For a examples, take a +look at the `various alias analysis implementations`_ included with LLVM. + +Different Pass styles +--------------------- + +The first step to determining what type of :doc:`LLVM pass ` +you need to use for your Alias Analysis. As is the case with most other +analyses and transformations, the answer should be fairly obvious from what type +of problem you are trying to solve: + +#. If you require interprocedural analysis, it should be a ``Pass``. +#. If you are a function-local analysis, subclass ``FunctionPass``. +#. If you don't need to look at the program at all, subclass ``ImmutablePass``. + +In addition to the pass that you subclass, you should also inherit from the +``AliasAnalysis`` interface, of course, and use the ``RegisterAnalysisGroup`` +template to register as an implementation of ``AliasAnalysis``. + +Required initialization calls +----------------------------- + +Your subclass of ``AliasAnalysis`` is required to invoke two methods on the +``AliasAnalysis`` base class: ``getAnalysisUsage`` and +``InitializeAliasAnalysis``. In particular, your implementation of +``getAnalysisUsage`` should explicitly call into the +``AliasAnalysis::getAnalysisUsage`` method in addition to doing any declaring +any pass dependencies your pass has. Thus you should have something like this: + +.. code-block:: c++ + + void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + // declare your dependencies here. + } + +Additionally, your must invoke the ``InitializeAliasAnalysis`` method from your +analysis run method (``run`` for a ``Pass``, ``runOnFunction`` for a +``FunctionPass``, or ``InitializePass`` for an ``ImmutablePass``). For example +(as part of a ``Pass``): + +.. code-block:: c++ + + bool run(Module &M) { + InitializeAliasAnalysis(this); + // Perform analysis here... + return false; + } + +Interfaces which may be specified +--------------------------------- + +All of the `AliasAnalysis +`__ virtual methods +default to providing :ref:`chaining ` to another alias +analysis implementation, which ends up returning conservatively correct +information (returning "May" Alias and "Mod/Ref" for alias and mod/ref queries +respectively). Depending on the capabilities of the analysis you are +implementing, you just override the interfaces you can improve. + +.. _aliasanalysis-chaining: + +``AliasAnalysis`` chaining behavior +----------------------------------- + +With only one special exception (the :ref:`-no-aa ` pass) +every alias analysis pass chains to another alias analysis implementation (for +example, the user can specify "``-basicaa -ds-aa -licm``" to get the maximum +benefit from both alias analyses). The alias analysis class automatically +takes care of most of this for methods that you don't override. For methods +that you do override, in code paths that return a conservative MayAlias or +Mod/Ref result, simply return whatever the superclass computes. For example: + +.. code-block:: c++ + + AliasAnalysis::AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + if (...) + return NoAlias; + ... + + // Couldn't determine a must or no-alias result. + return AliasAnalysis::alias(V1, V1Size, V2, V2Size); + } + +In addition to analysis queries, you must make sure to unconditionally pass LLVM +`update notification`_ methods to the superclass as well if you override them, +which allows all alias analyses in a change to be updated. + +.. _update notification: + +Updating analysis results for transformations +--------------------------------------------- + +Alias analysis information is initially computed for a static snapshot of the +program, but clients will use this information to make transformations to the +code. All but the most trivial forms of alias analysis will need to have their +analysis results updated to reflect the changes made by these transformations. + +The ``AliasAnalysis`` interface exposes four methods which are used to +communicate program changes from the clients to the analysis implementations. +Various alias analysis implementations should use these methods to ensure that +their internal data structures are kept up-to-date as the program changes (for +example, when an instruction is deleted), and clients of alias analysis must be +sure to call these interfaces appropriately. + +The ``deleteValue`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``deleteValue`` method is called by transformations when they remove an +instruction or any other value from the program (including values that do not +use pointers). Typically alias analyses keep data structures that have entries +for each value in the program. When this method is called, they should remove +any entries for the specified value, if they exist. + +The ``copyValue`` method +^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``copyValue`` method is used when a new value is introduced into the +program. There is no way to introduce a value into the program that did not +exist before (this doesn't make sense for a safe compiler transformation), so +this is the only way to introduce a new value. This method indicates that the +new value has exactly the same properties as the value being copied. + +The ``replaceWithNewValue`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This method is a simple helper method that is provided to make clients easier to +use. It is implemented by copying the old analysis information to the new +value, then deleting the old value. This method cannot be overridden by alias +analysis implementations. + +The ``addEscapingUse`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``addEscapingUse`` method is used when the uses of a pointer value have +changed in ways that may invalidate precomputed analysis information. +Implementations may either use this callback to provide conservative responses +for points whose uses have change since analysis time, or may recompute some or +all of their internal state to continue providing accurate responses. + +In general, any new use of a pointer value is considered an escaping use, and +must be reported through this callback, *except* for the uses below: + +* A ``bitcast`` or ``getelementptr`` of the pointer +* A ``store`` through the pointer (but not a ``store`` *of* the pointer) +* A ``load`` through the pointer + +Efficiency Issues +----------------- + +From the LLVM perspective, the only thing you need to do to provide an efficient +alias analysis is to make sure that alias analysis **queries** are serviced +quickly. The actual calculation of the alias analysis results (the "run" +method) is only performed once, but many (perhaps duplicate) queries may be +performed. Because of this, try to move as much computation to the run method +as possible (within reason). + +Limitations +----------- + +The AliasAnalysis infrastructure has several limitations which make writing a +new ``AliasAnalysis`` implementation difficult. + +There is no way to override the default alias analysis. It would be very useful +to be able to do something like "``opt -my-aa -O2``" and have it use ``-my-aa`` +for all passes which need AliasAnalysis, but there is currently no support for +that, short of changing the source code and recompiling. Similarly, there is +also no way of setting a chain of analyses as the default. + +There is no way for transform passes to declare that they preserve +``AliasAnalysis`` implementations. The ``AliasAnalysis`` interface includes +``deleteValue`` and ``copyValue`` methods which are intended to allow a pass to +keep an AliasAnalysis consistent, however there's no way for a pass to declare +in its ``getAnalysisUsage`` that it does so. Some passes attempt to use +``AU.addPreserved``, however this doesn't actually have any +effect. + +``AliasAnalysisCounter`` (``-count-aa``) and ``AliasDebugger`` (``-debug-aa``) +are implemented as ``ModulePass`` classes, so if your alias analysis uses +``FunctionPass``, it won't be able to use these utilities. If you try to use +them, the pass manager will silently route alias analysis queries directly to +``BasicAliasAnalysis`` instead. + +Similarly, the ``opt -p`` option introduces ``ModulePass`` passes between each +pass, which prevents the use of ``FunctionPass`` alias analysis passes. + +The ``AliasAnalysis`` API does have functions for notifying implementations when +values are deleted or copied, however these aren't sufficient. There are many +other ways that LLVM IR can be modified which could be relevant to +``AliasAnalysis`` implementations which can not be expressed. + +The ``AliasAnalysisDebugger`` utility seems to suggest that ``AliasAnalysis`` +implementations can expect that they will be informed of any relevant ``Value`` +before it appears in an alias query. However, popular clients such as ``GVN`` +don't support this, and are known to trigger errors when run with the +``AliasAnalysisDebugger``. + +Due to several of the above limitations, the most obvious use for the +``AliasAnalysisCounter`` utility, collecting stats on all alias queries in a +compilation, doesn't work, even if the ``AliasAnalysis`` implementations don't +use ``FunctionPass``. There's no way to set a default, much less a default +sequence, and there's no way to preserve it. + +The ``AliasSetTracker`` class (which is used by ``LICM``) makes a +non-deterministic number of alias queries. This can cause stats collected by +``AliasAnalysisCounter`` to have fluctuations among identical runs, for +example. Another consequence is that debugging techniques involving pausing +execution after a predetermined number of queries can be unreliable. + +Many alias queries can be reformulated in terms of other alias queries. When +multiple ``AliasAnalysis`` queries are chained together, it would make sense to +start those queries from the beginning of the chain, with care taken to avoid +infinite looping, however currently an implementation which wants to do this can +only start such queries from itself. + +Using alias analysis results +============================ + +There are several different ways to use alias analysis results. In order of +preference, these are: + +Using the ``MemoryDependenceAnalysis`` Pass +------------------------------------------- + +The ``memdep`` pass uses alias analysis to provide high-level dependence +information about memory-using instructions. This will tell you which store +feeds into a load, for example. It uses caching and other techniques to be +efficient, and is used by Dead Store Elimination, GVN, and memcpy optimizations. + +.. _AliasSetTracker: + +Using the ``AliasSetTracker`` class +----------------------------------- + +Many transformations need information about alias **sets** that are active in +some scope, rather than information about pairwise aliasing. The +`AliasSetTracker `__ +class is used to efficiently build these Alias Sets from the pairwise alias +analysis information provided by the ``AliasAnalysis`` interface. + +First you initialize the AliasSetTracker by using the "``add``" methods to add +information about various potentially aliasing instructions in the scope you are +interested in. Once all of the alias sets are completed, your pass should +simply iterate through the constructed alias sets, using the ``AliasSetTracker`` +``begin()``/``end()`` methods. + +The ``AliasSet``\s formed by the ``AliasSetTracker`` are guaranteed to be +disjoint, calculate mod/ref information and volatility for the set, and keep +track of whether or not all of the pointers in the set are Must aliases. The +AliasSetTracker also makes sure that sets are properly folded due to call +instructions, and can provide a list of pointers in each set. + +As an example user of this, the `Loop Invariant Code Motion +`_ pass uses ``AliasSetTracker``\s to calculate alias +sets for each loop nest. If an ``AliasSet`` in a loop is not modified, then all +load instructions from that set may be hoisted out of the loop. If any alias +sets are stored to **and** are must alias sets, then the stores may be sunk +to outside of the loop, promoting the memory location to a register for the +duration of the loop nest. Both of these transformations only apply if the +pointer argument is loop-invariant. + +The AliasSetTracker implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The AliasSetTracker class is implemented to be as efficient as possible. It +uses the union-find algorithm to efficiently merge AliasSets when a pointer is +inserted into the AliasSetTracker that aliases multiple sets. The primary data +structure is a hash table mapping pointers to the AliasSet they are in. + +The AliasSetTracker class must maintain a list of all of the LLVM ``Value*``\s +that are in each AliasSet. Since the hash table already has entries for each +LLVM ``Value*`` of interest, the AliasesSets thread the linked list through +these hash-table nodes to avoid having to allocate memory unnecessarily, and to +make merging alias sets extremely efficient (the linked list merge is constant +time). + +You shouldn't need to understand these details if you are just a client of the +AliasSetTracker, but if you look at the code, hopefully this brief description +will help make sense of why things are designed the way they are. + +Using the ``AliasAnalysis`` interface directly +---------------------------------------------- + +If neither of these utility class are what your pass needs, you should use the +interfaces exposed by the ``AliasAnalysis`` class directly. Try to use the +higher-level methods when possible (e.g., use mod/ref information instead of the +`alias`_ method directly if possible) to get the best precision and efficiency. + +Existing alias analysis implementations and clients +=================================================== + +If you're going to be working with the LLVM alias analysis infrastructure, you +should know what clients and implementations of alias analysis are available. +In particular, if you are implementing an alias analysis, you should be aware of +the `the clients`_ that are useful for monitoring and evaluating different +implementations. + +.. _various alias analysis implementations: + +Available ``AliasAnalysis`` implementations +------------------------------------------- + +This section lists the various implementations of the ``AliasAnalysis`` +interface. With the exception of the :ref:`-no-aa ` +implementation, all of these :ref:`chain ` to other +alias analysis implementations. + +.. _aliasanalysis-no-aa: + +The ``-no-aa`` pass +^^^^^^^^^^^^^^^^^^^ + +The ``-no-aa`` pass is just like what it sounds: an alias analysis that never +returns any useful information. This pass can be useful if you think that alias +analysis is doing something wrong and are trying to narrow down a problem. + +The ``-basicaa`` pass +^^^^^^^^^^^^^^^^^^^^^ + +The ``-basicaa`` pass is an aggressive local analysis that *knows* many +important facts: + +* Distinct globals, stack allocations, and heap allocations can never alias. +* Globals, stack allocations, and heap allocations never alias the null pointer. +* Different fields of a structure do not alias. +* Indexes into arrays with statically differing subscripts cannot alias. +* Many common standard C library functions `never access memory or only read + memory`_. +* Pointers that obviously point to constant globals "``pointToConstantMemory``". +* Function calls can not modify or references stack allocations if they never + escape from the function that allocates them (a common case for automatic + arrays). + +The ``-globalsmodref-aa`` pass +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This pass implements a simple context-sensitive mod/ref and alias analysis for +internal global variables that don't "have their address taken". If a global +does not have its address taken, the pass knows that no pointers alias the +global. This pass also keeps track of functions that it knows never access +memory or never read memory. This allows certain optimizations (e.g. GVN) to +eliminate call instructions entirely. + +The real power of this pass is that it provides context-sensitive mod/ref +information for call instructions. This allows the optimizer to know that calls +to a function do not clobber or read the value of the global, allowing loads and +stores to be eliminated. + +.. note:: + + This pass is somewhat limited in its scope (only support non-address taken + globals), but is very quick analysis. + +The ``-steens-aa`` pass +^^^^^^^^^^^^^^^^^^^^^^^ + +The ``-steens-aa`` pass implements a variation on the well-known "Steensgaard's +algorithm" for interprocedural alias analysis. Steensgaard's algorithm is a +unification-based, flow-insensitive, context-insensitive, and field-insensitive +alias analysis that is also very scalable (effectively linear time). + +The LLVM ``-steens-aa`` pass implements a "speculatively field-**sensitive**" +version of Steensgaard's algorithm using the Data Structure Analysis framework. +This gives it substantially more precision than the standard algorithm while +maintaining excellent analysis scalability. + +.. note:: + + ``-steens-aa`` is available in the optional "poolalloc" module. It is not part + of the LLVM core. + +The ``-ds-aa`` pass +^^^^^^^^^^^^^^^^^^^ + +The ``-ds-aa`` pass implements the full Data Structure Analysis algorithm. Data +Structure Analysis is a modular unification-based, flow-insensitive, +context-**sensitive**, and speculatively field-**sensitive** alias +analysis that is also quite scalable, usually at ``O(n * log(n))``. + +This algorithm is capable of responding to a full variety of alias analysis +queries, and can provide context-sensitive mod/ref information as well. The +only major facility not implemented so far is support for must-alias +information. + +.. note:: + + ``-ds-aa`` is available in the optional "poolalloc" module. It is not part of + the LLVM core. + +The ``-scev-aa`` pass +^^^^^^^^^^^^^^^^^^^^^ + +The ``-scev-aa`` pass implements AliasAnalysis queries by translating them into +ScalarEvolution queries. This gives it a more complete understanding of +``getelementptr`` instructions and loop induction variables than other alias +analyses have. + +Alias analysis driven transformations +------------------------------------- + +LLVM includes several alias-analysis driven transformations which can be used +with any of the implementations above. + +The ``-adce`` pass +^^^^^^^^^^^^^^^^^^ + +The ``-adce`` pass, which implements Aggressive Dead Code Elimination uses the +``AliasAnalysis`` interface to delete calls to functions that do not have +side-effects and are not used. + +The ``-licm`` pass +^^^^^^^^^^^^^^^^^^ + +The ``-licm`` pass implements various Loop Invariant Code Motion related +transformations. It uses the ``AliasAnalysis`` interface for several different +transformations: + +* It uses mod/ref information to hoist or sink load instructions out of loops if + there are no instructions in the loop that modifies the memory loaded. + +* It uses mod/ref information to hoist function calls out of loops that do not + write to memory and are loop-invariant. + +* If uses alias information to promote memory objects that are loaded and stored + to in loops to live in a register instead. It can do this if there are no may + aliases to the loaded/stored memory location. + +The ``-argpromotion`` pass +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``-argpromotion`` pass promotes by-reference arguments to be passed in +by-value instead. In particular, if pointer arguments are only loaded from it +passes in the value loaded instead of the address to the function. This pass +uses alias information to make sure that the value loaded from the argument +pointer is not modified between the entry of the function and any load of the +pointer. + +The ``-gvn``, ``-memcpyopt``, and ``-dse`` passes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These passes use AliasAnalysis information to reason about loads and stores. + +.. _the clients: + +Clients for debugging and evaluation of implementations +------------------------------------------------------- + +These passes are useful for evaluating the various alias analysis +implementations. You can use them with commands like: + +.. code-block:: bash + + % opt -ds-aa -aa-eval foo.bc -disable-output -stats + +The ``-print-alias-sets`` pass +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``-print-alias-sets`` pass is exposed as part of the ``opt`` tool to print +out the Alias Sets formed by the `AliasSetTracker`_ class. This is useful if +you're using the ``AliasSetTracker`` class. To use it, use something like: + +.. code-block:: bash + + % opt -ds-aa -print-alias-sets -disable-output + +The ``-count-aa`` pass +^^^^^^^^^^^^^^^^^^^^^^ + +The ``-count-aa`` pass is useful to see how many queries a particular pass is +making and what responses are returned by the alias analysis. As an example: + +.. code-block:: bash + + % opt -basicaa -count-aa -ds-aa -count-aa -licm + +will print out how many queries (and what responses are returned) by the +``-licm`` pass (of the ``-ds-aa`` pass) and how many queries are made of the +``-basicaa`` pass by the ``-ds-aa`` pass. This can be useful when debugging a +transformation or an alias analysis implementation. + +The ``-aa-eval`` pass +^^^^^^^^^^^^^^^^^^^^^ + +The ``-aa-eval`` pass simply iterates through all pairs of pointers in a +function and asks an alias analysis whether or not the pointers alias. This +gives an indication of the precision of the alias analysis. Statistics are +printed indicating the percent of no/may/must aliases found (a more precise +algorithm will have a lower number of may aliases). + +Memory Dependence Analysis +========================== + +If you're just looking to be a client of alias analysis information, consider +using the Memory Dependence Analysis interface instead. MemDep is a lazy, +caching layer on top of alias analysis that is able to answer the question of +what preceding memory operations a given instruction depends on, either at an +intra- or inter-block level. Because of its laziness and caching policy, using +MemDep can be a significant performance win over accessing alias analysis +directly. diff --git a/docs/Atomics.rst b/docs/Atomics.rst new file mode 100644 index 00000000..1243f345 --- /dev/null +++ b/docs/Atomics.rst @@ -0,0 +1,439 @@ +============================================== +LLVM Atomic Instructions and Concurrency Guide +============================================== + +.. contents:: + :local: + +Introduction +============ + +Historically, LLVM has not had very strong support for concurrency; some minimal +intrinsics were provided, and ``volatile`` was used in some cases to achieve +rough semantics in the presence of concurrency. However, this is changing; +there are now new instructions which are well-defined in the presence of threads +and asynchronous signals, and the model for existing instructions has been +clarified in the IR. + +The atomic instructions are designed specifically to provide readable IR and +optimized code generation for the following: + +* The new C++0x ```` header. (`C++0x draft available here + `_.) (`C1x draft available here + `_.) + +* Proper semantics for Java-style memory, for both ``volatile`` and regular + shared variables. (`Java Specification + `_) + +* gcc-compatible ``__sync_*`` builtins. (`Description + `_) + +* Other scenarios with atomic semantics, including ``static`` variables with + non-trivial constructors in C++. + +Atomic and volatile in the IR are orthogonal; "volatile" is the C/C++ volatile, +which ensures that every volatile load and store happens and is performed in the +stated order. A couple examples: if a SequentiallyConsistent store is +immediately followed by another SequentiallyConsistent store to the same +address, the first store can be erased. This transformation is not allowed for a +pair of volatile stores. On the other hand, a non-volatile non-atomic load can +be moved across a volatile load freely, but not an Acquire load. + +This document is intended to provide a guide to anyone either writing a frontend +for LLVM or working on optimization passes for LLVM with a guide for how to deal +with instructions with special semantics in the presence of concurrency. This +is not intended to be a precise guide to the semantics; the details can get +extremely complicated and unreadable, and are not usually necessary. + +.. _Optimization outside atomic: + +Optimization outside atomic +=========================== + +The basic ``'load'`` and ``'store'`` allow a variety of optimizations, but can +lead to undefined results in a concurrent environment; see `NotAtomic`_. This +section specifically goes into the one optimizer restriction which applies in +concurrent environments, which gets a bit more of an extended description +because any optimization dealing with stores needs to be aware of it. + +From the optimizer's point of view, the rule is that if there are not any +instructions with atomic ordering involved, concurrency does not matter, with +one exception: if a variable might be visible to another thread or signal +handler, a store cannot be inserted along a path where it might not execute +otherwise. Take the following example: + +.. code-block:: c + + /* C code, for readability; run through clang -O2 -S -emit-llvm to get + equivalent IR */ + int x; + void f(int* a) { + for (int i = 0; i < 100; i++) { + if (a[i]) + x += 1; + } + } + +The following is equivalent in non-concurrent situations: + +.. code-block:: c + + int x; + void f(int* a) { + int xtemp = x; + for (int i = 0; i < 100; i++) { + if (a[i]) + xtemp += 1; + } + x = xtemp; + } + +However, LLVM is not allowed to transform the former to the latter: it could +indirectly introduce undefined behavior if another thread can access ``x`` at +the same time. (This example is particularly of interest because before the +concurrency model was implemented, LLVM would perform this transformation.) + +Note that speculative loads are allowed; a load which is part of a race returns +``undef``, but does not have undefined behavior. + +Atomic instructions +=================== + +For cases where simple loads and stores are not sufficient, LLVM provides +various atomic instructions. The exact guarantees provided depend on the +ordering; see `Atomic orderings`_. + +``load atomic`` and ``store atomic`` provide the same basic functionality as +non-atomic loads and stores, but provide additional guarantees in situations +where threads and signals are involved. + +``cmpxchg`` and ``atomicrmw`` are essentially like an atomic load followed by an +atomic store (where the store is conditional for ``cmpxchg``), but no other +memory operation can happen on any thread between the load and store. Note that +LLVM's cmpxchg does not provide quite as many options as the C++0x version. + +A ``fence`` provides Acquire and/or Release ordering which is not part of +another operation; it is normally used along with Monotonic memory operations. +A Monotonic load followed by an Acquire fence is roughly equivalent to an +Acquire load. + +Frontends generating atomic instructions generally need to be aware of the +target to some degree; atomic instructions are guaranteed to be lock-free, and +therefore an instruction which is wider than the target natively supports can be +impossible to generate. + +.. _Atomic orderings: + +Atomic orderings +================ + +In order to achieve a balance between performance and necessary guarantees, +there are six levels of atomicity. They are listed in order of strength; each +level includes all the guarantees of the previous level except for +Acquire/Release. (See also `LangRef Ordering `_.) + +.. _NotAtomic: + +NotAtomic +--------- + +NotAtomic is the obvious, a load or store which is not atomic. (This isn't +really a level of atomicity, but is listed here for comparison.) This is +essentially a regular load or store. If there is a race on a given memory +location, loads from that location return undef. + +Relevant standard + This is intended to match shared variables in C/C++, and to be used in any + other context where memory access is necessary, and a race is impossible. (The + precise definition is in `LangRef Memory Model `_.) + +Notes for frontends + The rule is essentially that all memory accessed with basic loads and stores + by multiple threads should be protected by a lock or other synchronization; + otherwise, you are likely to run into undefined behavior. If your frontend is + for a "safe" language like Java, use Unordered to load and store any shared + variable. Note that NotAtomic volatile loads and stores are not properly + atomic; do not try to use them as a substitute. (Per the C/C++ standards, + volatile does provide some limited guarantees around asynchronous signals, but + atomics are generally a better solution.) + +Notes for optimizers + Introducing loads to shared variables along a codepath where they would not + otherwise exist is allowed; introducing stores to shared variables is not. See + `Optimization outside atomic`_. + +Notes for code generation + The one interesting restriction here is that it is not allowed to write to + bytes outside of the bytes relevant to a store. This is mostly relevant to + unaligned stores: it is not allowed in general to convert an unaligned store + into two aligned stores of the same width as the unaligned store. Backends are + also expected to generate an i8 store as an i8 store, and not an instruction + which writes to surrounding bytes. (If you are writing a backend for an + architecture which cannot satisfy these restrictions and cares about + concurrency, please send an email to llvmdev.) + +Unordered +--------- + +Unordered is the lowest level of atomicity. It essentially guarantees that races +produce somewhat sane results instead of having undefined behavior. It also +guarantees the operation to be lock-free, so it do not depend on the data being +part of a special atomic structure or depend on a separate per-process global +lock. Note that code generation will fail for unsupported atomic operations; if +you need such an operation, use explicit locking. + +Relevant standard + This is intended to match the Java memory model for shared variables. + +Notes for frontends + This cannot be used for synchronization, but is useful for Java and other + "safe" languages which need to guarantee that the generated code never + exhibits undefined behavior. Note that this guarantee is cheap on common + platforms for loads of a native width, but can be expensive or unavailable for + wider loads, like a 64-bit store on ARM. (A frontend for Java or other "safe" + languages would normally split a 64-bit store on ARM into two 32-bit unordered + stores.) + +Notes for optimizers + In terms of the optimizer, this prohibits any transformation that transforms a + single load into multiple loads, transforms a store into multiple stores, + narrows a store, or stores a value which would not be stored otherwise. Some + examples of unsafe optimizations are narrowing an assignment into a bitfield, + rematerializing a load, and turning loads and stores into a memcpy + call. Reordering unordered operations is safe, though, and optimizers should + take advantage of that because unordered operations are common in languages + that need them. + +Notes for code generation + These operations are required to be atomic in the sense that if you use + unordered loads and unordered stores, a load cannot see a value which was + never stored. A normal load or store instruction is usually sufficient, but + note that an unordered load or store cannot be split into multiple + instructions (or an instruction which does multiple memory operations, like + ``LDRD`` on ARM without LPAE, or not naturally-aligned ``LDRD`` on LPAE ARM). + +Monotonic +--------- + +Monotonic is the weakest level of atomicity that can be used in synchronization +primitives, although it does not provide any general synchronization. It +essentially guarantees that if you take all the operations affecting a specific +address, a consistent ordering exists. + +Relevant standard + This corresponds to the C++0x/C1x ``memory_order_relaxed``; see those + standards for the exact definition. + +Notes for frontends + If you are writing a frontend which uses this directly, use with caution. The + guarantees in terms of synchronization are very weak, so make sure these are + only used in a pattern which you know is correct. Generally, these would + either be used for atomic operations which do not protect other memory (like + an atomic counter), or along with a ``fence``. + +Notes for optimizers + In terms of the optimizer, this can be treated as a read+write on the relevant + memory location (and alias analysis will take advantage of that). In addition, + it is legal to reorder non-atomic and Unordered loads around Monotonic + loads. CSE/DSE and a few other optimizations are allowed, but Monotonic + operations are unlikely to be used in ways which would make those + optimizations useful. + +Notes for code generation + Code generation is essentially the same as that for unordered for loads and + stores. No fences are required. ``cmpxchg`` and ``atomicrmw`` are required + to appear as a single operation. + +Acquire +------- + +Acquire provides a barrier of the sort necessary to acquire a lock to access +other memory with normal loads and stores. + +Relevant standard + This corresponds to the C++0x/C1x ``memory_order_acquire``. It should also be + used for C++0x/C1x ``memory_order_consume``. + +Notes for frontends + If you are writing a frontend which uses this directly, use with caution. + Acquire only provides a semantic guarantee when paired with a Release + operation. + +Notes for optimizers + Optimizers not aware of atomics can treat this like a nothrow call. It is + also possible to move stores from before an Acquire load or read-modify-write + operation to after it, and move non-Acquire loads from before an Acquire + operation to after it. + +Notes for code generation + Architectures with weak memory ordering (essentially everything relevant today + except x86 and SPARC) require some sort of fence to maintain the Acquire + semantics. The precise fences required varies widely by architecture, but for + a simple implementation, most architectures provide a barrier which is strong + enough for everything (``dmb`` on ARM, ``sync`` on PowerPC, etc.). Putting + such a fence after the equivalent Monotonic operation is sufficient to + maintain Acquire semantics for a memory operation. + +Release +------- + +Release is similar to Acquire, but with a barrier of the sort necessary to +release a lock. + +Relevant standard + This corresponds to the C++0x/C1x ``memory_order_release``. + +Notes for frontends + If you are writing a frontend which uses this directly, use with caution. + Release only provides a semantic guarantee when paired with a Acquire + operation. + +Notes for optimizers + Optimizers not aware of atomics can treat this like a nothrow call. It is + also possible to move loads from after a Release store or read-modify-write + operation to before it, and move non-Release stores from after an Release + operation to before it. + +Notes for code generation + See the section on Acquire; a fence before the relevant operation is usually + sufficient for Release. Note that a store-store fence is not sufficient to + implement Release semantics; store-store fences are generally not exposed to + IR because they are extremely difficult to use correctly. + +AcquireRelease +-------------- + +AcquireRelease (``acq_rel`` in IR) provides both an Acquire and a Release +barrier (for fences and operations which both read and write memory). + +Relevant standard + This corresponds to the C++0x/C1x ``memory_order_acq_rel``. + +Notes for frontends + If you are writing a frontend which uses this directly, use with caution. + Acquire only provides a semantic guarantee when paired with a Release + operation, and vice versa. + +Notes for optimizers + In general, optimizers should treat this like a nothrow call; the possible + optimizations are usually not interesting. + +Notes for code generation + This operation has Acquire and Release semantics; see the sections on Acquire + and Release. + +SequentiallyConsistent +---------------------- + +SequentiallyConsistent (``seq_cst`` in IR) provides Acquire semantics for loads +and Release semantics for stores. Additionally, it guarantees that a total +ordering exists between all SequentiallyConsistent operations. + +Relevant standard + This corresponds to the C++0x/C1x ``memory_order_seq_cst``, Java volatile, and + the gcc-compatible ``__sync_*`` builtins which do not specify otherwise. + +Notes for frontends + If a frontend is exposing atomic operations, these are much easier to reason + about for the programmer than other kinds of operations, and using them is + generally a practical performance tradeoff. + +Notes for optimizers + Optimizers not aware of atomics can treat this like a nothrow call. For + SequentiallyConsistent loads and stores, the same reorderings are allowed as + for Acquire loads and Release stores, except that SequentiallyConsistent + operations may not be reordered. + +Notes for code generation + SequentiallyConsistent loads minimally require the same barriers as Acquire + operations and SequentiallyConsistent stores require Release + barriers. Additionally, the code generator must enforce ordering between + SequentiallyConsistent stores followed by SequentiallyConsistent loads. This + is usually done by emitting either a full fence before the loads or a full + fence after the stores; which is preferred varies by architecture. + +Atomics and IR optimization +=========================== + +Predicates for optimizer writers to query: + +* ``isSimple()``: A load or store which is not volatile or atomic. This is + what, for example, memcpyopt would check for operations it might transform. + +* ``isUnordered()``: A load or store which is not volatile and at most + Unordered. This would be checked, for example, by LICM before hoisting an + operation. + +* ``mayReadFromMemory()``/``mayWriteToMemory()``: Existing predicate, but note + that they return true for any operation which is volatile or at least + Monotonic. + +* Alias analysis: Note that AA will return ModRef for anything Acquire or + Release, and for the address accessed by any Monotonic operation. + +To support optimizing around atomic operations, make sure you are using the +right predicates; everything should work if that is done. If your pass should +optimize some atomic operations (Unordered operations in particular), make sure +it doesn't replace an atomic load or store with a non-atomic operation. + +Some examples of how optimizations interact with various kinds of atomic +operations: + +* ``memcpyopt``: An atomic operation cannot be optimized into part of a + memcpy/memset, including unordered loads/stores. It can pull operations + across some atomic operations. + +* LICM: Unordered loads/stores can be moved out of a loop. It just treats + monotonic operations like a read+write to a memory location, and anything + stricter than that like a nothrow call. + +* DSE: Unordered stores can be DSE'ed like normal stores. Monotonic stores can + be DSE'ed in some cases, but it's tricky to reason about, and not especially + important. + +* Folding a load: Any atomic load from a constant global can be constant-folded, + because it cannot be observed. Similar reasoning allows scalarrepl with + atomic loads and stores. + +Atomics and Codegen +=================== + +Atomic operations are represented in the SelectionDAG with ``ATOMIC_*`` opcodes. +On architectures which use barrier instructions for all atomic ordering (like +ARM), appropriate fences are split out as the DAG is built. + +The MachineMemOperand for all atomic operations is currently marked as volatile; +this is not correct in the IR sense of volatile, but CodeGen handles anything +marked volatile very conservatively. This should get fixed at some point. + +Common architectures have some way of representing at least a pointer-sized +lock-free ``cmpxchg``; such an operation can be used to implement all the other +atomic operations which can be represented in IR up to that size. Backends are +expected to implement all those operations, but not operations which cannot be +implemented in a lock-free manner. It is expected that backends will give an +error when given an operation which cannot be implemented. (The LLVM code +generator is not very helpful here at the moment, but hopefully that will +change.) + +The implementation of atomics on LL/SC architectures (like ARM) is currently a +bit of a mess; there is a lot of copy-pasted code across targets, and the +representation is relatively unsuited to optimization (it would be nice to be +able to optimize loops involving cmpxchg etc.). + +On x86, all atomic loads generate a ``MOV``. SequentiallyConsistent stores +generate an ``XCHG``, other stores generate a ``MOV``. SequentiallyConsistent +fences generate an ``MFENCE``, other fences do not cause any code to be +generated. cmpxchg uses the ``LOCK CMPXCHG`` instruction. ``atomicrmw xchg`` +uses ``XCHG``, ``atomicrmw add`` and ``atomicrmw sub`` use ``XADD``, and all +other ``atomicrmw`` operations generate a loop with ``LOCK CMPXCHG``. Depending +on the users of the result, some ``atomicrmw`` operations can be translated into +operations like ``LOCK AND``, but that does not work in general. + +On ARM, MIPS, and many other RISC architectures, Acquire, Release, and +SequentiallyConsistent semantics require barrier instructions for every such +operation. Loads and stores generate normal instructions. ``cmpxchg`` and +``atomicrmw`` can be represented using a loop with LL/SC-style instructions +which take some sort of exclusive lock on a cache line (``LDREX`` and ``STREX`` +on ARM, etc.). At the moment, the IR does not provide any way to represent a +weak ``cmpxchg`` which would not require a loop. diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst new file mode 100644 index 00000000..d9d1df0b --- /dev/null +++ b/docs/BitCodeFormat.rst @@ -0,0 +1,1093 @@ +.. role:: raw-html(raw) + :format: html + +======================== +LLVM Bitcode File Format +======================== + +.. contents:: + :local: + +Abstract +======== + +This document describes the LLVM bitstream file format and the encoding of the +LLVM IR into it. + +Overview +======== + +What is commonly known as the LLVM bitcode file format (also, sometimes +anachronistically known as bytecode) is actually two things: a `bitstream +container format`_ and an `encoding of LLVM IR`_ into the container format. + +The bitstream format is an abstract encoding of structured data, very similar to +XML in some ways. Like XML, bitstream files contain tags, and nested +structures, and you can parse the file without having to understand the tags. +Unlike XML, the bitstream format is a binary encoding, and unlike XML it +provides a mechanism for the file to self-describe "abbreviations", which are +effectively size optimizations for the content. + +LLVM IR files may be optionally embedded into a `wrapper`_ structure that makes +it easy to embed extra data along with LLVM IR files. + +This document first describes the LLVM bitstream format, describes the wrapper +format, then describes the record structure used by LLVM IR files. + +.. _bitstream container format: + +Bitstream Format +================ + +The bitstream format is literally a stream of bits, with a very simple +structure. This structure consists of the following concepts: + +* A "`magic number`_" that identifies the contents of the stream. + +* Encoding `primitives`_ like variable bit-rate integers. + +* `Blocks`_, which define nested content. + +* `Data Records`_, which describe entities within the file. + +* Abbreviations, which specify compression optimizations for the file. + +Note that the :doc:`llvm-bcanalyzer ` tool can be +used to dump and inspect arbitrary bitstreams, which is very useful for +understanding the encoding. + +.. _magic number: + +Magic Numbers +------------- + +The first two bytes of a bitcode file are 'BC' (``0x42``, ``0x43``). The second +two bytes are an application-specific magic number. Generic bitcode tools can +look at only the first two bytes to verify the file is bitcode, while +application-specific programs will want to look at all four. + +.. _primitives: + +Primitives +---------- + +A bitstream literally consists of a stream of bits, which are read in order +starting with the least significant bit of each byte. The stream is made up of +a number of primitive values that encode a stream of unsigned integer values. +These integers are encoded in two ways: either as `Fixed Width Integers`_ or as +`Variable Width Integers`_. + +.. _Fixed Width Integers: +.. _fixed-width value: + +Fixed Width Integers +^^^^^^^^^^^^^^^^^^^^ + +Fixed-width integer values have their low bits emitted directly to the file. +For example, a 3-bit integer value encodes 1 as 001. Fixed width integers are +used when there are a well-known number of options for a field. For example, +boolean values are usually encoded with a 1-bit wide integer. + +.. _Variable Width Integers: +.. _Variable Width Integer: +.. _variable-width value: + +Variable Width Integers +^^^^^^^^^^^^^^^^^^^^^^^ + +Variable-width integer (VBR) values encode values of arbitrary size, optimizing +for the case where the values are small. Given a 4-bit VBR field, any 3-bit +value (0 through 7) is encoded directly, with the high bit set to zero. Values +larger than N-1 bits emit their bits in a series of N-1 bit chunks, where all +but the last set the high bit. + +For example, the value 27 (0x1B) is encoded as 1011 0011 when emitted as a vbr4 +value. The first set of four bits indicates the value 3 (011) with a +continuation piece (indicated by a high bit of 1). The next word indicates a +value of 24 (011 << 3) with no continuation. The sum (3+24) yields the value +27. + +.. _char6-encoded value: + +6-bit characters +^^^^^^^^^^^^^^^^ + +6-bit characters encode common characters into a fixed 6-bit field. They +represent the following characters with the following 6-bit values: + +:: + + 'a' .. 'z' --- 0 .. 25 + 'A' .. 'Z' --- 26 .. 51 + '0' .. '9' --- 52 .. 61 + '.' --- 62 + '_' --- 63 + +This encoding is only suitable for encoding characters and strings that consist +only of the above characters. It is completely incapable of encoding characters +not in the set. + +Word Alignment +^^^^^^^^^^^^^^ + +Occasionally, it is useful to emit zero bits until the bitstream is a multiple +of 32 bits. This ensures that the bit position in the stream can be represented +as a multiple of 32-bit words. + +Abbreviation IDs +---------------- + +A bitstream is a sequential series of `Blocks`_ and `Data Records`_. Both of +these start with an abbreviation ID encoded as a fixed-bitwidth field. The +width is specified by the current block, as described below. The value of the +abbreviation ID specifies either a builtin ID (which have special meanings, +defined below) or one of the abbreviation IDs defined for the current block by +the stream itself. + +The set of builtin abbrev IDs is: + +* 0 - `END_BLOCK`_ --- This abbrev ID marks the end of the current block. + +* 1 - `ENTER_SUBBLOCK`_ --- This abbrev ID marks the beginning of a new + block. + +* 2 - `DEFINE_ABBREV`_ --- This defines a new abbreviation. + +* 3 - `UNABBREV_RECORD`_ --- This ID specifies the definition of an + unabbreviated record. + +Abbreviation IDs 4 and above are defined by the stream itself, and specify an +`abbreviated record encoding`_. + +.. _Blocks: + +Blocks +------ + +Blocks in a bitstream denote nested regions of the stream, and are identified by +a content-specific id number (for example, LLVM IR uses an ID of 12 to represent +function bodies). Block IDs 0-7 are reserved for `standard blocks`_ whose +meaning is defined by Bitcode; block IDs 8 and greater are application +specific. Nested blocks capture the hierarchical structure of the data encoded +in it, and various properties are associated with blocks as the file is parsed. +Block definitions allow the reader to efficiently skip blocks in constant time +if the reader wants a summary of blocks, or if it wants to efficiently skip data +it does not understand. The LLVM IR reader uses this mechanism to skip function +bodies, lazily reading them on demand. + +When reading and encoding the stream, several properties are maintained for the +block. In particular, each block maintains: + +#. A current abbrev id width. This value starts at 2 at the beginning of the + stream, and is set every time a block record is entered. The block entry + specifies the abbrev id width for the body of the block. + +#. A set of abbreviations. Abbreviations may be defined within a block, in + which case they are only defined in that block (neither subblocks nor + enclosing blocks see the abbreviation). Abbreviations can also be defined + inside a `BLOCKINFO`_ block, in which case they are defined in all blocks + that match the ID that the ``BLOCKINFO`` block is describing. + +As sub blocks are entered, these properties are saved and the new sub-block has +its own set of abbreviations, and its own abbrev id width. When a sub-block is +popped, the saved values are restored. + +.. _ENTER_SUBBLOCK: + +ENTER_SUBBLOCK Encoding +^^^^^^^^^^^^^^^^^^^^^^^ + +:raw-html:`` +[ENTER_SUBBLOCK, blockid\ :sub:`vbr8`, newabbrevlen\ :sub:`vbr4`, , blocklen_32] +:raw-html:`` + +The ``ENTER_SUBBLOCK`` abbreviation ID specifies the start of a new block +record. The ``blockid`` value is encoded as an 8-bit VBR identifier, and +indicates the type of block being entered, which can be a `standard block`_ or +an application-specific block. The ``newabbrevlen`` value is a 4-bit VBR, which +specifies the abbrev id width for the sub-block. The ``blocklen`` value is a +32-bit aligned value that specifies the size of the subblock in 32-bit +words. This value allows the reader to skip over the entire block in one jump. + +.. _END_BLOCK: + +END_BLOCK Encoding +^^^^^^^^^^^^^^^^^^ + +``[END_BLOCK, ]`` + +The ``END_BLOCK`` abbreviation ID specifies the end of the current block record. +Its end is aligned to 32-bits to ensure that the size of the block is an even +multiple of 32-bits. + +.. _Data Records: + +Data Records +------------ + +Data records consist of a record code and a number of (up to) 64-bit integer +values. The interpretation of the code and values is application specific and +may vary between different block types. Records can be encoded either using an +unabbrev record, or with an abbreviation. In the LLVM IR format, for example, +there is a record which encodes the target triple of a module. The code is +``MODULE_CODE_TRIPLE``, and the values of the record are the ASCII codes for the +characters in the string. + +.. _UNABBREV_RECORD: + +UNABBREV_RECORD Encoding +^^^^^^^^^^^^^^^^^^^^^^^^ + +:raw-html:`` +[UNABBREV_RECORD, code\ :sub:`vbr6`, numops\ :sub:`vbr6`, op0\ :sub:`vbr6`, op1\ :sub:`vbr6`, ...] +:raw-html:`` + +An ``UNABBREV_RECORD`` provides a default fallback encoding, which is both +completely general and extremely inefficient. It can describe an arbitrary +record by emitting the code and operands as VBRs. + +For example, emitting an LLVM IR target triple as an unabbreviated record +requires emitting the ``UNABBREV_RECORD`` abbrevid, a vbr6 for the +``MODULE_CODE_TRIPLE`` code, a vbr6 for the length of the string, which is equal +to the number of operands, and a vbr6 for each character. Because there are no +letters with values less than 32, each letter would need to be emitted as at +least a two-part VBR, which means that each letter would require at least 12 +bits. This is not an efficient encoding, but it is fully general. + +.. _abbreviated record encoding: + +Abbreviated Record Encoding +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[, fields...]`` + +An abbreviated record is a abbreviation id followed by a set of fields that are +encoded according to the `abbreviation definition`_. This allows records to be +encoded significantly more densely than records encoded with the +`UNABBREV_RECORD`_ type, and allows the abbreviation types to be specified in +the stream itself, which allows the files to be completely self describing. The +actual encoding of abbreviations is defined below. + +The record code, which is the first field of an abbreviated record, may be +encoded in the abbreviation definition (as a literal operand) or supplied in the +abbreviated record (as a Fixed or VBR operand value). + +.. _abbreviation definition: + +Abbreviations +------------- + +Abbreviations are an important form of compression for bitstreams. The idea is +to specify a dense encoding for a class of records once, then use that encoding +to emit many records. It takes space to emit the encoding into the file, but +the space is recouped (hopefully plus some) when the records that use it are +emitted. + +Abbreviations can be determined dynamically per client, per file. Because the +abbreviations are stored in the bitstream itself, different streams of the same +format can contain different sets of abbreviations according to the needs of the +specific stream. As a concrete example, LLVM IR files usually emit an +abbreviation for binary operators. If a specific LLVM module contained no or +few binary operators, the abbreviation does not need to be emitted. + +.. _DEFINE_ABBREV: + +DEFINE_ABBREV Encoding +^^^^^^^^^^^^^^^^^^^^^^ + +:raw-html:`` +[DEFINE_ABBREV, numabbrevops\ :sub:`vbr5`, abbrevop0, abbrevop1, ...] +:raw-html:`` + +A ``DEFINE_ABBREV`` record adds an abbreviation to the list of currently defined +abbreviations in the scope of this block. This definition only exists inside +this immediate block --- it is not visible in subblocks or enclosing blocks. +Abbreviations are implicitly assigned IDs sequentially starting from 4 (the +first application-defined abbreviation ID). Any abbreviations defined in a +``BLOCKINFO`` record for the particular block type receive IDs first, in order, +followed by any abbreviations defined within the block itself. Abbreviated data +records reference this ID to indicate what abbreviation they are invoking. + +An abbreviation definition consists of the ``DEFINE_ABBREV`` abbrevid followed +by a VBR that specifies the number of abbrev operands, then the abbrev operands +themselves. Abbreviation operands come in three forms. They all start with a +single bit that indicates whether the abbrev operand is a literal operand (when +the bit is 1) or an encoding operand (when the bit is 0). + +#. Literal operands --- :raw-html:`` [1\ :sub:`1`, litvalue\ + :sub:`vbr8`] :raw-html:`` --- Literal operands specify that the value in + the result is always a single specific value. This specific value is emitted + as a vbr8 after the bit indicating that it is a literal operand. + +#. Encoding info without data --- :raw-html:`` [0\ :sub:`1`, encoding\ + :sub:`3`] :raw-html:`` --- Operand encodings that do not have extra data + are just emitted as their code. + +#. Encoding info with data --- :raw-html:`` [0\ :sub:`1`, encoding\ + :sub:`3`, value\ :sub:`vbr5`] :raw-html:`` --- Operand encodings that do + have extra data are emitted as their code, followed by the extra data. + +The possible operand encodings are: + +* Fixed (code 1): The field should be emitted as a `fixed-width value`_, whose + width is specified by the operand's extra data. + +* VBR (code 2): The field should be emitted as a `variable-width value`_, whose + width is specified by the operand's extra data. + +* Array (code 3): This field is an array of values. The array operand has no + extra data, but expects another operand to follow it, indicating the element + type of the array. When reading an array in an abbreviated record, the first + integer is a vbr6 that indicates the array length, followed by the encoded + elements of the array. An array may only occur as the last operand of an + abbreviation (except for the one final operand that gives the array's + type). + +* Char6 (code 4): This field should be emitted as a `char6-encoded value`_. + This operand type takes no extra data. Char6 encoding is normally used as an + array element type. + +* Blob (code 5): This field is emitted as a vbr6, followed by padding to a + 32-bit boundary (for alignment) and an array of 8-bit objects. The array of + bytes is further followed by tail padding to ensure that its total length is a + multiple of 4 bytes. This makes it very efficient for the reader to decode + the data without having to make a copy of it: it can use a pointer to the data + in the mapped in file and poke directly at it. A blob may only occur as the + last operand of an abbreviation. + +For example, target triples in LLVM modules are encoded as a record of the form +``[TRIPLE, 'a', 'b', 'c', 'd']``. Consider if the bitstream emitted the +following abbrev entry: + +:: + + [0, Fixed, 4] + [0, Array] + [0, Char6] + +When emitting a record with this abbreviation, the above entry would be emitted +as: + +:raw-html:`
` +[4\ :sub:`abbrevwidth`, 2\ :sub:`4`, 4\ :sub:`vbr6`, 0\ :sub:`6`, 1\ :sub:`6`, 2\ :sub:`6`, 3\ :sub:`6`] +:raw-html:`
` + +These values are: + +#. The first value, 4, is the abbreviation ID for this abbreviation. + +#. The second value, 2, is the record code for ``TRIPLE`` records within LLVM IR + file ``MODULE_BLOCK`` blocks. + +#. The third value, 4, is the length of the array. + +#. The rest of the values are the char6 encoded values for ``"abcd"``. + +With this abbreviation, the triple is emitted with only 37 bits (assuming a +abbrev id width of 3). Without the abbreviation, significantly more space would +be required to emit the target triple. Also, because the ``TRIPLE`` value is +not emitted as a literal in the abbreviation, the abbreviation can also be used +for any other string value. + +.. _standard blocks: +.. _standard block: + +Standard Blocks +--------------- + +In addition to the basic block structure and record encodings, the bitstream +also defines specific built-in block types. These block types specify how the +stream is to be decoded or other metadata. In the future, new standard blocks +may be added. Block IDs 0-7 are reserved for standard blocks. + +.. _BLOCKINFO: + +#0 - BLOCKINFO Block +^^^^^^^^^^^^^^^^^^^^ + +The ``BLOCKINFO`` block allows the description of metadata for other blocks. +The currently specified records are: + +:: + + [SETBID (#1), blockid] + [DEFINE_ABBREV, ...] + [BLOCKNAME, ...name...] + [SETRECORDNAME, RecordID, ...name...] + +The ``SETBID`` record (code 1) indicates which block ID is being described. +``SETBID`` records can occur multiple times throughout the block to change which +block ID is being described. There must be a ``SETBID`` record prior to any +other records. + +Standard ``DEFINE_ABBREV`` records can occur inside ``BLOCKINFO`` blocks, but +unlike their occurrence in normal blocks, the abbreviation is defined for blocks +matching the block ID we are describing, *not* the ``BLOCKINFO`` block +itself. The abbreviations defined in ``BLOCKINFO`` blocks receive abbreviation +IDs as described in `DEFINE_ABBREV`_. + +The ``BLOCKNAME`` record (code 2) can optionally occur in this block. The +elements of the record are the bytes of the string name of the block. +llvm-bcanalyzer can use this to dump out bitcode files symbolically. + +The ``SETRECORDNAME`` record (code 3) can also optionally occur in this block. +The first operand value is a record ID number, and the rest of the elements of +the record are the bytes for the string name of the record. llvm-bcanalyzer can +use this to dump out bitcode files symbolically. + +Note that although the data in ``BLOCKINFO`` blocks is described as "metadata," +the abbreviations they contain are essential for parsing records from the +corresponding blocks. It is not safe to skip them. + +.. _wrapper: + +Bitcode Wrapper Format +====================== + +Bitcode files for LLVM IR may optionally be wrapped in a simple wrapper +structure. This structure contains a simple header that indicates the offset +and size of the embedded BC file. This allows additional information to be +stored alongside the BC file. The structure of this file header is: + +:raw-html:`
` +[Magic\ :sub:`32`, Version\ :sub:`32`, Offset\ :sub:`32`, Size\ :sub:`32`, CPUType\ :sub:`32`] +:raw-html:`
` + +Each of the fields are 32-bit fields stored in little endian form (as with the +rest of the bitcode file fields). The Magic number is always ``0x0B17C0DE`` and +the version is currently always ``0``. The Offset field is the offset in bytes +to the start of the bitcode stream in the file, and the Size field is the size +in bytes of the stream. CPUType is a target-specific value that can be used to +encode the CPU of the target. + +.. _encoding of LLVM IR: + +LLVM IR Encoding +================ + +LLVM IR is encoded into a bitstream by defining blocks and records. It uses +blocks for things like constant pools, functions, symbol tables, etc. It uses +records for things like instructions, global variable descriptors, type +descriptions, etc. This document does not describe the set of abbreviations +that the writer uses, as these are fully self-described in the file, and the +reader is not allowed to build in any knowledge of this. + +Basics +------ + +LLVM IR Magic Number +^^^^^^^^^^^^^^^^^^^^ + +The magic number for LLVM IR files is: + +:raw-html:`
` +[0x0\ :sub:`4`, 0xC\ :sub:`4`, 0xE\ :sub:`4`, 0xD\ :sub:`4`] +:raw-html:`
` + +When combined with the bitcode magic number and viewed as bytes, this is +``"BC 0xC0DE"``. + +.. _Signed VBRs: + +Signed VBRs +^^^^^^^^^^^ + +`Variable Width Integer`_ encoding is an efficient way to encode arbitrary sized +unsigned values, but is an extremely inefficient for encoding signed values, as +signed values are otherwise treated as maximally large unsigned values. + +As such, signed VBR values of a specific width are emitted as follows: + +* Positive values are emitted as VBRs of the specified width, but with their + value shifted left by one. + +* Negative values are emitted as VBRs of the specified width, but the negated + value is shifted left by one, and the low bit is set. + +With this encoding, small positive and small negative values can both be emitted +efficiently. Signed VBR encoding is used in ``CST_CODE_INTEGER`` and +``CST_CODE_WIDE_INTEGER`` records within ``CONSTANTS_BLOCK`` blocks. +It is also used for phi instruction operands in `MODULE_CODE_VERSION`_ 1. + +LLVM IR Blocks +^^^^^^^^^^^^^^ + +LLVM IR is defined with the following blocks: + +* 8 --- `MODULE_BLOCK`_ --- This is the top-level block that contains the entire + module, and describes a variety of per-module information. + +* 9 --- `PARAMATTR_BLOCK`_ --- This enumerates the parameter attributes. + +* 10 --- `TYPE_BLOCK`_ --- This describes all of the types in the module. + +* 11 --- `CONSTANTS_BLOCK`_ --- This describes constants for a module or + function. + +* 12 --- `FUNCTION_BLOCK`_ --- This describes a function body. + +* 13 --- `TYPE_SYMTAB_BLOCK`_ --- This describes the type symbol table. + +* 14 --- `VALUE_SYMTAB_BLOCK`_ --- This describes a value symbol table. + +* 15 --- `METADATA_BLOCK`_ --- This describes metadata items. + +* 16 --- `METADATA_ATTACHMENT`_ --- This contains records associating metadata + with function instruction values. + +.. _MODULE_BLOCK: + +MODULE_BLOCK Contents +--------------------- + +The ``MODULE_BLOCK`` block (id 8) is the top-level block for LLVM bitcode files, +and each bitcode file must contain exactly one. In addition to records +(described below) containing information about the module, a ``MODULE_BLOCK`` +block may contain the following sub-blocks: + +* `BLOCKINFO`_ +* `PARAMATTR_BLOCK`_ +* `TYPE_BLOCK`_ +* `TYPE_SYMTAB_BLOCK`_ +* `VALUE_SYMTAB_BLOCK`_ +* `CONSTANTS_BLOCK`_ +* `FUNCTION_BLOCK`_ +* `METADATA_BLOCK`_ + +.. _MODULE_CODE_VERSION: + +MODULE_CODE_VERSION Record +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[VERSION, version#]`` + +The ``VERSION`` record (code 1) contains a single value indicating the format +version. Versions 0 and 1 are supported at this time. The difference between +version 0 and 1 is in the encoding of instruction operands in +each `FUNCTION_BLOCK`_. + +In version 0, each value defined by an instruction is assigned an ID +unique to the function. Function-level value IDs are assigned starting from +``NumModuleValues`` since they share the same namespace as module-level +values. The value enumerator resets after each function. When a value is +an operand of an instruction, the value ID is used to represent the operand. +For large functions or large modules, these operand values can be large. + +The encoding in version 1 attempts to avoid large operand values +in common cases. Instead of using the value ID directly, operands are +encoded as relative to the current instruction. Thus, if an operand +is the value defined by the previous instruction, the operand +will be encoded as 1. + +For example, instead of + +.. code-block:: llvm + + #n = load #n-1 + #n+1 = icmp eq #n, #const0 + br #n+1, label #(bb1), label #(bb2) + +version 1 will encode the instructions as + +.. code-block:: llvm + + #n = load #1 + #n+1 = icmp eq #1, (#n+1)-#const0 + br #1, label #(bb1), label #(bb2) + +Note in the example that operands which are constants also use +the relative encoding, while operands like basic block labels +do not use the relative encoding. + +Forward references will result in a negative value. +This can be inefficient, as operands are normally encoded +as unsigned VBRs. However, forward references are rare, except in the +case of phi instructions. For phi instructions, operands are encoded as +`Signed VBRs`_ to deal with forward references. + + +MODULE_CODE_TRIPLE Record +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[TRIPLE, ...string...]`` + +The ``TRIPLE`` record (code 2) contains a variable number of values representing +the bytes of the ``target triple`` specification string. + +MODULE_CODE_DATALAYOUT Record +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[DATALAYOUT, ...string...]`` + +The ``DATALAYOUT`` record (code 3) contains a variable number of values +representing the bytes of the ``target datalayout`` specification string. + +MODULE_CODE_ASM Record +^^^^^^^^^^^^^^^^^^^^^^ + +``[ASM, ...string...]`` + +The ``ASM`` record (code 4) contains a variable number of values representing +the bytes of ``module asm`` strings, with individual assembly blocks separated +by newline (ASCII 10) characters. + +.. _MODULE_CODE_SECTIONNAME: + +MODULE_CODE_SECTIONNAME Record +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[SECTIONNAME, ...string...]`` + +The ``SECTIONNAME`` record (code 5) contains a variable number of values +representing the bytes of a single section name string. There should be one +``SECTIONNAME`` record for each section name referenced (e.g., in global +variable or function ``section`` attributes) within the module. These records +can be referenced by the 1-based index in the *section* fields of ``GLOBALVAR`` +or ``FUNCTION`` records. + +MODULE_CODE_DEPLIB Record +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[DEPLIB, ...string...]`` + +The ``DEPLIB`` record (code 6) contains a variable number of values representing +the bytes of a single dependent library name string, one of the libraries +mentioned in a ``deplibs`` declaration. There should be one ``DEPLIB`` record +for each library name referenced. + +MODULE_CODE_GLOBALVAR Record +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[GLOBALVAR, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr]`` + +The ``GLOBALVAR`` record (code 7) marks the declaration or definition of a +global variable. The operand fields are: + +* *pointer type*: The type index of the pointer type used to point to this + global variable + +* *isconst*: Non-zero if the variable is treated as constant within the module, + or zero if it is not + +* *initid*: If non-zero, the value index of the initializer for this variable, + plus 1. + +.. _linkage type: + +* *linkage*: An encoding of the linkage type for this variable: + * ``external``: code 0 + * ``weak``: code 1 + * ``appending``: code 2 + * ``internal``: code 3 + * ``linkonce``: code 4 + * ``dllimport``: code 5 + * ``dllexport``: code 6 + * ``extern_weak``: code 7 + * ``common``: code 8 + * ``private``: code 9 + * ``weak_odr``: code 10 + * ``linkonce_odr``: code 11 + * ``available_externally``: code 12 + * ``linker_private``: code 13 + +* alignment*: The logarithm base 2 of the variable's requested alignment, plus 1 + +* *section*: If non-zero, the 1-based section index in the table of + `MODULE_CODE_SECTIONNAME`_ entries. + +.. _visibility: + +* *visibility*: If present, an encoding of the visibility of this variable: + * ``default``: code 0 + * ``hidden``: code 1 + * ``protected``: code 2 + +* *threadlocal*: If present, an encoding of the thread local storage mode of the + variable: + * ``not thread local``: code 0 + * ``thread local; default TLS model``: code 1 + * ``localdynamic``: code 2 + * ``initialexec``: code 3 + * ``localexec``: code 4 + +* *unnamed_addr*: If present and non-zero, indicates that the variable has + ``unnamed_addr`` + +.. _FUNCTION: + +MODULE_CODE_FUNCTION Record +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix]`` + +The ``FUNCTION`` record (code 8) marks the declaration or definition of a +function. The operand fields are: + +* *type*: The type index of the function type describing this function + +* *callingconv*: The calling convention number: + * ``ccc``: code 0 + * ``fastcc``: code 8 + * ``coldcc``: code 9 + * ``x86_stdcallcc``: code 64 + * ``x86_fastcallcc``: code 65 + * ``arm_apcscc``: code 66 + * ``arm_aapcscc``: code 67 + * ``arm_aapcs_vfpcc``: code 68 + +* isproto*: Non-zero if this entry represents a declaration rather than a + definition + +* *linkage*: An encoding of the `linkage type`_ for this function + +* *paramattr*: If nonzero, the 1-based parameter attribute index into the table + of `PARAMATTR_CODE_ENTRY`_ entries. + +* *alignment*: The logarithm base 2 of the function's requested alignment, plus + 1 + +* *section*: If non-zero, the 1-based section index in the table of + `MODULE_CODE_SECTIONNAME`_ entries. + +* *visibility*: An encoding of the `visibility`_ of this function + +* *gc*: If present and nonzero, the 1-based garbage collector index in the table + of `MODULE_CODE_GCNAME`_ entries. + +* *unnamed_addr*: If present and non-zero, indicates that the function has + ``unnamed_addr`` + +* *prefix*: If non-zero, the value index of the prefix data for this function, + plus 1. + +MODULE_CODE_ALIAS Record +^^^^^^^^^^^^^^^^^^^^^^^^ + +``[ALIAS, alias type, aliasee val#, linkage, visibility]`` + +The ``ALIAS`` record (code 9) marks the definition of an alias. The operand +fields are + +* *alias type*: The type index of the alias + +* *aliasee val#*: The value index of the aliased value + +* *linkage*: An encoding of the `linkage type`_ for this alias + +* *visibility*: If present, an encoding of the `visibility`_ of the alias + +MODULE_CODE_PURGEVALS Record +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[PURGEVALS, numvals]`` + +The ``PURGEVALS`` record (code 10) resets the module-level value list to the +size given by the single operand value. Module-level value list items are added +by ``GLOBALVAR``, ``FUNCTION``, and ``ALIAS`` records. After a ``PURGEVALS`` +record is seen, new value indices will start from the given *numvals* value. + +.. _MODULE_CODE_GCNAME: + +MODULE_CODE_GCNAME Record +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[GCNAME, ...string...]`` + +The ``GCNAME`` record (code 11) contains a variable number of values +representing the bytes of a single garbage collector name string. There should +be one ``GCNAME`` record for each garbage collector name referenced in function +``gc`` attributes within the module. These records can be referenced by 1-based +index in the *gc* fields of ``FUNCTION`` records. + +.. _PARAMATTR_BLOCK: + +PARAMATTR_BLOCK Contents +------------------------ + +The ``PARAMATTR_BLOCK`` block (id 9) contains a table of entries describing the +attributes of function parameters. These entries are referenced by 1-based index +in the *paramattr* field of module block `FUNCTION`_ records, or within the +*attr* field of function block ``INST_INVOKE`` and ``INST_CALL`` records. + +Entries within ``PARAMATTR_BLOCK`` are constructed to ensure that each is unique +(i.e., no two indicies represent equivalent attribute lists). + +.. _PARAMATTR_CODE_ENTRY: + +PARAMATTR_CODE_ENTRY Record +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[ENTRY, paramidx0, attr0, paramidx1, attr1...]`` + +The ``ENTRY`` record (code 1) contains an even number of values describing a +unique set of function parameter attributes. Each *paramidx* value indicates +which set of attributes is represented, with 0 representing the return value +attributes, 0xFFFFFFFF representing function attributes, and other values +representing 1-based function parameters. Each *attr* value is a bitmap with the +following interpretation: + +* bit 0: ``zeroext`` +* bit 1: ``signext`` +* bit 2: ``noreturn`` +* bit 3: ``inreg`` +* bit 4: ``sret`` +* bit 5: ``nounwind`` +* bit 6: ``noalias`` +* bit 7: ``byval`` +* bit 8: ``nest`` +* bit 9: ``readnone`` +* bit 10: ``readonly`` +* bit 11: ``noinline`` +* bit 12: ``alwaysinline`` +* bit 13: ``optsize`` +* bit 14: ``ssp`` +* bit 15: ``sspreq`` +* bits 16-31: ``align n`` +* bit 32: ``nocapture`` +* bit 33: ``noredzone`` +* bit 34: ``noimplicitfloat`` +* bit 35: ``naked`` +* bit 36: ``inlinehint`` +* bits 37-39: ``alignstack n``, represented as the logarithm + base 2 of the requested alignment, plus 1 + +.. _TYPE_BLOCK: + +TYPE_BLOCK Contents +------------------- + +The ``TYPE_BLOCK`` block (id 10) contains records which constitute a table of +type operator entries used to represent types referenced within an LLVM +module. Each record (with the exception of `NUMENTRY`_) generates a single type +table entry, which may be referenced by 0-based index from instructions, +constants, metadata, type symbol table entries, or other type operator records. + +Entries within ``TYPE_BLOCK`` are constructed to ensure that each entry is +unique (i.e., no two indicies represent structurally equivalent types). + +.. _TYPE_CODE_NUMENTRY: +.. _NUMENTRY: + +TYPE_CODE_NUMENTRY Record +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[NUMENTRY, numentries]`` + +The ``NUMENTRY`` record (code 1) contains a single value which indicates the +total number of type code entries in the type table of the module. If present, +``NUMENTRY`` should be the first record in the block. + +TYPE_CODE_VOID Record +^^^^^^^^^^^^^^^^^^^^^ + +``[VOID]`` + +The ``VOID`` record (code 2) adds a ``void`` type to the type table. + +TYPE_CODE_HALF Record +^^^^^^^^^^^^^^^^^^^^^ + +``[HALF]`` + +The ``HALF`` record (code 10) adds a ``half`` (16-bit floating point) type to +the type table. + +TYPE_CODE_FLOAT Record +^^^^^^^^^^^^^^^^^^^^^^ + +``[FLOAT]`` + +The ``FLOAT`` record (code 3) adds a ``float`` (32-bit floating point) type to +the type table. + +TYPE_CODE_DOUBLE Record +^^^^^^^^^^^^^^^^^^^^^^^ + +``[DOUBLE]`` + +The ``DOUBLE`` record (code 4) adds a ``double`` (64-bit floating point) type to +the type table. + +TYPE_CODE_LABEL Record +^^^^^^^^^^^^^^^^^^^^^^ + +``[LABEL]`` + +The ``LABEL`` record (code 5) adds a ``label`` type to the type table. + +TYPE_CODE_OPAQUE Record +^^^^^^^^^^^^^^^^^^^^^^^ + +``[OPAQUE]`` + +The ``OPAQUE`` record (code 6) adds an ``opaque`` type to the type table. Note +that distinct ``opaque`` types are not unified. + +TYPE_CODE_INTEGER Record +^^^^^^^^^^^^^^^^^^^^^^^^ + +``[INTEGER, width]`` + +The ``INTEGER`` record (code 7) adds an integer type to the type table. The +single *width* field indicates the width of the integer type. + +TYPE_CODE_POINTER Record +^^^^^^^^^^^^^^^^^^^^^^^^ + +``[POINTER, pointee type, address space]`` + +The ``POINTER`` record (code 8) adds a pointer type to the type table. The +operand fields are + +* *pointee type*: The type index of the pointed-to type + +* *address space*: If supplied, the target-specific numbered address space where + the pointed-to object resides. Otherwise, the default address space is zero. + +TYPE_CODE_FUNCTION Record +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[FUNCTION, vararg, ignored, retty, ...paramty... ]`` + +The ``FUNCTION`` record (code 9) adds a function type to the type table. The +operand fields are + +* *vararg*: Non-zero if the type represents a varargs function + +* *ignored*: This value field is present for backward compatibility only, and is + ignored + +* *retty*: The type index of the function's return type + +* *paramty*: Zero or more type indices representing the parameter types of the + function + +TYPE_CODE_STRUCT Record +^^^^^^^^^^^^^^^^^^^^^^^ + +``[STRUCT, ispacked, ...eltty...]`` + +The ``STRUCT`` record (code 10) adds a struct type to the type table. The +operand fields are + +* *ispacked*: Non-zero if the type represents a packed structure + +* *eltty*: Zero or more type indices representing the element types of the + structure + +TYPE_CODE_ARRAY Record +^^^^^^^^^^^^^^^^^^^^^^ + +``[ARRAY, numelts, eltty]`` + +The ``ARRAY`` record (code 11) adds an array type to the type table. The +operand fields are + +* *numelts*: The number of elements in arrays of this type + +* *eltty*: The type index of the array element type + +TYPE_CODE_VECTOR Record +^^^^^^^^^^^^^^^^^^^^^^^ + +``[VECTOR, numelts, eltty]`` + +The ``VECTOR`` record (code 12) adds a vector type to the type table. The +operand fields are + +* *numelts*: The number of elements in vectors of this type + +* *eltty*: The type index of the vector element type + +TYPE_CODE_X86_FP80 Record +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[X86_FP80]`` + +The ``X86_FP80`` record (code 13) adds an ``x86_fp80`` (80-bit floating point) +type to the type table. + +TYPE_CODE_FP128 Record +^^^^^^^^^^^^^^^^^^^^^^ + +``[FP128]`` + +The ``FP128`` record (code 14) adds an ``fp128`` (128-bit floating point) type +to the type table. + +TYPE_CODE_PPC_FP128 Record +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[PPC_FP128]`` + +The ``PPC_FP128`` record (code 15) adds a ``ppc_fp128`` (128-bit floating point) +type to the type table. + +TYPE_CODE_METADATA Record +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[METADATA]`` + +The ``METADATA`` record (code 16) adds a ``metadata`` type to the type table. + +.. _CONSTANTS_BLOCK: + +CONSTANTS_BLOCK Contents +------------------------ + +The ``CONSTANTS_BLOCK`` block (id 11) ... + +.. _FUNCTION_BLOCK: + +FUNCTION_BLOCK Contents +----------------------- + +The ``FUNCTION_BLOCK`` block (id 12) ... + +In addition to the record types described below, a ``FUNCTION_BLOCK`` block may +contain the following sub-blocks: + +* `CONSTANTS_BLOCK`_ +* `VALUE_SYMTAB_BLOCK`_ +* `METADATA_ATTACHMENT`_ + +.. _TYPE_SYMTAB_BLOCK: + +TYPE_SYMTAB_BLOCK Contents +-------------------------- + +The ``TYPE_SYMTAB_BLOCK`` block (id 13) contains entries which map between +module-level named types and their corresponding type indices. + +.. _TST_CODE_ENTRY: + +TST_CODE_ENTRY Record +^^^^^^^^^^^^^^^^^^^^^ + +``[ENTRY, typeid, ...string...]`` + +The ``ENTRY`` record (code 1) contains a variable number of values, with the +first giving the type index of the designated type, and the remaining values +giving the character codes of the type name. Each entry corresponds to a single +named type. + +.. _VALUE_SYMTAB_BLOCK: + +VALUE_SYMTAB_BLOCK Contents +--------------------------- + +The ``VALUE_SYMTAB_BLOCK`` block (id 14) ... + +.. _METADATA_BLOCK: + +METADATA_BLOCK Contents +----------------------- + +The ``METADATA_BLOCK`` block (id 15) ... + +.. _METADATA_ATTACHMENT: + +METADATA_ATTACHMENT Contents +---------------------------- + +The ``METADATA_ATTACHMENT`` block (id 16) ... diff --git a/docs/BranchWeightMetadata.rst b/docs/BranchWeightMetadata.rst new file mode 100644 index 00000000..71ecd34c --- /dev/null +++ b/docs/BranchWeightMetadata.rst @@ -0,0 +1,116 @@ +=========================== +LLVM Branch Weight Metadata +=========================== + +.. contents:: + :local: + +Introduction +============ + +Branch Weight Metadata represents branch weights as its likeliness to be +taken. Metadata is assigned to the ``TerminatorInst`` as a ``MDNode`` of the +``MD_prof`` kind. The first operator is always a ``MDString`` node with the +string "branch_weights". Number of operators depends on the terminator type. + +Branch weights might be fetch from the profiling file, or generated based on +`__builtin_expect`_ instruction. + +All weights are represented as an unsigned 32-bit values, where higher value +indicates greater chance to be taken. + +Supported Instructions +====================== + +``BranchInst`` +^^^^^^^^^^^^^^ + +Metadata is only assigned to the conditional branches. There are two extra +operarands for the true and the false branch. + +.. code-block:: llvm + + !0 = metadata !{ + metadata !"branch_weights", + i32 , + i32 + } + +``SwitchInst`` +^^^^^^^^^^^^^^ + +Branch weights are assigned to every case (including the ``default`` case which +is always case #0). + +.. code-block:: llvm + + !0 = metadata !{ + metadata !"branch_weights", + i32 + [ , i32 ... ] + } + +``IndirectBrInst`` +^^^^^^^^^^^^^^^^^^ + +Branch weights are assigned to every destination. + +.. code-block:: llvm + + !0 = metadata !{ + metadata !"branch_weights", + i32 + [ , i32 ... ] + } + +Other +^^^^^ + +Other terminator instructions are not allowed to contain Branch Weight Metadata. + +.. _\__builtin_expect: + +Built-in ``expect`` Instructions +================================ + +``__builtin_expect(long exp, long c)`` instruction provides branch prediction +information. The return value is the value of ``exp``. + +It is especially useful in conditional statements. Currently Clang supports two +conditional statements: + +``if`` statement +^^^^^^^^^^^^^^^^ + +The ``exp`` parameter is the condition. The ``c`` parameter is the expected +comparison value. If it is equal to 1 (true), the condition is likely to be +true, in other case condition is likely to be false. For example: + +.. code-block:: c++ + + if (__builtin_expect(x > 0, 1)) { + // This block is likely to be taken. + } + +``switch`` statement +^^^^^^^^^^^^^^^^^^^^ + +The ``exp`` parameter is the value. The ``c`` parameter is the expected +value. If the expected value doesn't show on the cases list, the ``default`` +case is assumed to be likely taken. + +.. code-block:: c++ + + switch (__builtin_expect(x, 5)) { + default: break; + case 0: // ... + case 3: // ... + case 5: // This case is likely to be taken. + } + +CFG Modifications +================= + +Branch Weight Metatada is not proof against CFG changes. If terminator operands' +are changed some action should be taken. In other case some misoptimizations may +occur due to incorrent branch prediction information. diff --git a/docs/Bugpoint.rst b/docs/Bugpoint.rst new file mode 100644 index 00000000..1a5fc8c0 --- /dev/null +++ b/docs/Bugpoint.rst @@ -0,0 +1,216 @@ +==================================== +LLVM bugpoint tool: design and usage +==================================== + +.. contents:: + :local: + +Description +=========== + +``bugpoint`` narrows down the source of problems in LLVM tools and passes. It +can be used to debug three types of failures: optimizer crashes, miscompilations +by optimizers, or bad native code generation (including problems in the static +and JIT compilers). It aims to reduce large test cases to small, useful ones. +For example, if ``opt`` crashes while optimizing a file, it will identify the +optimization (or combination of optimizations) that causes the crash, and reduce +the file down to a small example which triggers the crash. + +For detailed case scenarios, such as debugging ``opt``, or one of the LLVM code +generators, see `How To Submit a Bug Report document `_. + +Design Philosophy +================= + +``bugpoint`` is designed to be a useful tool without requiring any hooks into +the LLVM infrastructure at all. It works with any and all LLVM passes and code +generators, and does not need to "know" how they work. Because of this, it may +appear to do stupid things or miss obvious simplifications. ``bugpoint`` is +also designed to trade off programmer time for computer time in the +compiler-debugging process; consequently, it may take a long period of +(unattended) time to reduce a test case, but we feel it is still worth it. Note +that ``bugpoint`` is generally very quick unless debugging a miscompilation +where each test of the program (which requires executing it) takes a long time. + +Automatic Debugger Selection +---------------------------- + +``bugpoint`` reads each ``.bc`` or ``.ll`` file specified on the command line +and links them together into a single module, called the test program. If any +LLVM passes are specified on the command line, it runs these passes on the test +program. If any of the passes crash, or if they produce malformed output (which +causes the verifier to abort), ``bugpoint`` starts the `crash debugger`_. + +Otherwise, if the ``-output`` option was not specified, ``bugpoint`` runs the +test program with the "safe" backend (which is assumed to generate good code) to +generate a reference output. Once ``bugpoint`` has a reference output for the +test program, it tries executing it with the selected code generator. If the +selected code generator crashes, ``bugpoint`` starts the `crash debugger`_ on +the code generator. Otherwise, if the resulting output differs from the +reference output, it assumes the difference resulted from a code generator +failure, and starts the `code generator debugger`_. + +Finally, if the output of the selected code generator matches the reference +output, ``bugpoint`` runs the test program after all of the LLVM passes have +been applied to it. If its output differs from the reference output, it assumes +the difference resulted from a failure in one of the LLVM passes, and enters the +`miscompilation debugger`_. Otherwise, there is no problem ``bugpoint`` can +debug. + +.. _crash debugger: + +Crash debugger +-------------- + +If an optimizer or code generator crashes, ``bugpoint`` will try as hard as it +can to reduce the list of passes (for optimizer crashes) and the size of the +test program. First, ``bugpoint`` figures out which combination of optimizer +passes triggers the bug. This is useful when debugging a problem exposed by +``opt``, for example, because it runs over 38 passes. + +Next, ``bugpoint`` tries removing functions from the test program, to reduce its +size. Usually it is able to reduce a test program to a single function, when +debugging intraprocedural optimizations. Once the number of functions has been +reduced, it attempts to delete various edges in the control flow graph, to +reduce the size of the function as much as possible. Finally, ``bugpoint`` +deletes any individual LLVM instructions whose absence does not eliminate the +failure. At the end, ``bugpoint`` should tell you what passes crash, give you a +bitcode file, and give you instructions on how to reproduce the failure with +``opt`` or ``llc``. + +.. _code generator debugger: + +Code generator debugger +----------------------- + +The code generator debugger attempts to narrow down the amount of code that is +being miscompiled by the selected code generator. To do this, it takes the test +program and partitions it into two pieces: one piece which it compiles with the +"safe" backend (into a shared object), and one piece which it runs with either +the JIT or the static LLC compiler. It uses several techniques to reduce the +amount of code pushed through the LLVM code generator, to reduce the potential +scope of the problem. After it is finished, it emits two bitcode files (called +"test" [to be compiled with the code generator] and "safe" [to be compiled with +the "safe" backend], respectively), and instructions for reproducing the +problem. The code generator debugger assumes that the "safe" backend produces +good code. + +.. _miscompilation debugger: + +Miscompilation debugger +----------------------- + +The miscompilation debugger works similarly to the code generator debugger. It +works by splitting the test program into two pieces, running the optimizations +specified on one piece, linking the two pieces back together, and then executing +the result. It attempts to narrow down the list of passes to the one (or few) +which are causing the miscompilation, then reduce the portion of the test +program which is being miscompiled. The miscompilation debugger assumes that +the selected code generator is working properly. + +Advice for using bugpoint +========================= + +``bugpoint`` can be a remarkably useful tool, but it sometimes works in +non-obvious ways. Here are some hints and tips: + +* In the code generator and miscompilation debuggers, ``bugpoint`` only works + with programs that have deterministic output. Thus, if the program outputs + ``argv[0]``, the date, time, or any other "random" data, ``bugpoint`` may + misinterpret differences in these data, when output, as the result of a + miscompilation. Programs should be temporarily modified to disable outputs + that are likely to vary from run to run. + +* In the code generator and miscompilation debuggers, debugging will go faster + if you manually modify the program or its inputs to reduce the runtime, but + still exhibit the problem. + +* ``bugpoint`` is extremely useful when working on a new optimization: it helps + track down regressions quickly. To avoid having to relink ``bugpoint`` every + time you change your optimization however, have ``bugpoint`` dynamically load + your optimization with the ``-load`` option. + +* ``bugpoint`` can generate a lot of output and run for a long period of time. + It is often useful to capture the output of the program to file. For example, + in the C shell, you can run: + + .. code-block:: console + + $ bugpoint ... |& tee bugpoint.log + + to get a copy of ``bugpoint``'s output in the file ``bugpoint.log``, as well + as on your terminal. + +* ``bugpoint`` cannot debug problems with the LLVM linker. If ``bugpoint`` + crashes before you see its "All input ok" message, you might try ``llvm-link + -v`` on the same set of input files. If that also crashes, you may be + experiencing a linker bug. + +* ``bugpoint`` is useful for proactively finding bugs in LLVM. Invoking + ``bugpoint`` with the ``-find-bugs`` option will cause the list of specified + optimizations to be randomized and applied to the program. This process will + repeat until a bug is found or the user kills ``bugpoint``. + +What to do when bugpoint isn't enough +===================================== + +Sometimes, ``bugpoint`` is not enough. In particular, InstCombine and +TargetLowering both have visitor structured code with lots of potential +transformations. If the process of using bugpoint has left you with still too +much code to figure out and the problem seems to be in instcombine, the +following steps may help. These same techniques are useful with TargetLowering +as well. + +Turn on ``-debug-only=instcombine`` and see which transformations within +instcombine are firing by selecting out lines with "``IC``" in them. + +At this point, you have a decision to make. Is the number of transformations +small enough to step through them using a debugger? If so, then try that. + +If there are too many transformations, then a source modification approach may +be helpful. In this approach, you can modify the source code of instcombine to +disable just those transformations that are being performed on your test input +and perform a binary search over the set of transformations. One set of places +to modify are the "``visit*``" methods of ``InstCombiner`` (*e.g.* +``visitICmpInst``) by adding a "``return false``" as the first line of the +method. + +If that still doesn't remove enough, then change the caller of +``InstCombiner::DoOneIteration``, ``InstCombiner::runOnFunction`` to limit the +number of iterations. + +You may also find it useful to use "``-stats``" now to see what parts of +instcombine are firing. This can guide where to put additional reporting code. + +At this point, if the amount of transformations is still too large, then +inserting code to limit whether or not to execute the body of the code in the +visit function can be helpful. Add a static counter which is incremented on +every invocation of the function. Then add code which simply returns false on +desired ranges. For example: + +.. code-block:: c++ + + + static int calledCount = 0; + calledCount++; + DEBUG(if (calledCount < 212) return false); + DEBUG(if (calledCount > 217) return false); + DEBUG(if (calledCount == 213) return false); + DEBUG(if (calledCount == 214) return false); + DEBUG(if (calledCount == 215) return false); + DEBUG(if (calledCount == 216) return false); + DEBUG(dbgs() << "visitXOR calledCount: " << calledCount << "\n"); + DEBUG(dbgs() << "I: "; I->dump()); + +could be added to ``visitXOR`` to limit ``visitXor`` to being applied only to +calls 212 and 217. This is from an actual test case and raises an important +point---a simple binary search may not be sufficient, as transformations that +interact may require isolating more than one call. In TargetLowering, use +``return SDNode();`` instead of ``return false;``. + +Now that that the number of transformations is down to a manageable number, try +examining the output to see if you can figure out which transformations are +being done. If that can be figured out, then do the usual debugging. If which +code corresponds to the transformation being performed isn't obvious, set a +breakpoint after the call count based disabling and step through the code. +Alternatively, you can use "``printf``" style debugging to report waypoints. diff --git a/docs/CMake.rst b/docs/CMake.rst new file mode 100644 index 00000000..c9fe538c --- /dev/null +++ b/docs/CMake.rst @@ -0,0 +1,426 @@ +======================== +Building LLVM with CMake +======================== + +.. contents:: + :local: + +Introduction +============ + +`CMake `_ is a cross-platform build-generator tool. CMake +does not build the project, it generates the files needed by your build tool +(GNU make, Visual Studio, etc) for building LLVM. + +If you are really anxious about getting a functional LLVM build, go to the +`Quick start`_ section. If you are a CMake novice, start on `Basic CMake usage`_ +and then go back to the `Quick start`_ once you know what you are doing. The +`Options and variables`_ section is a reference for customizing your build. If +you already have experience with CMake, this is the recommended starting point. + +.. _Quick start: + +Quick start +=========== + +We use here the command-line, non-interactive CMake interface. + +#. `Download `_ and install + CMake. Version 2.8 is the minimum required. + +#. Open a shell. Your development tools must be reachable from this shell + through the PATH environment variable. + +#. Create a directory for containing the build. It is not supported to build + LLVM on the source directory. cd to this directory: + + .. code-block:: console + + $ mkdir mybuilddir + $ cd mybuilddir + +#. Execute this command on the shell replacing `path/to/llvm/source/root` with + the path to the root of your LLVM source tree: + + .. code-block:: console + + $ cmake path/to/llvm/source/root + + CMake will detect your development environment, perform a series of test and + generate the files required for building LLVM. CMake will use default values + for all build parameters. See the `Options and variables`_ section for + fine-tuning your build + + This can fail if CMake can't detect your toolset, or if it thinks that the + environment is not sane enough. On this case make sure that the toolset that + you intend to use is the only one reachable from the shell and that the shell + itself is the correct one for you development environment. CMake will refuse + to build MinGW makefiles if you have a POSIX shell reachable through the PATH + environment variable, for instance. You can force CMake to use a given build + tool, see the `Usage`_ section. + +.. _Basic CMake usage: +.. _Usage: + +Basic CMake usage +================= + +This section explains basic aspects of CMake, mostly for explaining those +options which you may need on your day-to-day usage. + +CMake comes with extensive documentation in the form of html files and on the +cmake executable itself. Execute ``cmake --help`` for further help options. + +CMake requires to know for which build tool it shall generate files (GNU make, +Visual Studio, Xcode, etc). If not specified on the command line, it tries to +guess it based on you environment. Once identified the build tool, CMake uses +the corresponding *Generator* for creating files for your build tool. You can +explicitly specify the generator with the command line option ``-G "Name of the +generator"``. For knowing the available generators on your platform, execute + +.. code-block:: console + + $ cmake --help + +This will list the generator's names at the end of the help text. Generator's +names are case-sensitive. Example: + +.. code-block:: console + + $ cmake -G "Visual Studio 10" path/to/llvm/source/root + +For a given development platform there can be more than one adequate +generator. If you use Visual Studio "NMake Makefiles" is a generator you can use +for building with NMake. By default, CMake chooses the more specific generator +supported by your development environment. If you want an alternative generator, +you must tell this to CMake with the ``-G`` option. + +.. todo:: + + Explain variables and cache. Move explanation here from #options section. + +.. _Options and variables: + +Options and variables +===================== + +Variables customize how the build will be generated. Options are boolean +variables, with possible values ON/OFF. Options and variables are defined on the +CMake command line like this: + +.. code-block:: console + + $ cmake -DVARIABLE=value path/to/llvm/source + +You can set a variable after the initial CMake invocation for changing its +value. You can also undefine a variable: + +.. code-block:: console + + $ cmake -UVARIABLE path/to/llvm/source + +Variables are stored on the CMake cache. This is a file named ``CMakeCache.txt`` +on the root of the build directory. Do not hand-edit it. + +Variables are listed here appending its type after a colon. It is correct to +write the variable and the type on the CMake command line: + +.. code-block:: console + + $ cmake -DVARIABLE:TYPE=value path/to/llvm/source + +Frequently-used CMake variables +------------------------------- + +Here are listed some of the CMake variables that are used often, along with a +brief explanation and LLVM-specific notes. For full documentation, check the +CMake docs or execute ``cmake --help-variable VARIABLE_NAME``. + +**CMAKE_BUILD_TYPE**:STRING + Sets the build type for ``make`` based generators. Possible values are + Release, Debug, RelWithDebInfo and MinSizeRel. On systems like Visual Studio + the user sets the build type with the IDE settings. + +**CMAKE_INSTALL_PREFIX**:PATH + Path where LLVM will be installed if "make install" is invoked or the + "INSTALL" target is built. + +**LLVM_LIBDIR_SUFFIX**:STRING + Extra suffix to append to the directory where libraries are to be + installed. On a 64-bit architecture, one could use ``-DLLVM_LIBDIR_SUFFIX=64`` + to install libraries to ``/usr/lib64``. + +**CMAKE_C_FLAGS**:STRING + Extra flags to use when compiling C source files. + +**CMAKE_CXX_FLAGS**:STRING + Extra flags to use when compiling C++ source files. + +**BUILD_SHARED_LIBS**:BOOL + Flag indicating is shared libraries will be built. Its default value is + OFF. Shared libraries are not supported on Windows and not recommended in the + other OSes. + +.. _LLVM-specific variables: + +LLVM-specific variables +----------------------- + +**LLVM_TARGETS_TO_BUILD**:STRING + Semicolon-separated list of targets to build, or *all* for building all + targets. Case-sensitive. Defaults to *all*. Example: + ``-DLLVM_TARGETS_TO_BUILD="X86;PowerPC"``. + +**LLVM_BUILD_TOOLS**:BOOL + Build LLVM tools. Defaults to ON. Targets for building each tool are generated + in any case. You can build an tool separately by invoking its target. For + example, you can build *llvm-as* with a makefile-based system executing *make + llvm-as* on the root of your build directory. + +**LLVM_INCLUDE_TOOLS**:BOOL + Generate build targets for the LLVM tools. Defaults to ON. You can use that + option for disabling the generation of build targets for the LLVM tools. + +**LLVM_BUILD_EXAMPLES**:BOOL + Build LLVM examples. Defaults to OFF. Targets for building each example are + generated in any case. See documentation for *LLVM_BUILD_TOOLS* above for more + details. + +**LLVM_INCLUDE_EXAMPLES**:BOOL + Generate build targets for the LLVM examples. Defaults to ON. You can use that + option for disabling the generation of build targets for the LLVM examples. + +**LLVM_BUILD_TESTS**:BOOL + Build LLVM unit tests. Defaults to OFF. Targets for building each unit test + are generated in any case. You can build a specific unit test with the target + *UnitTestNameTests* (where at this time *UnitTestName* can be ADT, Analysis, + ExecutionEngine, JIT, Support, Transform, VMCore; see the subdirectories of + *unittests* for an updated list.) It is possible to build all unit tests with + the target *UnitTests*. + +**LLVM_INCLUDE_TESTS**:BOOL + Generate build targets for the LLVM unit tests. Defaults to ON. You can use + that option for disabling the generation of build targets for the LLVM unit + tests. + +**LLVM_APPEND_VC_REV**:BOOL + Append version control revision info (svn revision number or Git revision id) + to LLVM version string (stored in the PACKAGE_VERSION macro). For this to work + cmake must be invoked before the build. Defaults to OFF. + +**LLVM_ENABLE_THREADS**:BOOL + Build with threads support, if available. Defaults to ON. + +**LLVM_ENABLE_ASSERTIONS**:BOOL + Enables code assertions. Defaults to OFF if and only if ``CMAKE_BUILD_TYPE`` + is *Release*. + +**LLVM_ENABLE_PIC**:BOOL + Add the ``-fPIC`` flag for the compiler command-line, if the compiler supports + this flag. Some systems, like Windows, do not need this flag. Defaults to ON. + +**LLVM_ENABLE_WARNINGS**:BOOL + Enable all compiler warnings. Defaults to ON. + +**LLVM_ENABLE_PEDANTIC**:BOOL + Enable pedantic mode. This disable compiler specific extensions, is + possible. Defaults to ON. + +**LLVM_ENABLE_WERROR**:BOOL + Stop and fail build, if a compiler warning is triggered. Defaults to OFF. + +**LLVM_BUILD_32_BITS**:BOOL + Build 32-bits executables and libraries on 64-bits systems. This option is + available only on some 64-bits unix systems. Defaults to OFF. + +**LLVM_TARGET_ARCH**:STRING + LLVM target to use for native code generation. This is required for JIT + generation. It defaults to "host", meaning that it shall pick the architecture + of the machine where LLVM is being built. If you are cross-compiling, set it + to the target architecture name. + +**LLVM_TABLEGEN**:STRING + Full path to a native TableGen executable (usually named ``tblgen``). This is + intended for cross-compiling: if the user sets this variable, no native + TableGen will be created. + +**LLVM_LIT_ARGS**:STRING + Arguments given to lit. ``make check`` and ``make clang-test`` are affected. + By default, ``'-sv --no-progress-bar'`` on Visual C++ and Xcode, ``'-sv'`` on + others. + +**LLVM_LIT_TOOLS_DIR**:PATH + The path to GnuWin32 tools for tests. Valid on Windows host. Defaults to "", + then Lit seeks tools according to %PATH%. Lit can find tools(eg. grep, sort, + &c) on LLVM_LIT_TOOLS_DIR at first, without specifying GnuWin32 to %PATH%. + +**LLVM_ENABLE_FFI**:BOOL + Indicates whether LLVM Interpreter will be linked with Foreign Function + Interface library. If the library or its headers are installed on a custom + location, you can set the variables FFI_INCLUDE_DIR and + FFI_LIBRARY_DIR. Defaults to OFF. + +**LLVM_EXTERNAL_{CLANG,LLD,POLLY}_SOURCE_DIR**:PATH + Path to ``{Clang,lld,Polly}``\'s source directory. Defaults to + ``tools/{clang,lld,polly}``. ``{Clang,lld,Polly}`` will not be built when it + is empty or it does not point valid path. + +**LLVM_USE_OPROFILE**:BOOL + Enable building OProfile JIT support. Defaults to OFF + +**LLVM_USE_INTEL_JITEVENTS**:BOOL + Enable building support for Intel JIT Events API. Defaults to OFF + +**LLVM_ENABLE_ZLIB**:BOOL + Build with zlib to support compression/uncompression in LLVM tools. + Defaults to ON. + +**LLVM_USE_SANITIZER**:STRING + Define the sanitizer used to build LLVM binaries and tests. Possible values + are ``Address``, ``Memory`` and ``MemoryWithOrigins``. Defaults to empty + string. + +Executing the test suite +======================== + +Testing is performed when the *check* target is built. For instance, if you are +using makefiles, execute this command while on the top level of your build +directory: + +.. code-block:: console + + $ make check + +On Visual Studio, you may run tests to build the project "check". + +Cross compiling +=============== + +See `this wiki page `_ for +generic instructions on how to cross-compile with CMake. It goes into detailed +explanations and may seem daunting, but it is not. On the wiki page there are +several examples including toolchain files. Go directly to `this section +`_ +for a quick solution. + +Also see the `LLVM-specific variables`_ section for variables used when +cross-compiling. + +Embedding LLVM in your project +============================== + +The most difficult part of adding LLVM to the build of a project is to determine +the set of LLVM libraries corresponding to the set of required LLVM +features. What follows is an example of how to obtain this information: + +.. code-block:: cmake + + # A convenience variable: + set(LLVM_ROOT "" CACHE PATH "Root of LLVM install.") + + # A bit of a sanity check: + if( NOT EXISTS ${LLVM_ROOT}/include/llvm ) + message(FATAL_ERROR "LLVM_ROOT (${LLVM_ROOT}) is not a valid LLVM install") + endif() + + # We incorporate the CMake features provided by LLVM: + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LLVM_ROOT}/share/llvm/cmake") + include(LLVMConfig) + + # Now set the header and library paths: + include_directories( ${LLVM_INCLUDE_DIRS} ) + link_directories( ${LLVM_LIBRARY_DIRS} ) + add_definitions( ${LLVM_DEFINITIONS} ) + + # Let's suppose we want to build a JIT compiler with support for + # binary code (no interpreter): + llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native) + + # Finally, we link the LLVM libraries to our executable: + target_link_libraries(mycompiler ${REQ_LLVM_LIBRARIES}) + +This assumes that LLVM_ROOT points to an install of LLVM. The procedure works +too for uninstalled builds although we need to take care to add an +`include_directories` for the location of the headers on the LLVM source +directory (if we are building out-of-source.) + +Alternativaly, you can utilize CMake's ``find_package`` functionality. Here is +an equivalent variant of snippet shown above: + +.. code-block:: cmake + + find_package(LLVM) + + if( NOT LLVM_FOUND ) + message(FATAL_ERROR "LLVM package can't be found. Set CMAKE_PREFIX_PATH variable to LLVM's installation prefix.") + endif() + + include_directories( ${LLVM_INCLUDE_DIRS} ) + link_directories( ${LLVM_LIBRARY_DIRS} ) + + llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native) + + target_link_libraries(mycompiler ${REQ_LLVM_LIBRARIES}) + +.. _cmake-out-of-source-pass: + +Developing LLVM pass out of source +---------------------------------- + +It is possible to develop LLVM passes against installed LLVM. An example of +project layout provided below: + +.. code-block:: none + + / + | + CMakeLists.txt + / + | + CMakeLists.txt + Pass.cpp + ... + +Contents of ``/CMakeLists.txt``: + +.. code-block:: cmake + + find_package(LLVM) + + # Define add_llvm_* macro's. + include(AddLLVM) + + add_definitions(${LLVM_DEFINITIONS}) + include_directories(${LLVM_INCLUDE_DIRS}) + link_directories(${LLVM_LIBRARY_DIRS}) + + add_subdirectory() + +Contents of ``//CMakeLists.txt``: + +.. code-block:: cmake + + add_llvm_loadable_module(LLVMPassname + Pass.cpp + ) + +When you are done developing your pass, you may wish to integrate it +into LLVM source tree. You can achieve it in two easy steps: + +#. Copying ```` folder into ``/lib/Transform`` directory. + +#. Adding ``add_subdirectory()`` line into + ``/lib/Transform/CMakeLists.txt``. + +Compiler/Platform specific topics +================================= + +Notes for specific compilers and/or platforms. + +Microsoft Visual C++ +-------------------- + +**LLVM_COMPILER_JOBS**:STRING + Specifies the maximum number of parallell compiler jobs to use per project + when building with msbuild or Visual Studio. Only supported for the Visual + Studio 2010 CMake generator. 0 means use all processors. Default is 0. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 00000000..8c49aa5e --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,51 @@ + +if (DOXYGEN_FOUND) +if (LLVM_ENABLE_DOXYGEN) + set(abs_top_srcdir ${LLVM_MAIN_SRC_DIR}) + set(abs_top_builddir ${LLVM_BINARY_DIR}) + + if (HAVE_DOT) + set(DOT ${LLVM_PATH_DOT}) + endif() + + if (LLVM_DOXYGEN_EXTERNAL_SEARCH) + set(enable_searchengine "YES") + set(searchengine_url "${LLVM_DOXYGEN_SEARCHENGINE_URL}") + set(enable_server_based_search "YES") + set(enable_external_search "YES") + set(extra_search_mappings "${LLVM_DOXYGEN_SEARCH_MAPPINGS}") + else() + set(enable_searchengine "NO") + set(searchengine_url "") + set(enable_server_based_search "NO") + set(enable_external_search "NO") + set(extra_search_mappings "") + endif() + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxygen.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg @ONLY) + + set(abs_top_srcdir) + set(abs_top_builddir) + set(DOT) + set(enable_searchengine) + set(searchengine_url) + set(enable_server_based_search) + set(enable_external_search) + set(extra_search_mappings) + + add_custom_target(doxygen-llvm + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating llvm doxygen documentation." VERBATIM) + + if (LLVM_BUILD_DOCS) + add_dependencies(doxygen doxygen-llvm) + endif() + + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html + DESTINATION docs/html) + endif() +endif() +endif() diff --git a/docs/CodeGenerator.rst b/docs/CodeGenerator.rst new file mode 100644 index 00000000..c87a6286 --- /dev/null +++ b/docs/CodeGenerator.rst @@ -0,0 +1,2444 @@ +========================================== +The LLVM Target-Independent Code Generator +========================================== + +.. role:: raw-html(raw) + :format: html + +.. raw:: html + + + +.. contents:: + :local: + +.. warning:: + This is a work in progress. + +Introduction +============ + +The LLVM target-independent code generator is a framework that provides a suite +of reusable components for translating the LLVM internal representation to the +machine code for a specified target---either in assembly form (suitable for a +static compiler) or in binary machine code format (usable for a JIT +compiler). The LLVM target-independent code generator consists of six main +components: + +1. `Abstract target description`_ interfaces which capture important properties + about various aspects of the machine, independently of how they will be used. + These interfaces are defined in ``include/llvm/Target/``. + +2. Classes used to represent the `code being generated`_ for a target. These + classes are intended to be abstract enough to represent the machine code for + *any* target machine. These classes are defined in + ``include/llvm/CodeGen/``. At this level, concepts like "constant pool + entries" and "jump tables" are explicitly exposed. + +3. Classes and algorithms used to represent code as the object file level, the + `MC Layer`_. These classes represent assembly level constructs like labels, + sections, and instructions. At this level, concepts like "constant pool + entries" and "jump tables" don't exist. + +4. `Target-independent algorithms`_ used to implement various phases of native + code generation (register allocation, scheduling, stack frame representation, + etc). This code lives in ``lib/CodeGen/``. + +5. `Implementations of the abstract target description interfaces`_ for + particular targets. These machine descriptions make use of the components + provided by LLVM, and can optionally provide custom target-specific passes, + to build complete code generators for a specific target. Target descriptions + live in ``lib/Target/``. + +6. The target-independent JIT components. The LLVM JIT is completely target + independent (it uses the ``TargetJITInfo`` structure to interface for + target-specific issues. The code for the target-independent JIT lives in + ``lib/ExecutionEngine/JIT``. + +Depending on which part of the code generator you are interested in working on, +different pieces of this will be useful to you. In any case, you should be +familiar with the `target description`_ and `machine code representation`_ +classes. If you want to add a backend for a new target, you will need to +`implement the target description`_ classes for your new target and understand +the `LLVM code representation `_. If you are interested in +implementing a new `code generation algorithm`_, it should only depend on the +target-description and machine code representation classes, ensuring that it is +portable. + +Required components in the code generator +----------------------------------------- + +The two pieces of the LLVM code generator are the high-level interface to the +code generator and the set of reusable components that can be used to build +target-specific backends. The two most important interfaces (:raw-html:`` +`TargetMachine`_ :raw-html:`` and :raw-html:`` `DataLayout`_ +:raw-html:``) are the only ones that are required to be defined for a +backend to fit into the LLVM system, but the others must be defined if the +reusable code generator components are going to be used. + +This design has two important implications. The first is that LLVM can support +completely non-traditional code generation targets. For example, the C backend +does not require register allocation, instruction selection, or any of the other +standard components provided by the system. As such, it only implements these +two interfaces, and does its own thing. Note that C backend was removed from the +trunk since LLVM 3.1 release. Another example of a code generator like this is a +(purely hypothetical) backend that converts LLVM to the GCC RTL form and uses +GCC to emit machine code for a target. + +This design also implies that it is possible to design and implement radically +different code generators in the LLVM system that do not make use of any of the +built-in components. Doing so is not recommended at all, but could be required +for radically different targets that do not fit into the LLVM machine +description model: FPGAs for example. + +.. _high-level design of the code generator: + +The high-level design of the code generator +------------------------------------------- + +The LLVM target-independent code generator is designed to support efficient and +quality code generation for standard register-based microprocessors. Code +generation in this model is divided into the following stages: + +1. `Instruction Selection`_ --- This phase determines an efficient way to + express the input LLVM code in the target instruction set. This stage + produces the initial code for the program in the target instruction set, then + makes use of virtual registers in SSA form and physical registers that + represent any required register assignments due to target constraints or + calling conventions. This step turns the LLVM code into a DAG of target + instructions. + +2. `Scheduling and Formation`_ --- This phase takes the DAG of target + instructions produced by the instruction selection phase, determines an + ordering of the instructions, then emits the instructions as :raw-html:`` + `MachineInstr`_\s :raw-html:`` with that ordering. Note that we + describe this in the `instruction selection section`_ because it operates on + a `SelectionDAG`_. + +3. `SSA-based Machine Code Optimizations`_ --- This optional stage consists of a + series of machine-code optimizations that operate on the SSA-form produced by + the instruction selector. Optimizations like modulo-scheduling or peephole + optimization work here. + +4. `Register Allocation`_ --- The target code is transformed from an infinite + virtual register file in SSA form to the concrete register file used by the + target. This phase introduces spill code and eliminates all virtual register + references from the program. + +5. `Prolog/Epilog Code Insertion`_ --- Once the machine code has been generated + for the function and the amount of stack space required is known (used for + LLVM alloca's and spill slots), the prolog and epilog code for the function + can be inserted and "abstract stack location references" can be eliminated. + This stage is responsible for implementing optimizations like frame-pointer + elimination and stack packing. + +6. `Late Machine Code Optimizations`_ --- Optimizations that operate on "final" + machine code can go here, such as spill code scheduling and peephole + optimizations. + +7. `Code Emission`_ --- The final stage actually puts out the code for the + current function, either in the target assembler format or in machine + code. + +The code generator is based on the assumption that the instruction selector will +use an optimal pattern matching selector to create high-quality sequences of +native instructions. Alternative code generator designs based on pattern +expansion and aggressive iterative peephole optimization are much slower. This +design permits efficient compilation (important for JIT environments) and +aggressive optimization (used when generating code offline) by allowing +components of varying levels of sophistication to be used for any step of +compilation. + +In addition to these stages, target implementations can insert arbitrary +target-specific passes into the flow. For example, the X86 target uses a +special pass to handle the 80x87 floating point stack architecture. Other +targets with unusual requirements can be supported with custom passes as needed. + +Using TableGen for target description +------------------------------------- + +The target description classes require a detailed description of the target +architecture. These target descriptions often have a large amount of common +information (e.g., an ``add`` instruction is almost identical to a ``sub`` +instruction). In order to allow the maximum amount of commonality to be +factored out, the LLVM code generator uses the +:doc:`TableGen ` tool to describe big chunks of the +target machine, which allows the use of domain-specific and target-specific +abstractions to reduce the amount of repetition. + +As LLVM continues to be developed and refined, we plan to move more and more of +the target description to the ``.td`` form. Doing so gives us a number of +advantages. The most important is that it makes it easier to port LLVM because +it reduces the amount of C++ code that has to be written, and the surface area +of the code generator that needs to be understood before someone can get +something working. Second, it makes it easier to change things. In particular, +if tables and other things are all emitted by ``tblgen``, we only need a change +in one place (``tblgen``) to update all of the targets to a new interface. + +.. _Abstract target description: +.. _target description: + +Target description classes +========================== + +The LLVM target description classes (located in the ``include/llvm/Target`` +directory) provide an abstract description of the target machine independent of +any particular client. These classes are designed to capture the *abstract* +properties of the target (such as the instructions and registers it has), and do +not incorporate any particular pieces of code generation algorithms. + +All of the target description classes (except the :raw-html:`` `DataLayout`_ +:raw-html:`` class) are designed to be subclassed by the concrete target +implementation, and have virtual methods implemented. To get to these +implementations, the :raw-html:`` `TargetMachine`_ :raw-html:`` class +provides accessors that should be implemented by the target. + +.. _TargetMachine: + +The ``TargetMachine`` class +--------------------------- + +The ``TargetMachine`` class provides virtual methods that are used to access the +target-specific implementations of the various target description classes via +the ``get*Info`` methods (``getInstrInfo``, ``getRegisterInfo``, +``getFrameInfo``, etc.). This class is designed to be specialized by a concrete +target implementation (e.g., ``X86TargetMachine``) which implements the various +virtual methods. The only required target description class is the +:raw-html:`` `DataLayout`_ :raw-html:`` class, but if the code +generator components are to be used, the other interfaces should be implemented +as well. + +.. _DataLayout: + +The ``DataLayout`` class +------------------------ + +The ``DataLayout`` class is the only required target description class, and it +is the only class that is not extensible (you cannot derive a new class from +it). ``DataLayout`` specifies information about how the target lays out memory +for structures, the alignment requirements for various data types, the size of +pointers in the target, and whether the target is little-endian or +big-endian. + +.. _TargetLowering: + +The ``TargetLowering`` class +---------------------------- + +The ``TargetLowering`` class is used by SelectionDAG based instruction selectors +primarily to describe how LLVM code should be lowered to SelectionDAG +operations. Among other things, this class indicates: + +* an initial register class to use for various ``ValueType``\s, + +* which operations are natively supported by the target machine, + +* the return type of ``setcc`` operations, + +* the type to use for shift amounts, and + +* various high-level characteristics, like whether it is profitable to turn + division by a constant into a multiplication sequence. + +.. _TargetRegisterInfo: + +The ``TargetRegisterInfo`` class +-------------------------------- + +The ``TargetRegisterInfo`` class is used to describe the register file of the +target and any interactions between the registers. + +Registers are represented in the code generator by unsigned integers. Physical +registers (those that actually exist in the target description) are unique +small numbers, and virtual registers are generally large. Note that +register ``#0`` is reserved as a flag value. + +Each register in the processor description has an associated +``TargetRegisterDesc`` entry, which provides a textual name for the register +(used for assembly output and debugging dumps) and a set of aliases (used to +indicate whether one register overlaps with another). + +In addition to the per-register description, the ``TargetRegisterInfo`` class +exposes a set of processor specific register classes (instances of the +``TargetRegisterClass`` class). Each register class contains sets of registers +that have the same properties (for example, they are all 32-bit integer +registers). Each SSA virtual register created by the instruction selector has +an associated register class. When the register allocator runs, it replaces +virtual registers with a physical register in the set. + +The target-specific implementations of these classes is auto-generated from a +`TableGen `_ description of the register file. + +.. _TargetInstrInfo: + +The ``TargetInstrInfo`` class +----------------------------- + +The ``TargetInstrInfo`` class is used to describe the machine instructions +supported by the target. Descriptions define things like the mnemonic for +the opcode, the number of operands, the list of implicit register uses and defs, +whether the instruction has certain target-independent properties (accesses +memory, is commutable, etc), and holds any target-specific flags. + +The ``TargetFrameInfo`` class +----------------------------- + +The ``TargetFrameInfo`` class is used to provide information about the stack +frame layout of the target. It holds the direction of stack growth, the known +stack alignment on entry to each function, and the offset to the local area. +The offset to the local area is the offset from the stack pointer on function +entry to the first location where function data (local variables, spill +locations) can be stored. + +The ``TargetSubtarget`` class +----------------------------- + +The ``TargetSubtarget`` class is used to provide information about the specific +chip set being targeted. A sub-target informs code generation of which +instructions are supported, instruction latencies and instruction execution +itinerary; i.e., which processing units are used, in what order, and for how +long. + +The ``TargetJITInfo`` class +--------------------------- + +The ``TargetJITInfo`` class exposes an abstract interface used by the +Just-In-Time code generator to perform target-specific activities, such as +emitting stubs. If a ``TargetMachine`` supports JIT code generation, it should +provide one of these objects through the ``getJITInfo`` method. + +.. _code being generated: +.. _machine code representation: + +Machine code description classes +================================ + +At the high-level, LLVM code is translated to a machine specific representation +formed out of :raw-html:`` `MachineFunction`_ :raw-html:``, +:raw-html:`` `MachineBasicBlock`_ :raw-html:``, and :raw-html:`` +`MachineInstr`_ :raw-html:`` instances (defined in +``include/llvm/CodeGen``). This representation is completely target agnostic, +representing instructions in their most abstract form: an opcode and a series of +operands. This representation is designed to support both an SSA representation +for machine code, as well as a register allocated, non-SSA form. + +.. _MachineInstr: + +The ``MachineInstr`` class +-------------------------- + +Target machine instructions are represented as instances of the ``MachineInstr`` +class. This class is an extremely abstract way of representing machine +instructions. In particular, it only keeps track of an opcode number and a set +of operands. + +The opcode number is a simple unsigned integer that only has meaning to a +specific backend. All of the instructions for a target should be defined in the +``*InstrInfo.td`` file for the target. The opcode enum values are auto-generated +from this description. The ``MachineInstr`` class does not have any information +about how to interpret the instruction (i.e., what the semantics of the +instruction are); for that you must refer to the :raw-html:`` +`TargetInstrInfo`_ :raw-html:`` class. + +The operands of a machine instruction can be of several different types: a +register reference, a constant integer, a basic block reference, etc. In +addition, a machine operand should be marked as a def or a use of the value +(though only registers are allowed to be defs). + +By convention, the LLVM code generator orders instruction operands so that all +register definitions come before the register uses, even on architectures that +are normally printed in other orders. For example, the SPARC add instruction: +"``add %i1, %i2, %i3``" adds the "%i1", and "%i2" registers and stores the +result into the "%i3" register. In the LLVM code generator, the operands should +be stored as "``%i3, %i1, %i2``": with the destination first. + +Keeping destination (definition) operands at the beginning of the operand list +has several advantages. In particular, the debugging printer will print the +instruction like this: + +.. code-block:: llvm + + %r3 = add %i1, %i2 + +Also if the first operand is a def, it is easier to `create instructions`_ whose +only def is the first operand. + +.. _create instructions: + +Using the ``MachineInstrBuilder.h`` functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Machine instructions are created by using the ``BuildMI`` functions, located in +the ``include/llvm/CodeGen/MachineInstrBuilder.h`` file. The ``BuildMI`` +functions make it easy to build arbitrary machine instructions. Usage of the +``BuildMI`` functions look like this: + +.. code-block:: c++ + + // Create a 'DestReg = mov 42' (rendered in X86 assembly as 'mov DestReg, 42') + // instruction. The '1' specifies how many operands will be added. + MachineInstr *MI = BuildMI(X86::MOV32ri, 1, DestReg).addImm(42); + + // Create the same instr, but insert it at the end of a basic block. + MachineBasicBlock &MBB = ... + BuildMI(MBB, X86::MOV32ri, 1, DestReg).addImm(42); + + // Create the same instr, but insert it before a specified iterator point. + MachineBasicBlock::iterator MBBI = ... + BuildMI(MBB, MBBI, X86::MOV32ri, 1, DestReg).addImm(42); + + // Create a 'cmp Reg, 0' instruction, no destination reg. + MI = BuildMI(X86::CMP32ri, 2).addReg(Reg).addImm(0); + + // Create an 'sahf' instruction which takes no operands and stores nothing. + MI = BuildMI(X86::SAHF, 0); + + // Create a self looping branch instruction. + BuildMI(MBB, X86::JNE, 1).addMBB(&MBB); + +The key thing to remember with the ``BuildMI`` functions is that you have to +specify the number of operands that the machine instruction will take. This +allows for efficient memory allocation. You also need to specify if operands +default to be uses of values, not definitions. If you need to add a definition +operand (other than the optional destination register), you must explicitly mark +it as such: + +.. code-block:: c++ + + MI.addReg(Reg, RegState::Define); + +Fixed (preassigned) registers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One important issue that the code generator needs to be aware of is the presence +of fixed registers. In particular, there are often places in the instruction +stream where the register allocator *must* arrange for a particular value to be +in a particular register. This can occur due to limitations of the instruction +set (e.g., the X86 can only do a 32-bit divide with the ``EAX``/``EDX`` +registers), or external factors like calling conventions. In any case, the +instruction selector should emit code that copies a virtual register into or out +of a physical register when needed. + +For example, consider this simple LLVM example: + +.. code-block:: llvm + + define i32 @test(i32 %X, i32 %Y) { + %Z = udiv i32 %X, %Y + ret i32 %Z + } + +The X86 instruction selector produces this machine code for the ``div`` and +``ret`` (use "``llc X.bc -march=x86 -print-machineinstrs``" to get this): + +.. code-block:: llvm + + ;; Start of div + %EAX = mov %reg1024 ;; Copy X (in reg1024) into EAX + %reg1027 = sar %reg1024, 31 + %EDX = mov %reg1027 ;; Sign extend X into EDX + idiv %reg1025 ;; Divide by Y (in reg1025) + %reg1026 = mov %EAX ;; Read the result (Z) out of EAX + + ;; Start of ret + %EAX = mov %reg1026 ;; 32-bit return value goes in EAX + ret + +By the end of code generation, the register allocator has coalesced the +registers and deleted the resultant identity moves producing the following +code: + +.. code-block:: llvm + + ;; X is in EAX, Y is in ECX + mov %EAX, %EDX + sar %EDX, 31 + idiv %ECX + ret + +This approach is extremely general (if it can handle the X86 architecture, it +can handle anything!) and allows all of the target specific knowledge about the +instruction stream to be isolated in the instruction selector. Note that +physical registers should have a short lifetime for good code generation, and +all physical registers are assumed dead on entry to and exit from basic blocks +(before register allocation). Thus, if you need a value to be live across basic +block boundaries, it *must* live in a virtual register. + +Call-clobbered registers +^^^^^^^^^^^^^^^^^^^^^^^^ + +Some machine instructions, like calls, clobber a large number of physical +registers. Rather than adding ```` operands for all of them, it is +possible to use an ``MO_RegisterMask`` operand instead. The register mask +operand holds a bit mask of preserved registers, and everything else is +considered to be clobbered by the instruction. + +Machine code in SSA form +^^^^^^^^^^^^^^^^^^^^^^^^ + +``MachineInstr``'s are initially selected in SSA-form, and are maintained in +SSA-form until register allocation happens. For the most part, this is +trivially simple since LLVM is already in SSA form; LLVM PHI nodes become +machine code PHI nodes, and virtual registers are only allowed to have a single +definition. + +After register allocation, machine code is no longer in SSA-form because there +are no virtual registers left in the code. + +.. _MachineBasicBlock: + +The ``MachineBasicBlock`` class +------------------------------- + +The ``MachineBasicBlock`` class contains a list of machine instructions +(:raw-html:`` `MachineInstr`_ :raw-html:`` instances). It roughly +corresponds to the LLVM code input to the instruction selector, but there can be +a one-to-many mapping (i.e. one LLVM basic block can map to multiple machine +basic blocks). The ``MachineBasicBlock`` class has a "``getBasicBlock``" method, +which returns the LLVM basic block that it comes from. + +.. _MachineFunction: + +The ``MachineFunction`` class +----------------------------- + +The ``MachineFunction`` class contains a list of machine basic blocks +(:raw-html:`` `MachineBasicBlock`_ :raw-html:`` instances). It +corresponds one-to-one with the LLVM function input to the instruction selector. +In addition to a list of basic blocks, the ``MachineFunction`` contains a a +``MachineConstantPool``, a ``MachineFrameInfo``, a ``MachineFunctionInfo``, and +a ``MachineRegisterInfo``. See ``include/llvm/CodeGen/MachineFunction.h`` for +more information. + +``MachineInstr Bundles`` +------------------------ + +LLVM code generator can model sequences of instructions as MachineInstr +bundles. A MI bundle can model a VLIW group / pack which contains an arbitrary +number of parallel instructions. It can also be used to model a sequential list +of instructions (potentially with data dependencies) that cannot be legally +separated (e.g. ARM Thumb2 IT blocks). + +Conceptually a MI bundle is a MI with a number of other MIs nested within: + +:: + + -------------- + | Bundle | --------- + -------------- \ + | ---------------- + | | MI | + | ---------------- + | | + | ---------------- + | | MI | + | ---------------- + | | + | ---------------- + | | MI | + | ---------------- + | + -------------- + | Bundle | -------- + -------------- \ + | ---------------- + | | MI | + | ---------------- + | | + | ---------------- + | | MI | + | ---------------- + | | + | ... + | + -------------- + | Bundle | -------- + -------------- \ + | + ... + +MI bundle support does not change the physical representations of +MachineBasicBlock and MachineInstr. All the MIs (including top level and nested +ones) are stored as sequential list of MIs. The "bundled" MIs are marked with +the 'InsideBundle' flag. A top level MI with the special BUNDLE opcode is used +to represent the start of a bundle. It's legal to mix BUNDLE MIs with indiviual +MIs that are not inside bundles nor represent bundles. + +MachineInstr passes should operate on a MI bundle as a single unit. Member +methods have been taught to correctly handle bundles and MIs inside bundles. +The MachineBasicBlock iterator has been modified to skip over bundled MIs to +enforce the bundle-as-a-single-unit concept. An alternative iterator +instr_iterator has been added to MachineBasicBlock to allow passes to iterate +over all of the MIs in a MachineBasicBlock, including those which are nested +inside bundles. The top level BUNDLE instruction must have the correct set of +register MachineOperand's that represent the cumulative inputs and outputs of +the bundled MIs. + +Packing / bundling of MachineInstr's should be done as part of the register +allocation super-pass. More specifically, the pass which determines what MIs +should be bundled together must be done after code generator exits SSA form +(i.e. after two-address pass, PHI elimination, and copy coalescing). Bundles +should only be finalized (i.e. adding BUNDLE MIs and input and output register +MachineOperands) after virtual registers have been rewritten into physical +registers. This requirement eliminates the need to add virtual register operands +to BUNDLE instructions which would effectively double the virtual register def +and use lists. + +.. _MC Layer: + +The "MC" Layer +============== + +The MC Layer is used to represent and process code at the raw machine code +level, devoid of "high level" information like "constant pools", "jump tables", +"global variables" or anything like that. At this level, LLVM handles things +like label names, machine instructions, and sections in the object file. The +code in this layer is used for a number of important purposes: the tail end of +the code generator uses it to write a .s or .o file, and it is also used by the +llvm-mc tool to implement standalone machine code assemblers and disassemblers. + +This section describes some of the important classes. There are also a number +of important subsystems that interact at this layer, they are described later in +this manual. + +.. _MCStreamer: + +The ``MCStreamer`` API +---------------------- + +MCStreamer is best thought of as an assembler API. It is an abstract API which +is *implemented* in different ways (e.g. to output a .s file, output an ELF .o +file, etc) but whose API correspond directly to what you see in a .s file. +MCStreamer has one method per directive, such as EmitLabel, EmitSymbolAttribute, +SwitchSection, EmitValue (for .byte, .word), etc, which directly correspond to +assembly level directives. It also has an EmitInstruction method, which is used +to output an MCInst to the streamer. + +This API is most important for two clients: the llvm-mc stand-alone assembler is +effectively a parser that parses a line, then invokes a method on MCStreamer. In +the code generator, the `Code Emission`_ phase of the code generator lowers +higher level LLVM IR and Machine* constructs down to the MC layer, emitting +directives through MCStreamer. + +On the implementation side of MCStreamer, there are two major implementations: +one for writing out a .s file (MCAsmStreamer), and one for writing out a .o +file (MCObjectStreamer). MCAsmStreamer is a straight-forward implementation +that prints out a directive for each method (e.g. ``EmitValue -> .byte``), but +MCObjectStreamer implements a full assembler. + +For target specific directives, the MCStreamer has a MCTargetStreamer instance. +Each target that needs it defines a class that inherits from it and is a lot +like MCStreamer itself: It has one method per directive and two classes that +inherit from it, a target object streamer and a target asm streamer. The target +asm streamer just prints it (``emitFnStart -> .fnstrart``), and the object +streamer implement the assembler logic for it. + +To make llvm use these classes, the target initialization must call +TargetRegistry::RegisterAsmStreamer and TargetRegistry::RegisterMCObjectStreamer +passing callbacks that allocate the corresponding target streamer and pass it +to createAsmStreamer or to the appropriate object streamer constructor. + +The ``MCContext`` class +----------------------- + +The MCContext class is the owner of a variety of uniqued data structures at the +MC layer, including symbols, sections, etc. As such, this is the class that you +interact with to create symbols and sections. This class can not be subclassed. + +The ``MCSymbol`` class +---------------------- + +The MCSymbol class represents a symbol (aka label) in the assembly file. There +are two interesting kinds of symbols: assembler temporary symbols, and normal +symbols. Assembler temporary symbols are used and processed by the assembler +but are discarded when the object file is produced. The distinction is usually +represented by adding a prefix to the label, for example "L" labels are +assembler temporary labels in MachO. + +MCSymbols are created by MCContext and uniqued there. This means that MCSymbols +can be compared for pointer equivalence to find out if they are the same symbol. +Note that pointer inequality does not guarantee the labels will end up at +different addresses though. It's perfectly legal to output something like this +to the .s file: + +:: + + foo: + bar: + .byte 4 + +In this case, both the foo and bar symbols will have the same address. + +The ``MCSection`` class +----------------------- + +The ``MCSection`` class represents an object-file specific section. It is +subclassed by object file specific implementations (e.g. ``MCSectionMachO``, +``MCSectionCOFF``, ``MCSectionELF``) and these are created and uniqued by +MCContext. The MCStreamer has a notion of the current section, which can be +changed with the SwitchToSection method (which corresponds to a ".section" +directive in a .s file). + +.. _MCInst: + +The ``MCInst`` class +-------------------- + +The ``MCInst`` class is a target-independent representation of an instruction. +It is a simple class (much more so than `MachineInstr`_) that holds a +target-specific opcode and a vector of MCOperands. MCOperand, in turn, is a +simple discriminated union of three cases: 1) a simple immediate, 2) a target +register ID, 3) a symbolic expression (e.g. "``Lfoo-Lbar+42``") as an MCExpr. + +MCInst is the common currency used to represent machine instructions at the MC +layer. It is the type used by the instruction encoder, the instruction printer, +and the type generated by the assembly parser and disassembler. + +.. _Target-independent algorithms: +.. _code generation algorithm: + +Target-independent code generation algorithms +============================================= + +This section documents the phases described in the `high-level design of the +code generator`_. It explains how they work and some of the rationale behind +their design. + +.. _Instruction Selection: +.. _instruction selection section: + +Instruction Selection +--------------------- + +Instruction Selection is the process of translating LLVM code presented to the +code generator into target-specific machine instructions. There are several +well-known ways to do this in the literature. LLVM uses a SelectionDAG based +instruction selector. + +Portions of the DAG instruction selector are generated from the target +description (``*.td``) files. Our goal is for the entire instruction selector +to be generated from these ``.td`` files, though currently there are still +things that require custom C++ code. + +.. _SelectionDAG: + +Introduction to SelectionDAGs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The SelectionDAG provides an abstraction for code representation in a way that +is amenable to instruction selection using automatic techniques +(e.g. dynamic-programming based optimal pattern matching selectors). It is also +well-suited to other phases of code generation; in particular, instruction +scheduling (SelectionDAG's are very close to scheduling DAGs post-selection). +Additionally, the SelectionDAG provides a host representation where a large +variety of very-low-level (but target-independent) `optimizations`_ may be +performed; ones which require extensive information about the instructions +efficiently supported by the target. + +The SelectionDAG is a Directed-Acyclic-Graph whose nodes are instances of the +``SDNode`` class. The primary payload of the ``SDNode`` is its operation code +(Opcode) that indicates what operation the node performs and the operands to the +operation. The various operation node types are described at the top of the +``include/llvm/CodeGen/SelectionDAGNodes.h`` file. + +Although most operations define a single value, each node in the graph may +define multiple values. For example, a combined div/rem operation will define +both the dividend and the remainder. Many other situations require multiple +values as well. Each node also has some number of operands, which are edges to +the node defining the used value. Because nodes may define multiple values, +edges are represented by instances of the ``SDValue`` class, which is a +```` pair, indicating the node and result value being used, +respectively. Each value produced by an ``SDNode`` has an associated ``MVT`` +(Machine Value Type) indicating what the type of the value is. + +SelectionDAGs contain two different kinds of values: those that represent data +flow and those that represent control flow dependencies. Data values are simple +edges with an integer or floating point value type. Control edges are +represented as "chain" edges which are of type ``MVT::Other``. These edges +provide an ordering between nodes that have side effects (such as loads, stores, +calls, returns, etc). All nodes that have side effects should take a token +chain as input and produce a new one as output. By convention, token chain +inputs are always operand #0, and chain results are always the last value +produced by an operation. + +A SelectionDAG has designated "Entry" and "Root" nodes. The Entry node is +always a marker node with an Opcode of ``ISD::EntryToken``. The Root node is +the final side-effecting node in the token chain. For example, in a single basic +block function it would be the return node. + +One important concept for SelectionDAGs is the notion of a "legal" vs. +"illegal" DAG. A legal DAG for a target is one that only uses supported +operations and supported types. On a 32-bit PowerPC, for example, a DAG with a +value of type i1, i8, i16, or i64 would be illegal, as would a DAG that uses a +SREM or UREM operation. The `legalize types`_ and `legalize operations`_ phases +are responsible for turning an illegal DAG into a legal DAG. + +.. _SelectionDAG-Process: + +SelectionDAG Instruction Selection Process +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +SelectionDAG-based instruction selection consists of the following steps: + +#. `Build initial DAG`_ --- This stage performs a simple translation from the + input LLVM code to an illegal SelectionDAG. + +#. `Optimize SelectionDAG`_ --- This stage performs simple optimizations on the + SelectionDAG to simplify it, and recognize meta instructions (like rotates + and ``div``/``rem`` pairs) for targets that support these meta operations. + This makes the resultant code more efficient and the `select instructions + from DAG`_ phase (below) simpler. + +#. `Legalize SelectionDAG Types`_ --- This stage transforms SelectionDAG nodes + to eliminate any types that are unsupported on the target. + +#. `Optimize SelectionDAG`_ --- The SelectionDAG optimizer is run to clean up + redundancies exposed by type legalization. + +#. `Legalize SelectionDAG Ops`_ --- This stage transforms SelectionDAG nodes to + eliminate any operations that are unsupported on the target. + +#. `Optimize SelectionDAG`_ --- The SelectionDAG optimizer is run to eliminate + inefficiencies introduced by operation legalization. + +#. `Select instructions from DAG`_ --- Finally, the target instruction selector + matches the DAG operations to target instructions. This process translates + the target-independent input DAG into another DAG of target instructions. + +#. `SelectionDAG Scheduling and Formation`_ --- The last phase assigns a linear + order to the instructions in the target-instruction DAG and emits them into + the MachineFunction being compiled. This step uses traditional prepass + scheduling techniques. + +After all of these steps are complete, the SelectionDAG is destroyed and the +rest of the code generation passes are run. + +One great way to visualize what is going on here is to take advantage of a few +LLC command line options. The following options pop up a window displaying the +SelectionDAG at specific times (if you only get errors printed to the console +while using this, you probably `need to configure your +system `_ to add support for it). + +* ``-view-dag-combine1-dags`` displays the DAG after being built, before the + first optimization pass. + +* ``-view-legalize-dags`` displays the DAG before Legalization. + +* ``-view-dag-combine2-dags`` displays the DAG before the second optimization + pass. + +* ``-view-isel-dags`` displays the DAG before the Select phase. + +* ``-view-sched-dags`` displays the DAG before Scheduling. + +The ``-view-sunit-dags`` displays the Scheduler's dependency graph. This graph +is based on the final SelectionDAG, with nodes that must be scheduled together +bundled into a single scheduling-unit node, and with immediate operands and +other nodes that aren't relevant for scheduling omitted. + +.. _Build initial DAG: + +Initial SelectionDAG Construction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The initial SelectionDAG is na\ :raw-html:`ï`\ vely peephole expanded from +the LLVM input by the ``SelectionDAGBuilder`` class. The intent of this pass +is to expose as much low-level, target-specific details to the SelectionDAG as +possible. This pass is mostly hard-coded (e.g. an LLVM ``add`` turns into an +``SDNode add`` while a ``getelementptr`` is expanded into the obvious +arithmetic). This pass requires target-specific hooks to lower calls, returns, +varargs, etc. For these features, the :raw-html:`` `TargetLowering`_ +:raw-html:`` interface is used. + +.. _legalize types: +.. _Legalize SelectionDAG Types: +.. _Legalize SelectionDAG Ops: + +SelectionDAG LegalizeTypes Phase +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Legalize phase is in charge of converting a DAG to only use the types that +are natively supported by the target. + +There are two main ways of converting values of unsupported scalar types to +values of supported types: converting small types to larger types ("promoting"), +and breaking up large integer types into smaller ones ("expanding"). For +example, a target might require that all f32 values are promoted to f64 and that +all i1/i8/i16 values are promoted to i32. The same target might require that +all i64 values be expanded into pairs of i32 values. These changes can insert +sign and zero extensions as needed to make sure that the final code has the same +behavior as the input. + +There are two main ways of converting values of unsupported vector types to +value of supported types: splitting vector types, multiple times if necessary, +until a legal type is found, and extending vector types by adding elements to +the end to round them out to legal types ("widening"). If a vector gets split +all the way down to single-element parts with no supported vector type being +found, the elements are converted to scalars ("scalarizing"). + +A target implementation tells the legalizer which types are supported (and which +register class to use for them) by calling the ``addRegisterClass`` method in +its ``TargetLowering`` constructor. + +.. _legalize operations: +.. _Legalizer: + +SelectionDAG Legalize Phase +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Legalize phase is in charge of converting a DAG to only use the operations +that are natively supported by the target. + +Targets often have weird constraints, such as not supporting every operation on +every supported datatype (e.g. X86 does not support byte conditional moves and +PowerPC does not support sign-extending loads from a 16-bit memory location). +Legalize takes care of this by open-coding another sequence of operations to +emulate the operation ("expansion"), by promoting one type to a larger type that +supports the operation ("promotion"), or by using a target-specific hook to +implement the legalization ("custom"). + +A target implementation tells the legalizer which operations are not supported +(and which of the above three actions to take) by calling the +``setOperationAction`` method in its ``TargetLowering`` constructor. + +Prior to the existence of the Legalize passes, we required that every target +`selector`_ supported and handled every operator and type even if they are not +natively supported. The introduction of the Legalize phases allows all of the +canonicalization patterns to be shared across targets, and makes it very easy to +optimize the canonicalized code because it is still in the form of a DAG. + +.. _optimizations: +.. _Optimize SelectionDAG: +.. _selector: + +SelectionDAG Optimization Phase: the DAG Combiner +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The SelectionDAG optimization phase is run multiple times for code generation, +immediately after the DAG is built and once after each legalization. The first +run of the pass allows the initial code to be cleaned up (e.g. performing +optimizations that depend on knowing that the operators have restricted type +inputs). Subsequent runs of the pass clean up the messy code generated by the +Legalize passes, which allows Legalize to be very simple (it can focus on making +code legal instead of focusing on generating *good* and legal code). + +One important class of optimizations performed is optimizing inserted sign and +zero extension instructions. We currently use ad-hoc techniques, but could move +to more rigorous techniques in the future. Here are some good papers on the +subject: + +"`Widening integer arithmetic `_" :raw-html:`
` +Kevin Redwine and Norman Ramsey :raw-html:`
` +International Conference on Compiler Construction (CC) 2004 + +"`Effective sign extension elimination `_" :raw-html:`
` +Motohiro Kawahito, Hideaki Komatsu, and Toshio Nakatani :raw-html:`
` +Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language Design +and Implementation. + +.. _Select instructions from DAG: + +SelectionDAG Select Phase +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Select phase is the bulk of the target-specific code for instruction +selection. This phase takes a legal SelectionDAG as input, pattern matches the +instructions supported by the target to this DAG, and produces a new DAG of +target code. For example, consider the following LLVM fragment: + +.. code-block:: llvm + + %t1 = fadd float %W, %X + %t2 = fmul float %t1, %Y + %t3 = fadd float %t2, %Z + +This LLVM code corresponds to a SelectionDAG that looks basically like this: + +.. code-block:: llvm + + (fadd:f32 (fmul:f32 (fadd:f32 W, X), Y), Z) + +If a target supports floating point multiply-and-add (FMA) operations, one of +the adds can be merged with the multiply. On the PowerPC, for example, the +output of the instruction selector might look like this DAG: + +:: + + (FMADDS (FADDS W, X), Y, Z) + +The ``FMADDS`` instruction is a ternary instruction that multiplies its first +two operands and adds the third (as single-precision floating-point numbers). +The ``FADDS`` instruction is a simple binary single-precision add instruction. +To perform this pattern match, the PowerPC backend includes the following +instruction definitions: + +.. code-block:: text + :emphasize-lines: 4-5,9 + + def FMADDS : AForm_1<59, 29, + (ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRC, F4RC:$FRB), + "fmadds $FRT, $FRA, $FRC, $FRB", + [(set F4RC:$FRT, (fadd (fmul F4RC:$FRA, F4RC:$FRC), + F4RC:$FRB))]>; + def FADDS : AForm_2<59, 21, + (ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB), + "fadds $FRT, $FRA, $FRB", + [(set F4RC:$FRT, (fadd F4RC:$FRA, F4RC:$FRB))]>; + +The highlighted portion of the instruction definitions indicates the pattern +used to match the instructions. The DAG operators (like ``fmul``/``fadd``) +are defined in the ``include/llvm/Target/TargetSelectionDAG.td`` file. +"``F4RC``" is the register class of the input and result values. + +The TableGen DAG instruction selector generator reads the instruction patterns +in the ``.td`` file and automatically builds parts of the pattern matching code +for your target. It has the following strengths: + +* At compiler-compiler time, it analyzes your instruction patterns and tells you + if your patterns make sense or not. + +* It can handle arbitrary constraints on operands for the pattern match. In + particular, it is straight-forward to say things like "match any immediate + that is a 13-bit sign-extended value". For examples, see the ``immSExt16`` + and related ``tblgen`` classes in the PowerPC backend. + +* It knows several important identities for the patterns defined. For example, + it knows that addition is commutative, so it allows the ``FMADDS`` pattern + above to match "``(fadd X, (fmul Y, Z))``" as well as "``(fadd (fmul X, Y), + Z)``", without the target author having to specially handle this case. + +* It has a full-featured type-inferencing system. In particular, you should + rarely have to explicitly tell the system what type parts of your patterns + are. In the ``FMADDS`` case above, we didn't have to tell ``tblgen`` that all + of the nodes in the pattern are of type 'f32'. It was able to infer and + propagate this knowledge from the fact that ``F4RC`` has type 'f32'. + +* Targets can define their own (and rely on built-in) "pattern fragments". + Pattern fragments are chunks of reusable patterns that get inlined into your + patterns during compiler-compiler time. For example, the integer "``(not + x)``" operation is actually defined as a pattern fragment that expands as + "``(xor x, -1)``", since the SelectionDAG does not have a native '``not``' + operation. Targets can define their own short-hand fragments as they see fit. + See the definition of '``not``' and '``ineg``' for examples. + +* In addition to instructions, targets can specify arbitrary patterns that map + to one or more instructions using the 'Pat' class. For example, the PowerPC + has no way to load an arbitrary integer immediate into a register in one + instruction. To tell tblgen how to do this, it defines: + + :: + + // Arbitrary immediate support. Implement in terms of LIS/ORI. + def : Pat<(i32 imm:$imm), + (ORI (LIS (HI16 imm:$imm)), (LO16 imm:$imm))>; + + If none of the single-instruction patterns for loading an immediate into a + register match, this will be used. This rule says "match an arbitrary i32 + immediate, turning it into an ``ORI`` ('or a 16-bit immediate') and an ``LIS`` + ('load 16-bit immediate, where the immediate is shifted to the left 16 bits') + instruction". To make this work, the ``LO16``/``HI16`` node transformations + are used to manipulate the input immediate (in this case, take the high or low + 16-bits of the immediate). + +* When using the 'Pat' class to map a pattern to an instruction that has one + or more complex operands (like e.g. `X86 addressing mode`_), the pattern may + either specify the operand as a whole using a ``ComplexPattern``, or else it + may specify the components of the complex operand separately. The latter is + done e.g. for pre-increment instructions by the PowerPC back end: + + :: + + def STWU : DForm_1<37, (outs ptr_rc:$ea_res), (ins GPRC:$rS, memri:$dst), + "stwu $rS, $dst", LdStStoreUpd, []>, + RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">; + + def : Pat<(pre_store GPRC:$rS, ptr_rc:$ptrreg, iaddroff:$ptroff), + (STWU GPRC:$rS, iaddroff:$ptroff, ptr_rc:$ptrreg)>; + + Here, the pair of ``ptroff`` and ``ptrreg`` operands is matched onto the + complex operand ``dst`` of class ``memri`` in the ``STWU`` instruction. + +* While the system does automate a lot, it still allows you to write custom C++ + code to match special cases if there is something that is hard to + express. + +While it has many strengths, the system currently has some limitations, +primarily because it is a work in progress and is not yet finished: + +* Overall, there is no way to define or match SelectionDAG nodes that define + multiple values (e.g. ``SMUL_LOHI``, ``LOAD``, ``CALL``, etc). This is the + biggest reason that you currently still *have to* write custom C++ code + for your instruction selector. + +* There is no great way to support matching complex addressing modes yet. In + the future, we will extend pattern fragments to allow them to define multiple + values (e.g. the four operands of the `X86 addressing mode`_, which are + currently matched with custom C++ code). In addition, we'll extend fragments + so that a fragment can match multiple different patterns. + +* We don't automatically infer flags like ``isStore``/``isLoad`` yet. + +* We don't automatically generate the set of supported registers and operations + for the `Legalizer`_ yet. + +* We don't have a way of tying in custom legalized nodes yet. + +Despite these limitations, the instruction selector generator is still quite +useful for most of the binary and logical operations in typical instruction +sets. If you run into any problems or can't figure out how to do something, +please let Chris know! + +.. _Scheduling and Formation: +.. _SelectionDAG Scheduling and Formation: + +SelectionDAG Scheduling and Formation Phase +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The scheduling phase takes the DAG of target instructions from the selection +phase and assigns an order. The scheduler can pick an order depending on +various constraints of the machines (i.e. order for minimal register pressure or +try to cover instruction latencies). Once an order is established, the DAG is +converted to a list of :raw-html:`` `MachineInstr`_\s :raw-html:`` and +the SelectionDAG is destroyed. + +Note that this phase is logically separate from the instruction selection phase, +but is tied to it closely in the code because it operates on SelectionDAGs. + +Future directions for the SelectionDAG +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. Optional function-at-a-time selection. + +#. Auto-generate entire selector from ``.td`` file. + +.. _SSA-based Machine Code Optimizations: + +SSA-based Machine Code Optimizations +------------------------------------ + +To Be Written + +Live Intervals +-------------- + +Live Intervals are the ranges (intervals) where a variable is *live*. They are +used by some `register allocator`_ passes to determine if two or more virtual +registers which require the same physical register are live at the same point in +the program (i.e., they conflict). When this situation occurs, one virtual +register must be *spilled*. + +Live Variable Analysis +^^^^^^^^^^^^^^^^^^^^^^ + +The first step in determining the live intervals of variables is to calculate +the set of registers that are immediately dead after the instruction (i.e., the +instruction calculates the value, but it is never used) and the set of registers +that are used by the instruction, but are never used after the instruction +(i.e., they are killed). Live variable information is computed for +each *virtual* register and *register allocatable* physical register +in the function. This is done in a very efficient manner because it uses SSA to +sparsely compute lifetime information for virtual registers (which are in SSA +form) and only has to track physical registers within a block. Before register +allocation, LLVM can assume that physical registers are only live within a +single basic block. This allows it to do a single, local analysis to resolve +physical register lifetimes within each basic block. If a physical register is +not register allocatable (e.g., a stack pointer or condition codes), it is not +tracked. + +Physical registers may be live in to or out of a function. Live in values are +typically arguments in registers. Live out values are typically return values in +registers. Live in values are marked as such, and are given a dummy "defining" +instruction during live intervals analysis. If the last basic block of a +function is a ``return``, then it's marked as using all live out values in the +function. + +``PHI`` nodes need to be handled specially, because the calculation of the live +variable information from a depth first traversal of the CFG of the function +won't guarantee that a virtual register used by the ``PHI`` node is defined +before it's used. When a ``PHI`` node is encountered, only the definition is +handled, because the uses will be handled in other basic blocks. + +For each ``PHI`` node of the current basic block, we simulate an assignment at +the end of the current basic block and traverse the successor basic blocks. If a +successor basic block has a ``PHI`` node and one of the ``PHI`` node's operands +is coming from the current basic block, then the variable is marked as *alive* +within the current basic block and all of its predecessor basic blocks, until +the basic block with the defining instruction is encountered. + +Live Intervals Analysis +^^^^^^^^^^^^^^^^^^^^^^^ + +We now have the information available to perform the live intervals analysis and +build the live intervals themselves. We start off by numbering the basic blocks +and machine instructions. We then handle the "live-in" values. These are in +physical registers, so the physical register is assumed to be killed by the end +of the basic block. Live intervals for virtual registers are computed for some +ordering of the machine instructions ``[1, N]``. A live interval is an interval +``[i, j)``, where ``1 >= i >= j > N``, for which a variable is live. + +.. note:: + More to come... + +.. _Register Allocation: +.. _register allocator: + +Register Allocation +------------------- + +The *Register Allocation problem* consists in mapping a program +:raw-html:`` P\ :sub:`v`\ :raw-html:``, that can use an unbounded +number of virtual registers, to a program :raw-html:`` P\ :sub:`p`\ +:raw-html:`` that contains a finite (possibly small) number of physical +registers. Each target architecture has a different number of physical +registers. If the number of physical registers is not enough to accommodate all +the virtual registers, some of them will have to be mapped into memory. These +virtuals are called *spilled virtuals*. + +How registers are represented in LLVM +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In LLVM, physical registers are denoted by integer numbers that normally range +from 1 to 1023. To see how this numbering is defined for a particular +architecture, you can read the ``GenRegisterNames.inc`` file for that +architecture. For instance, by inspecting +``lib/Target/X86/X86GenRegisterInfo.inc`` we see that the 32-bit register +``EAX`` is denoted by 43, and the MMX register ``MM0`` is mapped to 65. + +Some architectures contain registers that share the same physical location. A +notable example is the X86 platform. For instance, in the X86 architecture, the +registers ``EAX``, ``AX`` and ``AL`` share the first eight bits. These physical +registers are marked as *aliased* in LLVM. Given a particular architecture, you +can check which registers are aliased by inspecting its ``RegisterInfo.td`` +file. Moreover, the class ``MCRegAliasIterator`` enumerates all the physical +registers aliased to a register. + +Physical registers, in LLVM, are grouped in *Register Classes*. Elements in the +same register class are functionally equivalent, and can be interchangeably +used. Each virtual register can only be mapped to physical registers of a +particular class. For instance, in the X86 architecture, some virtuals can only +be allocated to 8 bit registers. A register class is described by +``TargetRegisterClass`` objects. To discover if a virtual register is +compatible with a given physical, this code can be used:

+ +.. code-block:: c++ + + bool RegMapping_Fer::compatible_class(MachineFunction &mf, + unsigned v_reg, + unsigned p_reg) { + assert(TargetRegisterInfo::isPhysicalRegister(p_reg) && + "Target register must be physical"); + const TargetRegisterClass *trc = mf.getRegInfo().getRegClass(v_reg); + return trc->contains(p_reg); + } + +Sometimes, mostly for debugging purposes, it is useful to change the number of +physical registers available in the target architecture. This must be done +statically, inside the ``TargetRegsterInfo.td`` file. Just ``grep`` for +``RegisterClass``, the last parameter of which is a list of registers. Just +commenting some out is one simple way to avoid them being used. A more polite +way is to explicitly exclude some registers from the *allocation order*. See the +definition of the ``GR8`` register class in +``lib/Target/X86/X86RegisterInfo.td`` for an example of this. + +Virtual registers are also denoted by integer numbers. Contrary to physical +registers, different virtual registers never share the same number. Whereas +physical registers are statically defined in a ``TargetRegisterInfo.td`` file +and cannot be created by the application developer, that is not the case with +virtual registers. In order to create new virtual registers, use the method +``MachineRegisterInfo::createVirtualRegister()``. This method will return a new +virtual register. Use an ``IndexedMap`` to hold +information per virtual register. If you need to enumerate all virtual +registers, use the function ``TargetRegisterInfo::index2VirtReg()`` to find the +virtual register numbers: + +.. code-block:: c++ + + for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { + unsigned VirtReg = TargetRegisterInfo::index2VirtReg(i); + stuff(VirtReg); + } + +Before register allocation, the operands of an instruction are mostly virtual +registers, although physical registers may also be used. In order to check if a +given machine operand is a register, use the boolean function +``MachineOperand::isRegister()``. To obtain the integer code of a register, use +``MachineOperand::getReg()``. An instruction may define or use a register. For +instance, ``ADD reg:1026 := reg:1025 reg:1024`` defines the registers 1024, and +uses registers 1025 and 1026. Given a register operand, the method +``MachineOperand::isUse()`` informs if that register is being used by the +instruction. The method ``MachineOperand::isDef()`` informs if that registers is +being defined. + +We will call physical registers present in the LLVM bitcode before register +allocation *pre-colored registers*. Pre-colored registers are used in many +different situations, for instance, to pass parameters of functions calls, and +to store results of particular instructions. There are two types of pre-colored +registers: the ones *implicitly* defined, and those *explicitly* +defined. Explicitly defined registers are normal operands, and can be accessed +with ``MachineInstr::getOperand(int)::getReg()``. In order to check which +registers are implicitly defined by an instruction, use the +``TargetInstrInfo::get(opcode)::ImplicitDefs``, where ``opcode`` is the opcode +of the target instruction. One important difference between explicit and +implicit physical registers is that the latter are defined statically for each +instruction, whereas the former may vary depending on the program being +compiled. For example, an instruction that represents a function call will +always implicitly define or use the same set of physical registers. To read the +registers implicitly used by an instruction, use +``TargetInstrInfo::get(opcode)::ImplicitUses``. Pre-colored registers impose +constraints on any register allocation algorithm. The register allocator must +make sure that none of them are overwritten by the values of virtual registers +while still alive. + +Mapping virtual registers to physical registers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are two ways to map virtual registers to physical registers (or to memory +slots). The first way, that we will call *direct mapping*, is based on the use +of methods of the classes ``TargetRegisterInfo``, and ``MachineOperand``. The +second way, that we will call *indirect mapping*, relies on the ``VirtRegMap`` +class in order to insert loads and stores sending and getting values to and from +memory. + +The direct mapping provides more flexibility to the developer of the register +allocator; however, it is more error prone, and demands more implementation +work. Basically, the programmer will have to specify where load and store +instructions should be inserted in the target function being compiled in order +to get and store values in memory. To assign a physical register to a virtual +register present in a given operand, use ``MachineOperand::setReg(p_reg)``. To +insert a store instruction, use ``TargetInstrInfo::storeRegToStackSlot(...)``, +and to insert a load instruction, use ``TargetInstrInfo::loadRegFromStackSlot``. + +The indirect mapping shields the application developer from the complexities of +inserting load and store instructions. In order to map a virtual register to a +physical one, use ``VirtRegMap::assignVirt2Phys(vreg, preg)``. In order to map +a certain virtual register to memory, use +``VirtRegMap::assignVirt2StackSlot(vreg)``. This method will return the stack +slot where ``vreg``'s value will be located. If it is necessary to map another +virtual register to the same stack slot, use +``VirtRegMap::assignVirt2StackSlot(vreg, stack_location)``. One important point +to consider when using the indirect mapping, is that even if a virtual register +is mapped to memory, it still needs to be mapped to a physical register. This +physical register is the location where the virtual register is supposed to be +found before being stored or after being reloaded. + +If the indirect strategy is used, after all the virtual registers have been +mapped to physical registers or stack slots, it is necessary to use a spiller +object to place load and store instructions in the code. Every virtual that has +been mapped to a stack slot will be stored to memory after been defined and will +be loaded before being used. The implementation of the spiller tries to recycle +load/store instructions, avoiding unnecessary instructions. For an example of +how to invoke the spiller, see ``RegAllocLinearScan::runOnMachineFunction`` in +``lib/CodeGen/RegAllocLinearScan.cpp``. + +Handling two address instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With very rare exceptions (e.g., function calls), the LLVM machine code +instructions are three address instructions. That is, each instruction is +expected to define at most one register, and to use at most two registers. +However, some architectures use two address instructions. In this case, the +defined register is also one of the used register. For instance, an instruction +such as ``ADD %EAX, %EBX``, in X86 is actually equivalent to ``%EAX = %EAX + +%EBX``. + +In order to produce correct code, LLVM must convert three address instructions +that represent two address instructions into true two address instructions. LLVM +provides the pass ``TwoAddressInstructionPass`` for this specific purpose. It +must be run before register allocation takes place. After its execution, the +resulting code may no longer be in SSA form. This happens, for instance, in +situations where an instruction such as ``%a = ADD %b %c`` is converted to two +instructions such as: + +:: + + %a = MOVE %b + %a = ADD %a %c + +Notice that, internally, the second instruction is represented as ``ADD +%a[def/use] %c``. I.e., the register operand ``%a`` is both used and defined by +the instruction. + +The SSA deconstruction phase +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An important transformation that happens during register allocation is called +the *SSA Deconstruction Phase*. The SSA form simplifies many analyses that are +performed on the control flow graph of programs. However, traditional +instruction sets do not implement PHI instructions. Thus, in order to generate +executable code, compilers must replace PHI instructions with other instructions +that preserve their semantics. + +There are many ways in which PHI instructions can safely be removed from the +target code. The most traditional PHI deconstruction algorithm replaces PHI +instructions with copy instructions. That is the strategy adopted by LLVM. The +SSA deconstruction algorithm is implemented in +``lib/CodeGen/PHIElimination.cpp``. In order to invoke this pass, the identifier +``PHIEliminationID`` must be marked as required in the code of the register +allocator. + +Instruction folding +^^^^^^^^^^^^^^^^^^^ + +*Instruction folding* is an optimization performed during register allocation +that removes unnecessary copy instructions. For instance, a sequence of +instructions such as: + +:: + + %EBX = LOAD %mem_address + %EAX = COPY %EBX + +can be safely substituted by the single instruction: + +:: + + %EAX = LOAD %mem_address + +Instructions can be folded with the +``TargetRegisterInfo::foldMemoryOperand(...)`` method. Care must be taken when +folding instructions; a folded instruction can be quite different from the +original instruction. See ``LiveIntervals::addIntervalsForSpills`` in +``lib/CodeGen/LiveIntervalAnalysis.cpp`` for an example of its use. + +Built in register allocators +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The LLVM infrastructure provides the application developer with three different +register allocators: + +* *Fast* --- This register allocator is the default for debug builds. It + allocates registers on a basic block level, attempting to keep values in + registers and reusing registers as appropriate. + +* *Basic* --- This is an incremental approach to register allocation. Live + ranges are assigned to registers one at a time in an order that is driven by + heuristics. Since code can be rewritten on-the-fly during allocation, this + framework allows interesting allocators to be developed as extensions. It is + not itself a production register allocator but is a potentially useful + stand-alone mode for triaging bugs and as a performance baseline. + +* *Greedy* --- *The default allocator*. This is a highly tuned implementation of + the *Basic* allocator that incorporates global live range splitting. This + allocator works hard to minimize the cost of spill code. + +* *PBQP* --- A Partitioned Boolean Quadratic Programming (PBQP) based register + allocator. This allocator works by constructing a PBQP problem representing + the register allocation problem under consideration, solving this using a PBQP + solver, and mapping the solution back to a register assignment. + +The type of register allocator used in ``llc`` can be chosen with the command +line option ``-regalloc=...``: + +.. code-block:: bash + + $ llc -regalloc=linearscan file.bc -o ln.s + $ llc -regalloc=fast file.bc -o fa.s + $ llc -regalloc=pbqp file.bc -o pbqp.s + +.. _Prolog/Epilog Code Insertion: + +Prolog/Epilog Code Insertion +---------------------------- + +Compact Unwind + +Throwing an exception requires *unwinding* out of a function. The information on +how to unwind a given function is traditionally expressed in DWARF unwind +(a.k.a. frame) info. But that format was originally developed for debuggers to +backtrace, and each Frame Description Entry (FDE) requires ~20-30 bytes per +function. There is also the cost of mapping from an address in a function to the +corresponding FDE at runtime. An alternative unwind encoding is called *compact +unwind* and requires just 4-bytes per function. + +The compact unwind encoding is a 32-bit value, which is encoded in an +architecture-specific way. It specifies which registers to restore and from +where, and how to unwind out of the function. When the linker creates a final +linked image, it will create a ``__TEXT,__unwind_info`` section. This section is +a small and fast way for the runtime to access unwind info for any given +function. If we emit compact unwind info for the function, that compact unwind +info will be encoded in the ``__TEXT,__unwind_info`` section. If we emit DWARF +unwind info, the ``__TEXT,__unwind_info`` section will contain the offset of the +FDE in the ``__TEXT,__eh_frame`` section in the final linked image. + +For X86, there are three modes for the compact unwind encoding: + +*Function with a Frame Pointer (``EBP`` or ``RBP``)* + ``EBP/RBP``-based frame, where ``EBP/RBP`` is pushed onto the stack + immediately after the return address, then ``ESP/RSP`` is moved to + ``EBP/RBP``. Thus to unwind, ``ESP/RSP`` is restored with the current + ``EBP/RBP`` value, then ``EBP/RBP`` is restored by popping the stack, and the + return is done by popping the stack once more into the PC. All non-volatile + registers that need to be restored must have been saved in a small range on + the stack that starts ``EBP-4`` to ``EBP-1020`` (``RBP-8`` to + ``RBP-1020``). The offset (divided by 4 in 32-bit mode and 8 in 64-bit mode) + is encoded in bits 16-23 (mask: ``0x00FF0000``). The registers saved are + encoded in bits 0-14 (mask: ``0x00007FFF``) as five 3-bit entries from the + following table: + + ============== ============= =============== + Compact Number i386 Register x86-64 Register + ============== ============= =============== + 1 ``EBX`` ``RBX`` + 2 ``ECX`` ``R12`` + 3 ``EDX`` ``R13`` + 4 ``EDI`` ``R14`` + 5 ``ESI`` ``R15`` + 6 ``EBP`` ``RBP`` + ============== ============= =============== + +*Frameless with a Small Constant Stack Size (``EBP`` or ``RBP`` is not used as a frame pointer)* + To return, a constant (encoded in the compact unwind encoding) is added to the + ``ESP/RSP``. Then the return is done by popping the stack into the PC. All + non-volatile registers that need to be restored must have been saved on the + stack immediately after the return address. The stack size (divided by 4 in + 32-bit mode and 8 in 64-bit mode) is encoded in bits 16-23 (mask: + ``0x00FF0000``). There is a maximum stack size of 1024 bytes in 32-bit mode + and 2048 in 64-bit mode. The number of registers saved is encoded in bits 9-12 + (mask: ``0x00001C00``). Bits 0-9 (mask: ``0x000003FF``) contain which + registers were saved and their order. (See the + ``encodeCompactUnwindRegistersWithoutFrame()`` function in + ``lib/Target/X86FrameLowering.cpp`` for the encoding algorithm.) + +*Frameless with a Large Constant Stack Size (``EBP`` or ``RBP`` is not used as a frame pointer)* + This case is like the "Frameless with a Small Constant Stack Size" case, but + the stack size is too large to encode in the compact unwind encoding. Instead + it requires that the function contains "``subl $nnnnnn, %esp``" in its + prolog. The compact encoding contains the offset to the ``$nnnnnn`` value in + the function in bits 9-12 (mask: ``0x00001C00``). + +.. _Late Machine Code Optimizations: + +Late Machine Code Optimizations +------------------------------- + +.. note:: + + To Be Written + +.. _Code Emission: + +Code Emission +------------- + +The code emission step of code generation is responsible for lowering from the +code generator abstractions (like `MachineFunction`_, `MachineInstr`_, etc) down +to the abstractions used by the MC layer (`MCInst`_, `MCStreamer`_, etc). This +is done with a combination of several different classes: the (misnamed) +target-independent AsmPrinter class, target-specific subclasses of AsmPrinter +(such as SparcAsmPrinter), and the TargetLoweringObjectFile class. + +Since the MC layer works at the level of abstraction of object files, it doesn't +have a notion of functions, global variables etc. Instead, it thinks about +labels, directives, and instructions. A key class used at this time is the +MCStreamer class. This is an abstract API that is implemented in different ways +(e.g. to output a .s file, output an ELF .o file, etc) that is effectively an +"assembler API". MCStreamer has one method per directive, such as EmitLabel, +EmitSymbolAttribute, SwitchSection, etc, which directly correspond to assembly +level directives. + +If you are interested in implementing a code generator for a target, there are +three important things that you have to implement for your target: + +#. First, you need a subclass of AsmPrinter for your target. This class + implements the general lowering process converting MachineFunction's into MC + label constructs. The AsmPrinter base class provides a number of useful + methods and routines, and also allows you to override the lowering process in + some important ways. You should get much of the lowering for free if you are + implementing an ELF, COFF, or MachO target, because the + TargetLoweringObjectFile class implements much of the common logic. + +#. Second, you need to implement an instruction printer for your target. The + instruction printer takes an `MCInst`_ and renders it to a raw_ostream as + text. Most of this is automatically generated from the .td file (when you + specify something like "``add $dst, $src1, $src2``" in the instructions), but + you need to implement routines to print operands. + +#. Third, you need to implement code that lowers a `MachineInstr`_ to an MCInst, + usually implemented in "MCInstLower.cpp". This lowering process is + often target specific, and is responsible for turning jump table entries, + constant pool indices, global variable addresses, etc into MCLabels as + appropriate. This translation layer is also responsible for expanding pseudo + ops used by the code generator into the actual machine instructions they + correspond to. The MCInsts that are generated by this are fed into the + instruction printer or the encoder. + +Finally, at your choosing, you can also implement an subclass of MCCodeEmitter +which lowers MCInst's into machine code bytes and relocations. This is +important if you want to support direct .o file emission, or would like to +implement an assembler for your target. + +VLIW Packetizer +--------------- + +In a Very Long Instruction Word (VLIW) architecture, the compiler is responsible +for mapping instructions to functional-units available on the architecture. To +that end, the compiler creates groups of instructions called *packets* or +*bundles*. The VLIW packetizer in LLVM is a target-independent mechanism to +enable the packetization of machine instructions. + +Mapping from instructions to functional units +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Instructions in a VLIW target can typically be mapped to multiple functional +units. During the process of packetizing, the compiler must be able to reason +about whether an instruction can be added to a packet. This decision can be +complex since the compiler has to examine all possible mappings of instructions +to functional units. Therefore to alleviate compilation-time complexity, the +VLIW packetizer parses the instruction classes of a target and generates tables +at compiler build time. These tables can then be queried by the provided +machine-independent API to determine if an instruction can be accommodated in a +packet. + +How the packetization tables are generated and used +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The packetizer reads instruction classes from a target's itineraries and creates +a deterministic finite automaton (DFA) to represent the state of a packet. A DFA +consists of three major elements: inputs, states, and transitions. The set of +inputs for the generated DFA represents the instruction being added to a +packet. The states represent the possible consumption of functional units by +instructions in a packet. In the DFA, transitions from one state to another +occur on the addition of an instruction to an existing packet. If there is a +legal mapping of functional units to instructions, then the DFA contains a +corresponding transition. The absence of a transition indicates that a legal +mapping does not exist and that the instruction cannot be added to the packet. + +To generate tables for a VLIW target, add *Target*\ GenDFAPacketizer.inc as a +target to the Makefile in the target directory. The exported API provides three +functions: ``DFAPacketizer::clearResources()``, +``DFAPacketizer::reserveResources(MachineInstr *MI)``, and +``DFAPacketizer::canReserveResources(MachineInstr *MI)``. These functions allow +a target packetizer to add an instruction to an existing packet and to check +whether an instruction can be added to a packet. See +``llvm/CodeGen/DFAPacketizer.h`` for more information. + +Implementing a Native Assembler +=============================== + +Though you're probably reading this because you want to write or maintain a +compiler backend, LLVM also fully supports building a native assembler. +We've tried hard to automate the generation of the assembler from the .td files +(in particular the instruction syntax and encodings), which means that a large +part of the manual and repetitive data entry can be factored and shared with the +compiler. + +Instruction Parsing +------------------- + +.. note:: + + To Be Written + + +Instruction Alias Processing +---------------------------- + +Once the instruction is parsed, it enters the MatchInstructionImpl function. +The MatchInstructionImpl function performs alias processing and then does actual +matching. + +Alias processing is the phase that canonicalizes different lexical forms of the +same instructions down to one representation. There are several different kinds +of alias that are possible to implement and they are listed below in the order +that they are processed (which is in order from simplest/weakest to most +complex/powerful). Generally you want to use the first alias mechanism that +meets the needs of your instruction, because it will allow a more concise +description. + +Mnemonic Aliases +^^^^^^^^^^^^^^^^ + +The first phase of alias processing is simple instruction mnemonic remapping for +classes of instructions which are allowed with two different mnemonics. This +phase is a simple and unconditionally remapping from one input mnemonic to one +output mnemonic. It isn't possible for this form of alias to look at the +operands at all, so the remapping must apply for all forms of a given mnemonic. +Mnemonic aliases are defined simply, for example X86 has: + +:: + + def : MnemonicAlias<"cbw", "cbtw">; + def : MnemonicAlias<"smovq", "movsq">; + def : MnemonicAlias<"fldcww", "fldcw">; + def : MnemonicAlias<"fucompi", "fucomip">; + def : MnemonicAlias<"ud2a", "ud2">; + +... and many others. With a MnemonicAlias definition, the mnemonic is remapped +simply and directly. Though MnemonicAlias's can't look at any aspect of the +instruction (such as the operands) they can depend on global modes (the same +ones supported by the matcher), through a Requires clause: + +:: + + def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>; + def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>; + +In this example, the mnemonic gets mapped into different a new one depending on +the current instruction set. + +Instruction Aliases +^^^^^^^^^^^^^^^^^^^ + +The most general phase of alias processing occurs while matching is happening: +it provides new forms for the matcher to match along with a specific instruction +to generate. An instruction alias has two parts: the string to match and the +instruction to generate. For example: + +:: + + def : InstAlias<"movsx $src, $dst", (MOVSX16rr8W GR16:$dst, GR8 :$src)>; + def : InstAlias<"movsx $src, $dst", (MOVSX16rm8W GR16:$dst, i8mem:$src)>; + def : InstAlias<"movsx $src, $dst", (MOVSX32rr8 GR32:$dst, GR8 :$src)>; + def : InstAlias<"movsx $src, $dst", (MOVSX32rr16 GR32:$dst, GR16 :$src)>; + def : InstAlias<"movsx $src, $dst", (MOVSX64rr8 GR64:$dst, GR8 :$src)>; + def : InstAlias<"movsx $src, $dst", (MOVSX64rr16 GR64:$dst, GR16 :$src)>; + def : InstAlias<"movsx $src, $dst", (MOVSX64rr32 GR64:$dst, GR32 :$src)>; + +This shows a powerful example of the instruction aliases, matching the same +mnemonic in multiple different ways depending on what operands are present in +the assembly. The result of instruction aliases can include operands in a +different order than the destination instruction, and can use an input multiple +times, for example: + +:: + + def : InstAlias<"clrb $reg", (XOR8rr GR8 :$reg, GR8 :$reg)>; + def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg)>; + def : InstAlias<"clrl $reg", (XOR32rr GR32:$reg, GR32:$reg)>; + def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)>; + +This example also shows that tied operands are only listed once. In the X86 +backend, XOR8rr has two input GR8's and one output GR8 (where an input is tied +to the output). InstAliases take a flattened operand list without duplicates +for tied operands. The result of an instruction alias can also use immediates +and fixed physical registers which are added as simple immediate operands in the +result, for example: + +:: + + // Fixed Immediate operand. + def : InstAlias<"aad", (AAD8i8 10)>; + + // Fixed register operand. + def : InstAlias<"fcomi", (COM_FIr ST1)>; + + // Simple alias. + def : InstAlias<"fcomi $reg", (COM_FIr RST:$reg)>; + +Instruction aliases can also have a Requires clause to make them subtarget +specific. + +If the back-end supports it, the instruction printer can automatically emit the +alias rather than what's being aliased. It typically leads to better, more +readable code. If it's better to print out what's being aliased, then pass a '0' +as the third parameter to the InstAlias definition. + +Instruction Matching +-------------------- + +.. note:: + + To Be Written + +.. _Implementations of the abstract target description interfaces: +.. _implement the target description: + +Target-specific Implementation Notes +==================================== + +This section of the document explains features or design decisions that are +specific to the code generator for a particular target. First we start with a +table that summarizes what features are supported by each target. + +.. _target-feature-matrix: + +Target Feature Matrix +--------------------- + +Note that this table does not include the C backend or Cpp backends, since they +do not use the target independent code generator infrastructure. It also +doesn't list features that are not supported fully by any target yet. It +considers a feature to be supported if at least one subtarget supports it. A +feature being supported means that it is useful and works for most cases, it +does not indicate that there are zero known bugs in the implementation. Here is +the key: + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`
UnknownNot ApplicableNo supportPartial SupportComplete Support
` + +Here is the table: + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` + +:raw-html:`
Target
FeatureARMHexagonMSP430MipsNVPTXPowerPCSparcSystemZX86XCore
is generally reliable
assembly parser
disassembler
inline asm
jit*
.o file writing
tail calls
segmented stacks *
` + +.. _feat_reliable: + +Is Generally Reliable +^^^^^^^^^^^^^^^^^^^^^ + +This box indicates whether the target is considered to be production quality. +This indicates that the target has been used as a static compiler to compile +large amounts of code by a variety of different people and is in continuous use. + +.. _feat_asmparser: + +Assembly Parser +^^^^^^^^^^^^^^^ + +This box indicates whether the target supports parsing target specific .s files +by implementing the MCAsmParser interface. This is required for llvm-mc to be +able to act as a native assembler and is required for inline assembly support in +the native .o file writer. + +.. _feat_disassembler: + +Disassembler +^^^^^^^^^^^^ + +This box indicates whether the target supports the MCDisassembler API for +disassembling machine opcode bytes into MCInst's. + +.. _feat_inlineasm: + +Inline Asm +^^^^^^^^^^ + +This box indicates whether the target supports most popular inline assembly +constraints and modifiers. + +.. _feat_jit: + +JIT Support +^^^^^^^^^^^ + +This box indicates whether the target supports the JIT compiler through the +ExecutionEngine interface. + +.. _feat_jit_arm: + +The ARM backend has basic support for integer code in ARM codegen mode, but +lacks NEON and full Thumb support. + +.. _feat_objectwrite: + +.o File Writing +^^^^^^^^^^^^^^^ + +This box indicates whether the target supports writing .o files (e.g. MachO, +ELF, and/or COFF) files directly from the target. Note that the target also +must include an assembly parser and general inline assembly support for full +inline assembly support in the .o writer. + +Targets that don't support this feature can obviously still write out .o files, +they just rely on having an external assembler to translate from a .s file to a +.o file (as is the case for many C compilers). + +.. _feat_tailcall: + +Tail Calls +^^^^^^^^^^ + +This box indicates whether the target supports guaranteed tail calls. These are +calls marked "`tail `_" and use the fastcc calling +convention. Please see the `tail call section more more details`_. + +.. _feat_segstacks: + +Segmented Stacks +^^^^^^^^^^^^^^^^ + +This box indicates whether the target supports segmented stacks. This replaces +the traditional large C stack with many linked segments. It is compatible with +the `gcc implementation `_ used by the Go +front end. + +.. _feat_segstacks_x86: + +Basic support exists on the X86 backend. Currently vararg doesn't work and the +object files are not marked the way the gold linker expects, but simple Go +programs can be built by dragonegg. + +.. _tail call section more more details: + +Tail call optimization +---------------------- + +Tail call optimization, callee reusing the stack of the caller, is currently +supported on x86/x86-64 and PowerPC. It is performed if: + +* Caller and callee have the calling convention ``fastcc``, ``cc 10`` (GHC + calling convention) or ``cc 11`` (HiPE calling convention). + +* The call is a tail call - in tail position (ret immediately follows call and + ret uses value of call or is void). + +* Option ``-tailcallopt`` is enabled. + +* Platform specific constraints are met. + +x86/x86-64 constraints: + +* No variable argument lists are used. + +* On x86-64 when generating GOT/PIC code only module-local calls (visibility = + hidden or protected) are supported. + +PowerPC constraints: + +* No variable argument lists are used. + +* No byval parameters are used. + +* On ppc32/64 GOT/PIC only module-local calls (visibility = hidden or protected) + are supported. + +Example: + +Call as ``llc -tailcallopt test.ll``. + +.. code-block:: llvm + + declare fastcc i32 @tailcallee(i32 inreg %a1, i32 inreg %a2, i32 %a3, i32 %a4) + + define fastcc i32 @tailcaller(i32 %in1, i32 %in2) { + %l1 = add i32 %in1, %in2 + %tmp = tail call fastcc i32 @tailcallee(i32 %in1 inreg, i32 %in2 inreg, i32 %in1, i32 %l1) + ret i32 %tmp + } + +Implications of ``-tailcallopt``: + +To support tail call optimization in situations where the callee has more +arguments than the caller a 'callee pops arguments' convention is used. This +currently causes each ``fastcc`` call that is not tail call optimized (because +one or more of above constraints are not met) to be followed by a readjustment +of the stack. So performance might be worse in such cases. + +Sibling call optimization +------------------------- + +Sibling call optimization is a restricted form of tail call optimization. +Unlike tail call optimization described in the previous section, it can be +performed automatically on any tail calls when ``-tailcallopt`` option is not +specified. + +Sibling call optimization is currently performed on x86/x86-64 when the +following constraints are met: + +* Caller and callee have the same calling convention. It can be either ``c`` or + ``fastcc``. + +* The call is a tail call - in tail position (ret immediately follows call and + ret uses value of call or is void). + +* Caller and callee have matching return type or the callee result is not used. + +* If any of the callee arguments are being passed in stack, they must be + available in caller's own incoming argument stack and the frame offsets must + be the same. + +Example: + +.. code-block:: llvm + + declare i32 @bar(i32, i32) + + define i32 @foo(i32 %a, i32 %b, i32 %c) { + entry: + %0 = tail call i32 @bar(i32 %a, i32 %b) + ret i32 %0 + } + +The X86 backend +--------------- + +The X86 code generator lives in the ``lib/Target/X86`` directory. This code +generator is capable of targeting a variety of x86-32 and x86-64 processors, and +includes support for ISA extensions such as MMX and SSE. + +X86 Target Triples supported +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following are the known target triples that are supported by the X86 +backend. This is not an exhaustive list, and it would be useful to add those +that people test. + +* **i686-pc-linux-gnu** --- Linux + +* **i386-unknown-freebsd5.3** --- FreeBSD 5.3 + +* **i686-pc-cygwin** --- Cygwin on Win32 + +* **i686-pc-mingw32** --- MingW on Win32 + +* **i386-pc-mingw32msvc** --- MingW crosscompiler on Linux + +* **i686-apple-darwin*** --- Apple Darwin on X86 + +* **x86_64-unknown-linux-gnu** --- Linux + +X86 Calling Conventions supported +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following target-specific calling conventions are known to backend: + +* **x86_StdCall** --- stdcall calling convention seen on Microsoft Windows + platform (CC ID = 64). + +* **x86_FastCall** --- fastcall calling convention seen on Microsoft Windows + platform (CC ID = 65). + +* **x86_ThisCall** --- Similar to X86_StdCall. Passes first argument in ECX, + others via stack. Callee is responsible for stack cleaning. This convention is + used by MSVC by default for methods in its ABI (CC ID = 70). + +.. _X86 addressing mode: + +Representing X86 addressing modes in MachineInstrs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The x86 has a very flexible way of accessing memory. It is capable of forming +memory addresses of the following expression directly in integer instructions +(which use ModR/M addressing): + +:: + + SegmentReg: Base + [1,2,4,8] * IndexReg + Disp32 + +In order to represent this, LLVM tracks no less than 5 operands for each memory +operand of this form. This means that the "load" form of '``mov``' has the +following ``MachineOperand``\s in this order: + +:: + + Index: 0 | 1 2 3 4 5 + Meaning: DestReg, | BaseReg, Scale, IndexReg, Displacement Segment + OperandTy: VirtReg, | VirtReg, UnsImm, VirtReg, SignExtImm PhysReg + +Stores, and all other instructions, treat the four memory operands in the same +way and in the same order. If the segment register is unspecified (regno = 0), +then no segment override is generated. "Lea" operations do not have a segment +register specified, so they only have 4 operands for their memory reference. + +X86 address spaces supported +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +x86 has a feature which provides the ability to perform loads and stores to +different address spaces via the x86 segment registers. A segment override +prefix byte on an instruction causes the instruction's memory access to go to +the specified segment. LLVM address space 0 is the default address space, which +includes the stack, and any unqualified memory accesses in a program. Address +spaces 1-255 are currently reserved for user-defined code. The GS-segment is +represented by address space 256, while the FS-segment is represented by address +space 257. Other x86 segments have yet to be allocated address space +numbers. + +While these address spaces may seem similar to TLS via the ``thread_local`` +keyword, and often use the same underlying hardware, there are some fundamental +differences. + +The ``thread_local`` keyword applies to global variables and specifies that they +are to be allocated in thread-local memory. There are no type qualifiers +involved, and these variables can be pointed to with normal pointers and +accessed with normal loads and stores. The ``thread_local`` keyword is +target-independent at the LLVM IR level (though LLVM doesn't yet have +implementations of it for some configurations) + +Special address spaces, in contrast, apply to static types. Every load and store +has a particular address space in its address operand type, and this is what +determines which address space is accessed. LLVM ignores these special address +space qualifiers on global variables, and does not provide a way to directly +allocate storage in them. At the LLVM IR level, the behavior of these special +address spaces depends in part on the underlying OS or runtime environment, and +they are specific to x86 (and LLVM doesn't yet handle them correctly in some +cases). + +Some operating systems and runtime environments use (or may in the future use) +the FS/GS-segment registers for various low-level purposes, so care should be +taken when considering them. + +Instruction naming +^^^^^^^^^^^^^^^^^^ + +An instruction name consists of the base name, a default operand size, and a a +character per operand with an optional special size. For example: + +:: + + ADD8rr -> add, 8-bit register, 8-bit register + IMUL16rmi -> imul, 16-bit register, 16-bit memory, 16-bit immediate + IMUL16rmi8 -> imul, 16-bit register, 16-bit memory, 8-bit immediate + MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory + +The PowerPC backend +------------------- + +The PowerPC code generator lives in the lib/Target/PowerPC directory. The code +generation is retargetable to several variations or *subtargets* of the PowerPC +ISA; including ppc32, ppc64 and altivec. + +LLVM PowerPC ABI +^^^^^^^^^^^^^^^^ + +LLVM follows the AIX PowerPC ABI, with two deviations. LLVM uses a PC relative +(PIC) or static addressing for accessing global values, so no TOC (r2) is +used. Second, r31 is used as a frame pointer to allow dynamic growth of a stack +frame. LLVM takes advantage of having no TOC to provide space to save the frame +pointer in the PowerPC linkage area of the caller frame. Other details of +PowerPC ABI can be found at `PowerPC ABI +`_\ +. Note: This link describes the 32 bit ABI. The 64 bit ABI is similar except +space for GPRs are 8 bytes wide (not 4) and r13 is reserved for system use. + +Frame Layout +^^^^^^^^^^^^ + +The size of a PowerPC frame is usually fixed for the duration of a function's +invocation. Since the frame is fixed size, all references into the frame can be +accessed via fixed offsets from the stack pointer. The exception to this is +when dynamic alloca or variable sized arrays are present, then a base pointer +(r31) is used as a proxy for the stack pointer and stack pointer is free to grow +or shrink. A base pointer is also used if llvm-gcc is not passed the +-fomit-frame-pointer flag. The stack pointer is always aligned to 16 bytes, so +that space allocated for altivec vectors will be properly aligned. + +An invocation frame is laid out as follows (low memory at top): + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`
Linkage

Parameter area

Dynamic area

Locals area

Saved registers area


Previous Frame

` + +The *linkage* area is used by a callee to save special registers prior to +allocating its own frame. Only three entries are relevant to LLVM. The first +entry is the previous stack pointer (sp), aka link. This allows probing tools +like gdb or exception handlers to quickly scan the frames in the stack. A +function epilog can also use the link to pop the frame from the stack. The +third entry in the linkage area is used to save the return address from the lr +register. Finally, as mentioned above, the last entry is used to save the +previous frame pointer (r31.) The entries in the linkage area are the size of a +GPR, thus the linkage area is 24 bytes long in 32 bit mode and 48 bytes in 64 +bit mode. + +32 bit linkage area: + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`
0Saved SP (r1)
4Saved CR
8Saved LR
12Reserved
16Reserved
20Saved FP (r31)
` + +64 bit linkage area: + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`
0Saved SP (r1)
8Saved CR
16Saved LR
24Reserved
32Reserved
40Saved FP (r31)
` + +The *parameter area* is used to store arguments being passed to a callee +function. Following the PowerPC ABI, the first few arguments are actually +passed in registers, with the space in the parameter area unused. However, if +there are not enough registers or the callee is a thunk or vararg function, +these register arguments can be spilled into the parameter area. Thus, the +parameter area must be large enough to store all the parameters for the largest +call sequence made by the caller. The size must also be minimally large enough +to spill registers r3-r10. This allows callees blind to the call signature, +such as thunks and vararg functions, enough space to cache the argument +registers. Therefore, the parameter area is minimally 32 bytes (64 bytes in 64 +bit mode.) Also note that since the parameter area is a fixed offset from the +top of the frame, that a callee can access its spilt arguments using fixed +offsets from the stack pointer (or base pointer.) + +Combining the information about the linkage, parameter areas and alignment. A +stack frame is minimally 64 bytes in 32 bit mode and 128 bytes in 64 bit mode. + +The *dynamic area* starts out as size zero. If a function uses dynamic alloca +then space is added to the stack, the linkage and parameter areas are shifted to +top of stack, and the new space is available immediately below the linkage and +parameter areas. The cost of shifting the linkage and parameter areas is minor +since only the link value needs to be copied. The link value can be easily +fetched by adding the original frame size to the base pointer. Note that +allocations in the dynamic space need to observe 16 byte alignment. + +The *locals area* is where the llvm compiler reserves space for local variables. + +The *saved registers area* is where the llvm compiler spills callee saved +registers on entry to the callee. + +Prolog/Epilog +^^^^^^^^^^^^^ + +The llvm prolog and epilog are the same as described in the PowerPC ABI, with +the following exceptions. Callee saved registers are spilled after the frame is +created. This allows the llvm epilog/prolog support to be common with other +targets. The base pointer callee saved register r31 is saved in the TOC slot of +linkage area. This simplifies allocation of space for the base pointer and +makes it convenient to locate programatically and during debugging. + +Dynamic Allocation +^^^^^^^^^^^^^^^^^^ + +.. note:: + + TODO - More to come. + +The NVPTX backend +----------------- + +The NVPTX code generator under lib/Target/NVPTX is an open-source version of +the NVIDIA NVPTX code generator for LLVM. It is contributed by NVIDIA and is +a port of the code generator used in the CUDA compiler (nvcc). It targets the +PTX 3.0/3.1 ISA and can target any compute capability greater than or equal to +2.0 (Fermi). + +This target is of production quality and should be completely compatible with +the official NVIDIA toolchain. + +Code Generator Options: + +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`` +:raw-html:`
OptionDescription
sm_20Set shader model/compute capability to 2.0
sm_21Set shader model/compute capability to 2.1
sm_30Set shader model/compute capability to 3.0
sm_35Set shader model/compute capability to 3.5
ptx30Target PTX 3.0
ptx31Target PTX 3.1
` + diff --git a/docs/CodingStandards.rst b/docs/CodingStandards.rst new file mode 100644 index 00000000..9418680e --- /dev/null +++ b/docs/CodingStandards.rst @@ -0,0 +1,1348 @@ +===================== +LLVM Coding Standards +===================== + +.. contents:: + :local: + +Introduction +============ + +This document attempts to describe a few coding standards that are being used in +the LLVM source tree. Although no coding standards should be regarded as +absolute requirements to be followed in all instances, coding standards are +particularly important for large-scale code bases that follow a library-based +design (like LLVM). + +This document intentionally does not prescribe fixed standards for religious +issues such as brace placement and space usage. For issues like this, follow +the golden rule: + +.. _Golden Rule: + + **If you are extending, enhancing, or bug fixing already implemented code, + use the style that is already being used so that the source is uniform and + easy to follow.** + +Note that some code bases (e.g. ``libc++``) have really good reasons to deviate +from the coding standards. In the case of ``libc++``, this is because the +naming and other conventions are dictated by the C++ standard. If you think +there is a specific good reason to deviate from the standards here, please bring +it up on the LLVMdev mailing list. + +There are some conventions that are not uniformly followed in the code base +(e.g. the naming convention). This is because they are relatively new, and a +lot of code was written before they were put in place. Our long term goal is +for the entire codebase to follow the convention, but we explicitly *do not* +want patches that do large-scale reformating of existing code. On the other +hand, it is reasonable to rename the methods of a class if you're about to +change it in some other way. Just do the reformating as a separate commit from +the functionality change. + +The ultimate goal of these guidelines is the increase readability and +maintainability of our common source base. If you have suggestions for topics to +be included, please mail them to `Chris `_. + +Mechanical Source Issues +======================== + +Source Code Formatting +---------------------- + +Commenting +^^^^^^^^^^ + +Comments are one critical part of readability and maintainability. Everyone +knows they should comment their code, and so should you. When writing comments, +write them as English prose, which means they should use proper capitalization, +punctuation, etc. Aim to describe what the code is trying to do and why, not +*how* it does it at a micro level. Here are a few critical things to document: + +.. _header file comment: + +File Headers +"""""""""""" + +Every source file should have a header on it that describes the basic purpose of +the file. If a file does not have a header, it should not be checked into the +tree. The standard header looks like this: + +.. code-block:: c++ + + //===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file is distributed under the University of Illinois Open Source + // License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + /// + /// \file + /// \brief This file contains the declaration of the Instruction class, which is + /// the base class for all of the VM instructions. + /// + //===----------------------------------------------------------------------===// + +A few things to note about this particular format: The "``-*- C++ -*-``" string +on the first line is there to tell Emacs that the source file is a C++ file, not +a C file (Emacs assumes ``.h`` files are C files by default). + +.. note:: + + This tag is not necessary in ``.cpp`` files. The name of the file is also + on the first line, along with a very short description of the purpose of the + file. This is important when printing out code and flipping though lots of + pages. + +The next section in the file is a concise note that defines the license that the +file is released under. This makes it perfectly clear what terms the source +code can be distributed under and should not be modified in any way. + +The main body is a ``doxygen`` comment describing the purpose of the file. It +should have a ``\brief`` command that describes the file in one or two +sentences. Any additional information should be separated by a blank line. If +an algorithm is being implemented or something tricky is going on, a reference +to the paper where it is published should be included, as well as any notes or +*gotchas* in the code to watch out for. + +Class overviews +""""""""""""""" + +Classes are one fundamental part of a good object oriented design. As such, a +class definition should have a comment block that explains what the class is +used for and how it works. Every non-trivial class is expected to have a +``doxygen`` comment block. + +Method information +"""""""""""""""""" + +Methods defined in a class (as well as any global functions) should also be +documented properly. A quick note about what it does and a description of the +borderline behaviour is all that is necessary here (unless something +particularly tricky or insidious is going on). The hope is that people can +figure out how to use your interfaces without reading the code itself. + +Good things to talk about here are what happens when something unexpected +happens: does the method return null? Abort? Format your hard disk? + +Comment Formatting +^^^^^^^^^^^^^^^^^^ + +In general, prefer C++ style (``//``) comments. They take less space, require +less typing, don't have nesting problems, etc. There are a few cases when it is +useful to use C style (``/* */``) comments however: + +#. When writing C code: Obviously if you are writing C code, use C style + comments. + +#. When writing a header file that may be ``#include``\d by a C source file. + +#. When writing a source file that is used by a tool that only accepts C style + comments. + +To comment out a large block of code, use ``#if 0`` and ``#endif``. These nest +properly and are better behaved in general than C style comments. + +Doxygen Use in Documentation Comments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Use the ``\file`` command to turn the standard file header into a file-level +comment. + +Include descriptive ``\brief`` paragraphs for all public interfaces (public +classes, member and non-member functions). Explain API use and purpose in +``\brief`` paragraphs, don't just restate the information that can be inferred +from the API name. Put detailed discussion into separate paragraphs. + +To refer to parameter names inside a paragraph, use the ``\p name`` command. +Don't use the ``\arg name`` command since it starts a new paragraph that +contains documentation for the parameter. + +Wrap non-inline code examples in ``\code ... \endcode``. + +To document a function parameter, start a new paragraph with the +``\param name`` command. If the parameter is used as an out or an in/out +parameter, use the ``\param [out] name`` or ``\param [in,out] name`` command, +respectively. + +To describe function return value, start a new paragraph with the ``\returns`` +command. + +A minimal documentation comment: + +.. code-block:: c++ + + /// \brief Does foo and bar. + void fooBar(bool Baz); + +A documentation comment that uses all Doxygen features in a preferred way: + +.. code-block:: c++ + + /// \brief Does foo and bar. + /// + /// Does not do foo the usual way if \p Baz is true. + /// + /// Typical usage: + /// \code + /// fooBar(false, "quux", Res); + /// \endcode + /// + /// \param Quux kind of foo to do. + /// \param [out] Result filled with bar sequence on foo success. + /// + /// \returns true on success. + bool fooBar(bool Baz, StringRef Quux, std::vector &Result); + +Don't duplicate the documentation comment in the header file and in the +implementation file. Put the documentation comments for public APIs into the +header file. Documentation comments for private APIs can go to the +implementation file. In any case, implementation files can include additional +comments (not necessarily in Doxygen markup) to explain implementation details +as needed. + +Don't duplicate function or class name at the beginning of the comment. +For humans it is obvious which function or class is being documented; +automatic documentation processing tools are smart enough to bind the comment +to the correct declaration. + +Wrong: + +.. code-block:: c++ + + // In Something.h: + + /// Something - An abstraction for some complicated thing. + class Something { + public: + /// fooBar - Does foo and bar. + void fooBar(); + }; + + // In Something.cpp: + + /// fooBar - Does foo and bar. + void Something::fooBar() { ... } + +Correct: + +.. code-block:: c++ + + // In Something.h: + + /// \brief An abstraction for some complicated thing. + class Something { + public: + /// \brief Does foo and bar. + void fooBar(); + }; + + // In Something.cpp: + + // Builds a B-tree in order to do foo. See paper by... + void Something::fooBar() { ... } + +It is not required to use additional Doxygen features, but sometimes it might +be a good idea to do so. + +Consider: + +* adding comments to any narrow namespace containing a collection of + related functions or types; + +* using top-level groups to organize a collection of related functions at + namespace scope where the grouping is smaller than the namespace; + +* using member groups and additional comments attached to member + groups to organize within a class. + +For example: + +.. code-block:: c++ + + class Something { + /// \name Functions that do Foo. + /// @{ + void fooBar(); + void fooBaz(); + /// @} + ... + }; + +``#include`` Style +^^^^^^^^^^^^^^^^^^ + +Immediately after the `header file comment`_ (and include guards if working on a +header file), the `minimal list of #includes`_ required by the file should be +listed. We prefer these ``#include``\s to be listed in this order: + +.. _Main Module Header: +.. _Local/Private Headers: + +#. Main Module Header +#. Local/Private Headers +#. ``llvm/...`` +#. System ``#include``\s + +and each category should be sorted lexicographically by the full path. + +The `Main Module Header`_ file applies to ``.cpp`` files which implement an +interface defined by a ``.h`` file. This ``#include`` should always be included +**first** regardless of where it lives on the file system. By including a +header file first in the ``.cpp`` files that implement the interfaces, we ensure +that the header does not have any hidden dependencies which are not explicitly +``#include``\d in the header, but should be. It is also a form of documentation +in the ``.cpp`` file to indicate where the interfaces it implements are defined. + +.. _fit into 80 columns: + +Source Code Width +^^^^^^^^^^^^^^^^^ + +Write your code to fit within 80 columns of text. This helps those of us who +like to print out code and look at your code in an ``xterm`` without resizing +it. + +The longer answer is that there must be some limit to the width of the code in +order to reasonably allow developers to have multiple files side-by-side in +windows on a modest display. If you are going to pick a width limit, it is +somewhat arbitrary but you might as well pick something standard. Going with 90 +columns (for example) instead of 80 columns wouldn't add any significant value +and would be detrimental to printing out code. Also many other projects have +standardized on 80 columns, so some people have already configured their editors +for it (vs something else, like 90 columns). + +This is one of many contentious issues in coding standards, but it is not up for +debate. + +Use Spaces Instead of Tabs +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In all cases, prefer spaces to tabs in source files. People have different +preferred indentation levels, and different styles of indentation that they +like; this is fine. What isn't fine is that different editors/viewers expand +tabs out to different tab stops. This can cause your code to look completely +unreadable, and it is not worth dealing with. + +As always, follow the `Golden Rule`_ above: follow the style of +existing code if you are modifying and extending it. If you like four spaces of +indentation, **DO NOT** do that in the middle of a chunk of code with two spaces +of indentation. Also, do not reindent a whole source file: it makes for +incredible diffs that are absolutely worthless. + +Indent Code Consistently +^^^^^^^^^^^^^^^^^^^^^^^^ + +Okay, in your first year of programming you were told that indentation is +important. If you didn't believe and internalize this then, now is the time. +Just do it. + +Compiler Issues +--------------- + +Treat Compiler Warnings Like Errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If your code has compiler warnings in it, something is wrong --- you aren't +casting values correctly, you have "questionable" constructs in your code, or +you are doing something legitimately wrong. Compiler warnings can cover up +legitimate errors in output and make dealing with a translation unit difficult. + +It is not possible to prevent all warnings from all compilers, nor is it +desirable. Instead, pick a standard compiler (like ``gcc``) that provides a +good thorough set of warnings, and stick to it. At least in the case of +``gcc``, it is possible to work around any spurious errors by changing the +syntax of the code slightly. For example, a warning that annoys me occurs when +I write code like this: + +.. code-block:: c++ + + if (V = getValue()) { + ... + } + +``gcc`` will warn me that I probably want to use the ``==`` operator, and that I +probably mistyped it. In most cases, I haven't, and I really don't want the +spurious errors. To fix this particular problem, I rewrite the code like +this: + +.. code-block:: c++ + + if ((V = getValue())) { + ... + } + +which shuts ``gcc`` up. Any ``gcc`` warning that annoys you can be fixed by +massaging the code appropriately. + +Write Portable Code +^^^^^^^^^^^^^^^^^^^ + +In almost all cases, it is possible and within reason to write completely +portable code. If there are cases where it isn't possible to write portable +code, isolate it behind a well defined (and well documented) interface. + +In practice, this means that you shouldn't assume much about the host compiler +(and Visual Studio tends to be the lowest common denominator). If advanced +features are used, they should only be an implementation detail of a library +which has a simple exposed API, and preferably be buried in ``libSystem``. + +Do not use RTTI or Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In an effort to reduce code and executable size, LLVM does not use RTTI +(e.g. ``dynamic_cast<>;``) or exceptions. These two language features violate +the general C++ principle of *"you only pay for what you use"*, causing +executable bloat even if exceptions are never used in the code base, or if RTTI +is never used for a class. Because of this, we turn them off globally in the +code. + +That said, LLVM does make extensive use of a hand-rolled form of RTTI that use +templates like `isa<>, cast<>, and dyn_cast<> `_. +This form of RTTI is opt-in and can be +:doc:`added to any class `. It is also +substantially more efficient than ``dynamic_cast<>``. + +.. _static constructor: + +Do not use Static Constructors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Static constructors and destructors (e.g. global variables whose types have a +constructor or destructor) should not be added to the code base, and should be +removed wherever possible. Besides `well known problems +`_ where the order of +initialization is undefined between globals in different source files, the +entire concept of static constructors is at odds with the common use case of +LLVM as a library linked into a larger application. + +Consider the use of LLVM as a JIT linked into another application (perhaps for +`OpenGL, custom languages `_, `shaders in movies +`_, etc). Due to the +design of static constructors, they must be executed at startup time of the +entire application, regardless of whether or how LLVM is used in that larger +application. There are two problems with this: + +* The time to run the static constructors impacts startup time of applications + --- a critical time for GUI apps, among others. + +* The static constructors cause the app to pull many extra pages of memory off + the disk: both the code for the constructor in each ``.o`` file and the small + amount of data that gets touched. In addition, touched/dirty pages put more + pressure on the VM system on low-memory machines. + +We would really like for there to be zero cost for linking in an additional LLVM +target or other library into an application, but static constructors violate +this goal. + +That said, LLVM unfortunately does contain static constructors. It would be a +`great project `_ for someone to purge all static +constructors from LLVM, and then enable the ``-Wglobal-constructors`` warning +flag (when building with Clang) to ensure we do not regress in the future. + +Use of ``class`` and ``struct`` Keywords +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In C++, the ``class`` and ``struct`` keywords can be used almost +interchangeably. The only difference is when they are used to declare a class: +``class`` makes all members private by default while ``struct`` makes all +members public by default. + +Unfortunately, not all compilers follow the rules and some will generate +different symbols based on whether ``class`` or ``struct`` was used to declare +the symbol. This can lead to problems at link time. + +So, the rule for LLVM is to always use the ``class`` keyword, unless **all** +members are public and the type is a C++ `POD +`_ type, in which case +``struct`` is allowed. + +Style Issues +============ + +The High-Level Issues +--------------------- + +A Public Header File **is** a Module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +C++ doesn't do too well in the modularity department. There is no real +encapsulation or data hiding (unless you use expensive protocol classes), but it +is what we have to work with. When you write a public header file (in the LLVM +source tree, they live in the top level "``include``" directory), you are +defining a module of functionality. + +Ideally, modules should be completely independent of each other, and their +header files should only ``#include`` the absolute minimum number of headers +possible. A module is not just a class, a function, or a namespace: it's a +collection of these that defines an interface. This interface may be several +functions, classes, or data structures, but the important issue is how they work +together. + +In general, a module should be implemented by one or more ``.cpp`` files. Each +of these ``.cpp`` files should include the header that defines their interface +first. This ensures that all of the dependences of the module header have been +properly added to the module header itself, and are not implicit. System +headers should be included after user headers for a translation unit. + +.. _minimal list of #includes: + +``#include`` as Little as Possible +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``#include`` hurts compile time performance. Don't do it unless you have to, +especially in header files. + +But wait! Sometimes you need to have the definition of a class to use it, or to +inherit from it. In these cases go ahead and ``#include`` that header file. Be +aware however that there are many cases where you don't need to have the full +definition of a class. If you are using a pointer or reference to a class, you +don't need the header file. If you are simply returning a class instance from a +prototyped function or method, you don't need it. In fact, for most cases, you +simply don't need the definition of a class. And not ``#include``\ing speeds up +compilation. + +It is easy to try to go too overboard on this recommendation, however. You +**must** include all of the header files that you are using --- you can include +them either directly or indirectly through another header file. To make sure +that you don't accidentally forget to include a header file in your module +header, make sure to include your module header **first** in the implementation +file (as mentioned above). This way there won't be any hidden dependencies that +you'll find out about later. + +Keep "Internal" Headers Private +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Many modules have a complex implementation that causes them to use more than one +implementation (``.cpp``) file. It is often tempting to put the internal +communication interface (helper classes, extra functions, etc) in the public +module header file. Don't do this! + +If you really need to do something like this, put a private header file in the +same directory as the source files, and include it locally. This ensures that +your private interface remains private and undisturbed by outsiders. + +.. note:: + + It's okay to put extra implementation methods in a public class itself. Just + make them private (or protected) and all is well. + +.. _early exits: + +Use Early Exits and ``continue`` to Simplify Code +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When reading code, keep in mind how much state and how many previous decisions +have to be remembered by the reader to understand a block of code. Aim to +reduce indentation where possible when it doesn't make it more difficult to +understand the code. One great way to do this is by making use of early exits +and the ``continue`` keyword in long loops. As an example of using an early +exit from a function, consider this "bad" code: + +.. code-block:: c++ + + Value *doSomething(Instruction *I) { + if (!isa(I) && + I->hasOneUse() && doOtherThing(I)) { + ... some long code .... + } + + return 0; + } + +This code has several problems if the body of the ``'if'`` is large. When +you're looking at the top of the function, it isn't immediately clear that this +*only* does interesting things with non-terminator instructions, and only +applies to things with the other predicates. Second, it is relatively difficult +to describe (in comments) why these predicates are important because the ``if`` +statement makes it difficult to lay out the comments. Third, when you're deep +within the body of the code, it is indented an extra level. Finally, when +reading the top of the function, it isn't clear what the result is if the +predicate isn't true; you have to read to the end of the function to know that +it returns null. + +It is much preferred to format the code like this: + +.. code-block:: c++ + + Value *doSomething(Instruction *I) { + // Terminators never need 'something' done to them because ... + if (isa(I)) + return 0; + + // We conservatively avoid transforming instructions with multiple uses + // because goats like cheese. + if (!I->hasOneUse()) + return 0; + + // This is really just here for example. + if (!doOtherThing(I)) + return 0; + + ... some long code .... + } + +This fixes these problems. A similar problem frequently happens in ``for`` +loops. A silly example is something like this: + +.. code-block:: c++ + + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { + if (BinaryOperator *BO = dyn_cast(II)) { + Value *LHS = BO->getOperand(0); + Value *RHS = BO->getOperand(1); + if (LHS != RHS) { + ... + } + } + } + +When you have very, very small loops, this sort of structure is fine. But if it +exceeds more than 10-15 lines, it becomes difficult for people to read and +understand at a glance. The problem with this sort of code is that it gets very +nested very quickly. Meaning that the reader of the code has to keep a lot of +context in their brain to remember what is going immediately on in the loop, +because they don't know if/when the ``if`` conditions will have ``else``\s etc. +It is strongly preferred to structure the loop like this: + +.. code-block:: c++ + + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { + BinaryOperator *BO = dyn_cast(II); + if (!BO) continue; + + Value *LHS = BO->getOperand(0); + Value *RHS = BO->getOperand(1); + if (LHS == RHS) continue; + + ... + } + +This has all the benefits of using early exits for functions: it reduces nesting +of the loop, it makes it easier to describe why the conditions are true, and it +makes it obvious to the reader that there is no ``else`` coming up that they +have to push context into their brain for. If a loop is large, this can be a +big understandability win. + +Don't use ``else`` after a ``return`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For similar reasons above (reduction of indentation and easier reading), please +do not use ``'else'`` or ``'else if'`` after something that interrupts control +flow --- like ``return``, ``break``, ``continue``, ``goto``, etc. For +example, this is *bad*: + +.. code-block:: c++ + + case 'J': { + if (Signed) { + Type = Context.getsigjmp_bufType(); + if (Type.isNull()) { + Error = ASTContext::GE_Missing_sigjmp_buf; + return QualType(); + } else { + break; + } + } else { + Type = Context.getjmp_bufType(); + if (Type.isNull()) { + Error = ASTContext::GE_Missing_jmp_buf; + return QualType(); + } else { + break; + } + } + } + +It is better to write it like this: + +.. code-block:: c++ + + case 'J': + if (Signed) { + Type = Context.getsigjmp_bufType(); + if (Type.isNull()) { + Error = ASTContext::GE_Missing_sigjmp_buf; + return QualType(); + } + } else { + Type = Context.getjmp_bufType(); + if (Type.isNull()) { + Error = ASTContext::GE_Missing_jmp_buf; + return QualType(); + } + } + break; + +Or better yet (in this case) as: + +.. code-block:: c++ + + case 'J': + if (Signed) + Type = Context.getsigjmp_bufType(); + else + Type = Context.getjmp_bufType(); + + if (Type.isNull()) { + Error = Signed ? ASTContext::GE_Missing_sigjmp_buf : + ASTContext::GE_Missing_jmp_buf; + return QualType(); + } + break; + +The idea is to reduce indentation and the amount of code you have to keep track +of when reading the code. + +Turn Predicate Loops into Predicate Functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is very common to write small loops that just compute a boolean value. There +are a number of ways that people commonly write these, but an example of this +sort of thing is: + +.. code-block:: c++ + + bool FoundFoo = false; + for (unsigned I = 0, E = BarList.size(); I != E; ++I) + if (BarList[I]->isFoo()) { + FoundFoo = true; + break; + } + + if (FoundFoo) { + ... + } + +This sort of code is awkward to write, and is almost always a bad sign. Instead +of this sort of loop, we strongly prefer to use a predicate function (which may +be `static`_) that uses `early exits`_ to compute the predicate. We prefer the +code to be structured like this: + +.. code-block:: c++ + + /// \returns true if the specified list has an element that is a foo. + static bool containsFoo(const std::vector &List) { + for (unsigned I = 0, E = List.size(); I != E; ++I) + if (List[I]->isFoo()) + return true; + return false; + } + ... + + if (containsFoo(BarList)) { + ... + } + +There are many reasons for doing this: it reduces indentation and factors out +code which can often be shared by other code that checks for the same predicate. +More importantly, it *forces you to pick a name* for the function, and forces +you to write a comment for it. In this silly example, this doesn't add much +value. However, if the condition is complex, this can make it a lot easier for +the reader to understand the code that queries for this predicate. Instead of +being faced with the in-line details of how we check to see if the BarList +contains a foo, we can trust the function name and continue reading with better +locality. + +The Low-Level Issues +-------------------- + +Name Types, Functions, Variables, and Enumerators Properly +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Poorly-chosen names can mislead the reader and cause bugs. We cannot stress +enough how important it is to use *descriptive* names. Pick names that match +the semantics and role of the underlying entities, within reason. Avoid +abbreviations unless they are well known. After picking a good name, make sure +to use consistent capitalization for the name, as inconsistency requires clients +to either memorize the APIs or to look it up to find the exact spelling. + +In general, names should be in camel case (e.g. ``TextFileReader`` and +``isLValue()``). Different kinds of declarations have different rules: + +* **Type names** (including classes, structs, enums, typedefs, etc) should be + nouns and start with an upper-case letter (e.g. ``TextFileReader``). + +* **Variable names** should be nouns (as they represent state). The name should + be camel case, and start with an upper case letter (e.g. ``Leader`` or + ``Boats``). + +* **Function names** should be verb phrases (as they represent actions), and + command-like function should be imperative. The name should be camel case, + and start with a lower case letter (e.g. ``openFile()`` or ``isFoo()``). + +* **Enum declarations** (e.g. ``enum Foo {...}``) are types, so they should + follow the naming conventions for types. A common use for enums is as a + discriminator for a union, or an indicator of a subclass. When an enum is + used for something like this, it should have a ``Kind`` suffix + (e.g. ``ValueKind``). + +* **Enumerators** (e.g. ``enum { Foo, Bar }``) and **public member variables** + should start with an upper-case letter, just like types. Unless the + enumerators are defined in their own small namespace or inside a class, + enumerators should have a prefix corresponding to the enum declaration name. + For example, ``enum ValueKind { ... };`` may contain enumerators like + ``VK_Argument``, ``VK_BasicBlock``, etc. Enumerators that are just + convenience constants are exempt from the requirement for a prefix. For + instance: + + .. code-block:: c++ + + enum { + MaxSize = 42, + Density = 12 + }; + +As an exception, classes that mimic STL classes can have member names in STL's +style of lower-case words separated by underscores (e.g. ``begin()``, +``push_back()``, and ``empty()``). Classes that provide multiple +iterators should add a singular prefix to ``begin()`` and ``end()`` +(e.g. ``global_begin()`` and ``use_begin()``). + +Here are some examples of good and bad names: + +.. code-block:: c++ + + class VehicleMaker { + ... + Factory F; // Bad -- abbreviation and non-descriptive. + Factory Factory; // Better. + Factory TireFactory; // Even better -- if VehicleMaker has more than one + // kind of factories. + }; + + Vehicle MakeVehicle(VehicleType Type) { + VehicleMaker M; // Might be OK if having a short life-span. + Tire Tmp1 = M.makeTire(); // Bad -- 'Tmp1' provides no information. + Light Headlight = M.makeLight("head"); // Good -- descriptive. + ... + } + +Assert Liberally +^^^^^^^^^^^^^^^^ + +Use the "``assert``" macro to its fullest. Check all of your preconditions and +assumptions, you never know when a bug (not necessarily even yours) might be +caught early by an assertion, which reduces debugging time dramatically. The +"````" header file is probably already included by the header files you +are using, so it doesn't cost anything to use it. + +To further assist with debugging, make sure to put some kind of error message in +the assertion statement, which is printed if the assertion is tripped. This +helps the poor debugger make sense of why an assertion is being made and +enforced, and hopefully what to do about it. Here is one complete example: + +.. code-block:: c++ + + inline Value *getOperand(unsigned I) { + assert(I < Operands.size() && "getOperand() out of range!"); + return Operands[I]; + } + +Here are more examples: + +.. code-block:: c++ + + assert(Ty->isPointerType() && "Can't allocate a non pointer type!"); + + assert((Opcode == Shl || Opcode == Shr) && "ShiftInst Opcode invalid!"); + + assert(idx < getNumSuccessors() && "Successor # out of range!"); + + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + + assert(isa(Succ->front()) && "Only works on PHId BBs!"); + +You get the idea. + +In the past, asserts were used to indicate a piece of code that should not be +reached. These were typically of the form: + +.. code-block:: c++ + + assert(0 && "Invalid radix for integer literal"); + +This has a few issues, the main one being that some compilers might not +understand the assertion, or warn about a missing return in builds where +assertions are compiled out. + +Today, we have something much better: ``llvm_unreachable``: + +.. code-block:: c++ + + llvm_unreachable("Invalid radix for integer literal"); + +When assertions are enabled, this will print the message if it's ever reached +and then exit the program. When assertions are disabled (i.e. in release +builds), ``llvm_unreachable`` becomes a hint to compilers to skip generating +code for this branch. If the compiler does not support this, it will fall back +to the "abort" implementation. + +Another issue is that values used only by assertions will produce an "unused +value" warning when assertions are disabled. For example, this code will warn: + +.. code-block:: c++ + + unsigned Size = V.size(); + assert(Size > 42 && "Vector smaller than it should be"); + + bool NewToSet = Myset.insert(Value); + assert(NewToSet && "The value shouldn't be in the set yet"); + +These are two interesting different cases. In the first case, the call to +``V.size()`` is only useful for the assert, and we don't want it executed when +assertions are disabled. Code like this should move the call into the assert +itself. In the second case, the side effects of the call must happen whether +the assert is enabled or not. In this case, the value should be cast to void to +disable the warning. To be specific, it is preferred to write the code like +this: + +.. code-block:: c++ + + assert(V.size() > 42 && "Vector smaller than it should be"); + + bool NewToSet = Myset.insert(Value); (void)NewToSet; + assert(NewToSet && "The value shouldn't be in the set yet"); + +Do Not Use ``using namespace std`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In LLVM, we prefer to explicitly prefix all identifiers from the standard +namespace with an "``std::``" prefix, rather than rely on "``using namespace +std;``". + +In header files, adding a ``'using namespace XXX'`` directive pollutes the +namespace of any source file that ``#include``\s the header. This is clearly a +bad thing. + +In implementation files (e.g. ``.cpp`` files), the rule is more of a stylistic +rule, but is still important. Basically, using explicit namespace prefixes +makes the code **clearer**, because it is immediately obvious what facilities +are being used and where they are coming from. And **more portable**, because +namespace clashes cannot occur between LLVM code and other namespaces. The +portability rule is important because different standard library implementations +expose different symbols (potentially ones they shouldn't), and future revisions +to the C++ standard will add more symbols to the ``std`` namespace. As such, we +never use ``'using namespace std;'`` in LLVM. + +The exception to the general rule (i.e. it's not an exception for the ``std`` +namespace) is for implementation files. For example, all of the code in the +LLVM project implements code that lives in the 'llvm' namespace. As such, it is +ok, and actually clearer, for the ``.cpp`` files to have a ``'using namespace +llvm;'`` directive at the top, after the ``#include``\s. This reduces +indentation in the body of the file for source editors that indent based on +braces, and keeps the conceptual context cleaner. The general form of this rule +is that any ``.cpp`` file that implements code in any namespace may use that +namespace (and its parents'), but should not use any others. + +Provide a Virtual Method Anchor for Classes in Headers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a class is defined in a header file and has a vtable (either it has virtual +methods or it derives from classes with virtual methods), it must always have at +least one out-of-line virtual method in the class. Without this, the compiler +will copy the vtable and RTTI into every ``.o`` file that ``#include``\s the +header, bloating ``.o`` file sizes and increasing link times. + +Don't use default labels in fully covered switches over enumerations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``-Wswitch`` warns if a switch, without a default label, over an enumeration +does not cover every enumeration value. If you write a default label on a fully +covered switch over an enumeration then the ``-Wswitch`` warning won't fire +when new elements are added to that enumeration. To help avoid adding these +kinds of defaults, Clang has the warning ``-Wcovered-switch-default`` which is +off by default but turned on when building LLVM with a version of Clang that +supports the warning. + +A knock-on effect of this stylistic requirement is that when building LLVM with +GCC you may get warnings related to "control may reach end of non-void function" +if you return from each case of a covered switch-over-enum because GCC assumes +that the enum expression may take any representable value, not just those of +individual enumerators. To suppress this warning, use ``llvm_unreachable`` after +the switch. + +Use ``LLVM_DELETED_FUNCTION`` to mark uncallable methods +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Prior to C++11, a common pattern to make a class uncopyable was to declare an +unimplemented copy constructor and copy assignment operator and make them +private. This would give a compiler error for accessing a private method or a +linker error because it wasn't implemented. + +With C++11, we can mark methods that won't be implemented with ``= delete``. +This will trigger a much better error message and tell the compiler that the +method will never be implemented. This enables other checks like +``-Wunused-private-field`` to run correctly on classes that contain these +methods. + +To maintain compatibility with C++03, ``LLVM_DELETED_FUNCTION`` should be used +which will expand to ``= delete`` if the compiler supports it. These methods +should still be declared private. Example of the uncopyable pattern: + +.. code-block:: c++ + + class DontCopy { + private: + DontCopy(const DontCopy&) LLVM_DELETED_FUNCTION; + DontCopy &operator =(const DontCopy&) LLVM_DELETED_FUNCTION; + public: + ... + }; + +Don't evaluate ``end()`` every time through a loop +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Because C++ doesn't have a standard "``foreach``" loop (though it can be +emulated with macros and may be coming in C++'0x) we end up writing a lot of +loops that manually iterate from begin to end on a variety of containers or +through other data structures. One common mistake is to write a loop in this +style: + +.. code-block:: c++ + + BasicBlock *BB = ... + for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) + ... use I ... + +The problem with this construct is that it evaluates "``BB->end()``" every time +through the loop. Instead of writing the loop like this, we strongly prefer +loops to be written so that they evaluate it once before the loop starts. A +convenient way to do this is like so: + +.. code-block:: c++ + + BasicBlock *BB = ... + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + ... use I ... + +The observant may quickly point out that these two loops may have different +semantics: if the container (a basic block in this case) is being mutated, then +"``BB->end()``" may change its value every time through the loop and the second +loop may not in fact be correct. If you actually do depend on this behavior, +please write the loop in the first form and add a comment indicating that you +did it intentionally. + +Why do we prefer the second form (when correct)? Writing the loop in the first +form has two problems. First it may be less efficient than evaluating it at the +start of the loop. In this case, the cost is probably minor --- a few extra +loads every time through the loop. However, if the base expression is more +complex, then the cost can rise quickly. I've seen loops where the end +expression was actually something like: "``SomeMap[X]->end()``" and map lookups +really aren't cheap. By writing it in the second form consistently, you +eliminate the issue entirely and don't even have to think about it. + +The second (even bigger) issue is that writing the loop in the first form hints +to the reader that the loop is mutating the container (a fact that a comment +would handily confirm!). If you write the loop in the second form, it is +immediately obvious without even looking at the body of the loop that the +container isn't being modified, which makes it easier to read the code and +understand what it does. + +While the second form of the loop is a few extra keystrokes, we do strongly +prefer it. + +``#include `` is Forbidden +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The use of ``#include `` in library files is hereby **forbidden**, +because many common implementations transparently inject a `static constructor`_ +into every translation unit that includes it. + +Note that using the other stream headers (```` for example) is not +problematic in this regard --- just ````. However, ``raw_ostream`` +provides various APIs that are better performing for almost every use than +``std::ostream`` style APIs. + +.. note:: + + New code should always use `raw_ostream`_ for writing, or the + ``llvm::MemoryBuffer`` API for reading files. + +.. _raw_ostream: + +Use ``raw_ostream`` +^^^^^^^^^^^^^^^^^^^ + +LLVM includes a lightweight, simple, and efficient stream implementation in +``llvm/Support/raw_ostream.h``, which provides all of the common features of +``std::ostream``. All new code should use ``raw_ostream`` instead of +``ostream``. + +Unlike ``std::ostream``, ``raw_ostream`` is not a template and can be forward +declared as ``class raw_ostream``. Public headers should generally not include +the ``raw_ostream`` header, but use forward declarations and constant references +to ``raw_ostream`` instances. + +Avoid ``std::endl`` +^^^^^^^^^^^^^^^^^^^ + +The ``std::endl`` modifier, when used with ``iostreams`` outputs a newline to +the output stream specified. In addition to doing this, however, it also +flushes the output stream. In other words, these are equivalent: + +.. code-block:: c++ + + std::cout << std::endl; + std::cout << '\n' << std::flush; + +Most of the time, you probably have no reason to flush the output stream, so +it's better to use a literal ``'\n'``. + +Don't use ``inline`` when defining a function in a class definition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A member function defined in a class definition is implicitly inline, so don't +put the ``inline`` keyword in this case. + +Don't: + +.. code-block:: c++ + + class Foo { + public: + inline void bar() { + // ... + } + }; + +Do: + +.. code-block:: c++ + + class Foo { + public: + void bar() { + // ... + } + }; + +Microscopic Details +------------------- + +This section describes preferred low-level formatting guidelines along with +reasoning on why we prefer them. + +Spaces Before Parentheses +^^^^^^^^^^^^^^^^^^^^^^^^^ + +We prefer to put a space before an open parenthesis only in control flow +statements, but not in normal function call expressions and function-like +macros. For example, this is good: + +.. code-block:: c++ + + if (X) ... + for (I = 0; I != 100; ++I) ... + while (LLVMRocks) ... + + somefunc(42); + assert(3 != 4 && "laws of math are failing me"); + + A = foo(42, 92) + bar(X); + +and this is bad: + +.. code-block:: c++ + + if(X) ... + for(I = 0; I != 100; ++I) ... + while(LLVMRocks) ... + + somefunc (42); + assert (3 != 4 && "laws of math are failing me"); + + A = foo (42, 92) + bar (X); + +The reason for doing this is not completely arbitrary. This style makes control +flow operators stand out more, and makes expressions flow better. The function +call operator binds very tightly as a postfix operator. Putting a space after a +function name (as in the last example) makes it appear that the code might bind +the arguments of the left-hand-side of a binary operator with the argument list +of a function and the name of the right side. More specifically, it is easy to +misread the "``A``" example as: + +.. code-block:: c++ + + A = foo ((42, 92) + bar) (X); + +when skimming through the code. By avoiding a space in a function, we avoid +this misinterpretation. + +Prefer Preincrement +^^^^^^^^^^^^^^^^^^^ + +Hard fast rule: Preincrement (``++X``) may be no slower than postincrement +(``X++``) and could very well be a lot faster than it. Use preincrementation +whenever possible. + +The semantics of postincrement include making a copy of the value being +incremented, returning it, and then preincrementing the "work value". For +primitive types, this isn't a big deal. But for iterators, it can be a huge +issue (for example, some iterators contains stack and set objects in them... +copying an iterator could invoke the copy ctor's of these as well). In general, +get in the habit of always using preincrement, and you won't have a problem. + + +Namespace Indentation +^^^^^^^^^^^^^^^^^^^^^ + +In general, we strive to reduce indentation wherever possible. This is useful +because we want code to `fit into 80 columns`_ without wrapping horribly, but +also because it makes it easier to understand the code. Namespaces are a funny +thing: they are often large, and we often desire to put lots of stuff into them +(so they can be large). Other times they are tiny, because they just hold an +enum or something similar. In order to balance this, we use different +approaches for small versus large namespaces. + +If a namespace definition is small and *easily* fits on a screen (say, less than +35 lines of code), then you should indent its body. Here's an example: + +.. code-block:: c++ + + namespace llvm { + namespace X86 { + /// \brief An enum for the x86 relocation codes. Note that + /// the terminology here doesn't follow x86 convention - word means + /// 32-bit and dword means 64-bit. + enum RelocationType { + /// \brief PC relative relocation, add the relocated value to + /// the value already in memory, after we adjust it for where the PC is. + reloc_pcrel_word = 0, + + /// \brief PIC base relative relocation, add the relocated value to + /// the value already in memory, after we adjust it for where the + /// PIC base is. + reloc_picrel_word = 1, + + /// \brief Absolute relocation, just add the relocated value to the + /// value already in memory. + reloc_absolute_word = 2, + reloc_absolute_dword = 3 + }; + } + } + +Since the body is small, indenting adds value because it makes it very clear +where the namespace starts and ends, and it is easy to take the whole thing in +in one "gulp" when reading the code. If the blob of code in the namespace is +larger (as it typically is in a header in the ``llvm`` or ``clang`` namespaces), +do not indent the code, and add a comment indicating what namespace is being +closed. For example: + +.. code-block:: c++ + + namespace llvm { + namespace knowledge { + + /// This class represents things that Smith can have an intimate + /// understanding of and contains the data associated with it. + class Grokable { + ... + public: + explicit Grokable() { ... } + virtual ~Grokable() = 0; + + ... + + }; + + } // end namespace knowledge + } // end namespace llvm + +Because the class is large, we don't expect that the reader can easily +understand the entire concept in a glance, and the end of the file (where the +namespaces end) may be a long ways away from the place they open. As such, +indenting the contents of the namespace doesn't add any value, and detracts from +the readability of the class. In these cases it is best to *not* indent the +contents of the namespace. + +.. _static: + +Anonymous Namespaces +^^^^^^^^^^^^^^^^^^^^ + +After talking about namespaces in general, you may be wondering about anonymous +namespaces in particular. Anonymous namespaces are a great language feature +that tells the C++ compiler that the contents of the namespace are only visible +within the current translation unit, allowing more aggressive optimization and +eliminating the possibility of symbol name collisions. Anonymous namespaces are +to C++ as "static" is to C functions and global variables. While "``static``" +is available in C++, anonymous namespaces are more general: they can make entire +classes private to a file. + +The problem with anonymous namespaces is that they naturally want to encourage +indentation of their body, and they reduce locality of reference: if you see a +random function definition in a C++ file, it is easy to see if it is marked +static, but seeing if it is in an anonymous namespace requires scanning a big +chunk of the file. + +Because of this, we have a simple guideline: make anonymous namespaces as small +as possible, and only use them for class declarations. For example, this is +good: + +.. code-block:: c++ + + namespace { + class StringSort { + ... + public: + StringSort(...) + bool operator<(const char *RHS) const; + }; + } // end anonymous namespace + + static void runHelper() { + ... + } + + bool StringSort::operator<(const char *RHS) const { + ... + } + +This is bad: + +.. code-block:: c++ + + namespace { + class StringSort { + ... + public: + StringSort(...) + bool operator<(const char *RHS) const; + }; + + void runHelper() { + ... + } + + bool StringSort::operator<(const char *RHS) const { + ... + } + + } // end anonymous namespace + +This is bad specifically because if you're looking at "``runHelper``" in the middle +of a large C++ file, that you have no immediate way to tell if it is local to +the file. When it is marked static explicitly, this is immediately obvious. +Also, there is no reason to enclose the definition of "``operator<``" in the +namespace just because it was declared there. + +See Also +======== + +A lot of these comments and recommendations have been culled from other sources. +Two particularly important books for our work are: + +#. `Effective C++ + `_ + by Scott Meyers. Also interesting and useful are "More Effective C++" and + "Effective STL" by the same author. + +#. `Large-Scale C++ Software Design + `_ + by John Lakos + +If you get some free time, and you haven't read them: do so, you might learn +something. diff --git a/docs/CommandGuide/FileCheck.rst b/docs/CommandGuide/FileCheck.rst new file mode 100644 index 00000000..5a60d60a --- /dev/null +++ b/docs/CommandGuide/FileCheck.rst @@ -0,0 +1,410 @@ +FileCheck - Flexible pattern matching file verifier +=================================================== + +SYNOPSIS +-------- + +:program:`FileCheck` *match-filename* [*--check-prefix=XXX*] [*--strict-whitespace*] + +DESCRIPTION +----------- + +:program:`FileCheck` reads two files (one from standard input, and one +specified on the command line) and uses one to verify the other. This +behavior is particularly useful for the testsuite, which wants to verify that +the output of some tool (e.g. :program:`llc`) contains the expected information +(for example, a movsd from esp or whatever is interesting). This is similar to +using :program:`grep`, but it is optimized for matching multiple different +inputs in one file in a specific order. + +The ``match-filename`` file specifies the file that contains the patterns to +match. The file to verify is read from standard input unless the +:option:`--input-file` option is used. + +OPTIONS +------- + +.. option:: -help + + Print a summary of command line options. + +.. option:: --check-prefix prefix + + FileCheck searches the contents of ``match-filename`` for patterns to + match. By default, these patterns are prefixed with "``CHECK:``". + If you'd like to use a different prefix (e.g. because the same input + file is checking multiple different tool or options), the + :option:`--check-prefix` argument allows you to specify one or more + prefixes to match. Multiple prefixes are useful for tests which might + change for different run options, but most lines remain the same. + +.. option:: --input-file filename + + File to check (defaults to stdin). + +.. option:: --strict-whitespace + + By default, FileCheck canonicalizes input horizontal whitespace (spaces and + tabs) which causes it to ignore these differences (a space will match a tab). + The :option:`--strict-whitespace` argument disables this behavior. End-of-line + sequences are canonicalized to UNIX-style ``\n`` in all modes. + +.. option:: -version + + Show the version number of this program. + +EXIT STATUS +----------- + +If :program:`FileCheck` verifies that the file matches the expected contents, +it exits with 0. Otherwise, if not, or if an error occurs, it will exit with a +non-zero value. + +TUTORIAL +-------- + +FileCheck is typically used from LLVM regression tests, being invoked on the RUN +line of the test. A simple example of using FileCheck from a RUN line looks +like this: + +.. code-block:: llvm + + ; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s + +This syntax says to pipe the current file ("``%s``") into ``llvm-as``, pipe +that into ``llc``, then pipe the output of ``llc`` into ``FileCheck``. This +means that FileCheck will be verifying its standard input (the llc output) +against the filename argument specified (the original ``.ll`` file specified by +"``%s``"). To see how this works, let's look at the rest of the ``.ll`` file +(after the RUN line): + +.. code-block:: llvm + + define void @sub1(i32* %p, i32 %v) { + entry: + ; CHECK: sub1: + ; CHECK: subl + %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v) + ret void + } + + define void @inc4(i64* %p) { + entry: + ; CHECK: inc4: + ; CHECK: incq + %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1) + ret void + } + +Here you can see some "``CHECK:``" lines specified in comments. Now you can +see how the file is piped into ``llvm-as``, then ``llc``, and the machine code +output is what we are verifying. FileCheck checks the machine code output to +verify that it matches what the "``CHECK:``" lines specify. + +The syntax of the "``CHECK:``" lines is very simple: they are fixed strings that +must occur in order. FileCheck defaults to ignoring horizontal whitespace +differences (e.g. a space is allowed to match a tab) but otherwise, the contents +of the "``CHECK:``" line is required to match some thing in the test file exactly. + +One nice thing about FileCheck (compared to grep) is that it allows merging +test cases together into logical groups. For example, because the test above +is checking for the "``sub1:``" and "``inc4:``" labels, it will not match +unless there is a "``subl``" in between those labels. If it existed somewhere +else in the file, that would not count: "``grep subl``" matches if "``subl``" +exists anywhere in the file. + +The FileCheck -check-prefix option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FileCheck :option:`-check-prefix` option allows multiple test +configurations to be driven from one `.ll` file. This is useful in many +circumstances, for example, testing different architectural variants with +:program:`llc`. Here's a simple example: + +.. code-block:: llvm + + ; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \ + ; RUN: | FileCheck %s -check-prefix=X32 + ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \ + ; RUN: | FileCheck %s -check-prefix=X64 + + define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind { + %tmp1 = insertelement <4 x i32>; %tmp, i32 %s, i32 1 + ret <4 x i32> %tmp1 + ; X32: pinsrd_1: + ; X32: pinsrd $1, 4(%esp), %xmm0 + + ; X64: pinsrd_1: + ; X64: pinsrd $1, %edi, %xmm0 + } + +In this case, we're testing that we get the expected code generation with +both 32-bit and 64-bit code generation. + +The "CHECK-NEXT:" directive +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes you want to match lines and would like to verify that matches +happen on exactly consecutive lines with no other lines in between them. In +this case, you can use "``CHECK:``" and "``CHECK-NEXT:``" directives to specify +this. If you specified a custom check prefix, just use "``-NEXT:``". +For example, something like this works as you'd expect: + +.. code-block:: llvm + + define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) { + %tmp3 = load <2 x double>* %A, align 16 + %tmp7 = insertelement <2 x double> undef, double %B, i32 0 + %tmp9 = shufflevector <2 x double> %tmp3, + <2 x double> %tmp7, + <2 x i32> < i32 0, i32 2 > + store <2 x double> %tmp9, <2 x double>* %r, align 16 + ret void + + ; CHECK: t2: + ; CHECK: movl 8(%esp), %eax + ; CHECK-NEXT: movapd (%eax), %xmm0 + ; CHECK-NEXT: movhpd 12(%esp), %xmm0 + ; CHECK-NEXT: movl 4(%esp), %eax + ; CHECK-NEXT: movapd %xmm0, (%eax) + ; CHECK-NEXT: ret + } + +"``CHECK-NEXT:``" directives reject the input unless there is exactly one +newline between it and the previous directive. A "``CHECK-NEXT:``" cannot be +the first directive in a file. + +The "CHECK-NOT:" directive +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The "``CHECK-NOT:``" directive is used to verify that a string doesn't occur +between two matches (or before the first match, or after the last match). For +example, to verify that a load is removed by a transformation, a test like this +can be used: + +.. code-block:: llvm + + define i8 @coerce_offset0(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %P2 = bitcast i32* %P to i8* + %P3 = getelementptr i8* %P2, i32 2 + + %A = load i8* %P3 + ret i8 %A + ; CHECK: @coerce_offset0 + ; CHECK-NOT: load + ; CHECK: ret i8 + } + +The "CHECK-DAG:" directive +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If it's necessary to match strings that don't occur in a strictly sequential +order, "``CHECK-DAG:``" could be used to verify them between two matches (or +before the first match, or after the last match). For example, clang emits +vtable globals in reverse order. Using ``CHECK-DAG:``, we can keep the checks +in the natural order: + +.. code-block:: c++ + + // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + + struct Foo { virtual void method(); }; + Foo f; // emit vtable + // CHECK-DAG: @_ZTV3Foo = + + struct Bar { virtual void method(); }; + Bar b; + // CHECK-DAG: @_ZTV3Bar = + +``CHECK-NOT:`` directives could be mixed with ``CHECK-DAG:`` directives to +exclude strings between the surrounding ``CHECK-DAG:`` directives. As a result, +the surrounding ``CHECK-DAG:`` directives cannot be reordered, i.e. all +occurrences matching ``CHECK-DAG:`` before ``CHECK-NOT:`` must not fall behind +occurrences matching ``CHECK-DAG:`` after ``CHECK-NOT:``. For example, + +.. code-block:: llvm + + ; CHECK-DAG: BEFORE + ; CHECK-NOT: NOT + ; CHECK-DAG: AFTER + +This case will reject input strings where ``BEFORE`` occurs after ``AFTER``. + +With captured variables, ``CHECK-DAG:`` is able to match valid topological +orderings of a DAG with edges from the definition of a variable to its use. +It's useful, e.g., when your test cases need to match different output +sequences from the instruction scheduler. For example, + +.. code-block:: llvm + + ; CHECK-DAG: add [[REG1:r[0-9]+]], r1, r2 + ; CHECK-DAG: add [[REG2:r[0-9]+]], r3, r4 + ; CHECK: mul r5, [[REG1]], [[REG2]] + +In this case, any order of that two ``add`` instructions will be allowed. + +If you are defining `and` using variables in the same ``CHECK-DAG:`` block, +be aware that the definition rule can match `after` its use. + +So, for instance, the code below will pass: + +.. code-block:: llvm + + ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0] + ; CHECK-DAG: vmov.32 [[REG2]][1] + vmov.32 d0[1] + vmov.32 d0[0] + +While this other code, will not: + +.. code-block:: llvm + + ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0] + ; CHECK-DAG: vmov.32 [[REG2]][1] + vmov.32 d1[1] + vmov.32 d0[0] + +While this can be very useful, it's also dangerous, because in the case of +register sequence, you must have a strong order (read before write, copy before +use, etc). If the definition your test is looking for doesn't match (because +of a bug in the compiler), it may match further away from the use, and mask +real bugs away. + +In those cases, to enforce the order, use a non-DAG directive between DAG-blocks. + +The "CHECK-LABEL:" directive +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes in a file containing multiple tests divided into logical blocks, one +or more ``CHECK:`` directives may inadvertently succeed by matching lines in a +later block. While an error will usually eventually be generated, the check +flagged as causing the error may not actually bear any relationship to the +actual source of the problem. + +In order to produce better error messages in these cases, the "``CHECK-LABEL:``" +directive can be used. It is treated identically to a normal ``CHECK`` +directive except that FileCheck makes an additional assumption that a line +matched by the directive cannot also be matched by any other check present in +``match-filename``; this is intended to be used for lines containing labels or +other unique identifiers. Conceptually, the presence of ``CHECK-LABEL`` divides +the input stream into separate blocks, each of which is processed independently, +preventing a ``CHECK:`` directive in one block matching a line in another block. +For example, + +.. code-block:: llvm + + define %struct.C* @C_ctor_base(%struct.C* %this, i32 %x) { + entry: + ; CHECK-LABEL: C_ctor_base: + ; CHECK: mov [[SAVETHIS:r[0-9]+]], r0 + ; CHECK: bl A_ctor_base + ; CHECK: mov r0, [[SAVETHIS]] + %0 = bitcast %struct.C* %this to %struct.A* + %call = tail call %struct.A* @A_ctor_base(%struct.A* %0) + %1 = bitcast %struct.C* %this to %struct.B* + %call2 = tail call %struct.B* @B_ctor_base(%struct.B* %1, i32 %x) + ret %struct.C* %this + } + + define %struct.D* @D_ctor_base(%struct.D* %this, i32 %x) { + entry: + ; CHECK-LABEL: D_ctor_base: + +The use of ``CHECK-LABEL:`` directives in this case ensures that the three +``CHECK:`` directives only accept lines corresponding to the body of the +``@C_ctor_base`` function, even if the patterns match lines found later in +the file. Furthermore, if one of these three ``CHECK:`` directives fail, +FileCheck will recover by continuing to the next block, allowing multiple test +failures to be detected in a single invocation. + +There is no requirement that ``CHECK-LABEL:`` directives contain strings that +correspond to actual syntactic labels in a source or output language: they must +simply uniquely match a single line in the file being verified. + +``CHECK-LABEL:`` directives cannot contain variable definitions or uses. + +FileCheck Pattern Matching Syntax +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The "``CHECK:``" and "``CHECK-NOT:``" directives both take a pattern to match. +For most uses of FileCheck, fixed string matching is perfectly sufficient. For +some things, a more flexible form of matching is desired. To support this, +FileCheck allows you to specify regular expressions in matching strings, +surrounded by double braces: ``{{yourregex}}``. Because we want to use fixed +string matching for a majority of what we do, FileCheck has been designed to +support mixing and matching fixed string matching with regular expressions. +This allows you to write things like this: + +.. code-block:: llvm + + ; CHECK: movhpd {{[0-9]+}}(%esp), {{%xmm[0-7]}} + +In this case, any offset from the ESP register will be allowed, and any xmm +register will be allowed. + +Because regular expressions are enclosed with double braces, they are +visually distinct, and you don't need to use escape characters within the double +braces like you would in C. In the rare case that you want to match double +braces explicitly from the input, you can use something ugly like +``{{[{][{]}}`` as your pattern. + +FileCheck Variables +~~~~~~~~~~~~~~~~~~~ + +It is often useful to match a pattern and then verify that it occurs again +later in the file. For codegen tests, this can be useful to allow any register, +but verify that that register is used consistently later. To do this, +:program:`FileCheck` allows named variables to be defined and substituted into +patterns. Here is a simple example: + +.. code-block:: llvm + + ; CHECK: test5: + ; CHECK: notw [[REGISTER:%[a-z]+]] + ; CHECK: andw {{.*}}[[REGISTER]] + +The first check line matches a regex ``%[a-z]+`` and captures it into the +variable ``REGISTER``. The second line verifies that whatever is in +``REGISTER`` occurs later in the file after an "``andw``". :program:`FileCheck` +variable references are always contained in ``[[ ]]`` pairs, and their names can +be formed with the regex ``[a-zA-Z][a-zA-Z0-9]*``. If a colon follows the name, +then it is a definition of the variable; otherwise, it is a use. + +:program:`FileCheck` variables can be defined multiple times, and uses always +get the latest value. Variables can also be used later on the same line they +were defined on. For example: + +.. code-block:: llvm + + ; CHECK: op [[REG:r[0-9]+]], [[REG]] + +Can be useful if you want the operands of ``op`` to be the same register, +and don't care exactly which register it is. + +FileCheck Expressions +~~~~~~~~~~~~~~~~~~~~~ + +Sometimes there's a need to verify output which refers line numbers of the +match file, e.g. when testing compiler diagnostics. This introduces a certain +fragility of the match file structure, as "``CHECK:``" lines contain absolute +line numbers in the same file, which have to be updated whenever line numbers +change due to text addition or deletion. + +To support this case, FileCheck allows using ``[[@LINE]]``, +``[[@LINE+]]``, ``[[@LINE-]]`` expressions in patterns. These +expressions expand to a number of the line where a pattern is located (with an +optional integer offset). + +This way match patterns can be put near the relevant test lines and include +relative line number references, for example: + +.. code-block:: c++ + + // CHECK: test.cpp:[[@LINE+4]]:6: error: expected ';' after top level declarator + // CHECK-NEXT: {{^int a}} + // CHECK-NEXT: {{^ \^}} + // CHECK-NEXT: {{^ ;}} + int a + diff --git a/docs/CommandGuide/bugpoint.rst b/docs/CommandGuide/bugpoint.rst new file mode 100644 index 00000000..e4663e5d --- /dev/null +++ b/docs/CommandGuide/bugpoint.rst @@ -0,0 +1,187 @@ +bugpoint - automatic test case reduction tool +============================================= + +SYNOPSIS +-------- + +**bugpoint** [*options*] [*input LLVM ll/bc files*] [*LLVM passes*] **--args** +*program arguments* + +DESCRIPTION +----------- + +**bugpoint** narrows down the source of problems in LLVM tools and passes. It +can be used to debug three types of failures: optimizer crashes, miscompilations +by optimizers, or bad native code generation (including problems in the static +and JIT compilers). It aims to reduce large test cases to small, useful ones. +For more information on the design and inner workings of **bugpoint**, as well as +advice for using bugpoint, see *llvm/docs/Bugpoint.html* in the LLVM +distribution. + +OPTIONS +------- + +**--additional-so** *library* + + Load the dynamic shared object *library* into the test program whenever it is + run. This is useful if you are debugging programs which depend on non-LLVM + libraries (such as the X or curses libraries) to run. + +**--append-exit-code**\ =\ *{true,false}* + + Append the test programs exit code to the output file so that a change in exit + code is considered a test failure. Defaults to false. + +**--args** *program args* + + Pass all arguments specified after **--args** to the test program whenever it runs. + Note that if any of the *program args* start with a "``-``", you should use: + + .. code-block:: bash + + bugpoint [bugpoint args] --args -- [program args] + + The "``--``" right after the **--args** option tells **bugpoint** to consider + any options starting with "``-``" to be part of the **--args** option, not as + options to **bugpoint** itself. + +**--tool-args** *tool args* + + Pass all arguments specified after **--tool-args** to the LLVM tool under test + (**llc**, **lli**, etc.) whenever it runs. You should use this option in the + following way: + + .. code-block:: bash + + bugpoint [bugpoint args] --tool-args -- [tool args] + + The "``--``" right after the **--tool-args** option tells **bugpoint** to + consider any options starting with "``-``" to be part of the **--tool-args** + option, not as options to **bugpoint** itself. (See **--args**, above.) + +**--safe-tool-args** *tool args* + + Pass all arguments specified after **--safe-tool-args** to the "safe" execution + tool. + +**--gcc-tool-args** *gcc tool args* + + Pass all arguments specified after **--gcc-tool-args** to the invocation of + **gcc**. + +**--opt-args** *opt args* + + Pass all arguments specified after **--opt-args** to the invocation of **opt**. + +**--disable-{dce,simplifycfg}** + + Do not run the specified passes to clean up and reduce the size of the test + program. By default, **bugpoint** uses these passes internally when attempting to + reduce test programs. If you're trying to find a bug in one of these passes, + **bugpoint** may crash. + +**--enable-valgrind** + + Use valgrind to find faults in the optimization phase. This will allow + bugpoint to find otherwise asymptomatic problems caused by memory + mis-management. + +**-find-bugs** + + Continually randomize the specified passes and run them on the test program + until a bug is found or the user kills **bugpoint**. + +**-help** + + Print a summary of command line options. + +**--input** *filename* + + Open *filename* and redirect the standard input of the test program, whenever + it runs, to come from that file. + +**--load** *plugin* + + Load the dynamic object *plugin* into **bugpoint** itself. This object should + register new optimization passes. Once loaded, the object will add new command + line options to enable various optimizations. To see the new complete list of + optimizations, use the **-help** and **--load** options together; for example: + + + .. code-block:: bash + + bugpoint --load myNewPass.so -help + +**--mlimit** *megabytes* + + Specifies an upper limit on memory usage of the optimization and codegen. Set + to zero to disable the limit. + +**--output** *filename* + + Whenever the test program produces output on its standard output stream, it + should match the contents of *filename* (the "reference output"). If you + do not use this option, **bugpoint** will attempt to generate a reference output + by compiling the program with the "safe" backend and running it. + +**--profile-info-file** *filename* + + Profile file loaded by **--profile-loader**. + +**--run-{int,jit,llc,custom}** + + Whenever the test program is compiled, **bugpoint** should generate code for it + using the specified code generator. These options allow you to choose the + interpreter, the JIT compiler, the static native code compiler, or a + custom command (see **--exec-command**) respectively. + +**--safe-{llc,custom}** + + When debugging a code generator, **bugpoint** should use the specified code + generator as the "safe" code generator. This is a known-good code generator + used to generate the "reference output" if it has not been provided, and to + compile portions of the program that as they are excluded from the testcase. + These options allow you to choose the + static native code compiler, or a custom command, (see **--exec-command**) + respectively. The interpreter and the JIT backends cannot currently + be used as the "safe" backends. + +**--exec-command** *command* + + This option defines the command to use with the **--run-custom** and + **--safe-custom** options to execute the bitcode testcase. This can + be useful for cross-compilation. + +**--compile-command** *command* + + This option defines the command to use with the **--compile-custom** + option to compile the bitcode testcase. This can be useful for + testing compiler output without running any link or execute stages. To + generate a reduced unit test, you may add CHECK directives to the + testcase and pass the name of an executable compile-command script in this form: + + .. code-block:: sh + + #!/bin/sh + llc "$@" + not FileCheck [bugpoint input file].ll < bugpoint-test-program.s + + This script will "fail" as long as FileCheck passes. So the result + will be the minimum bitcode that passes FileCheck. + +**--safe-path** *path* + + This option defines the path to the command to execute with the + **--safe-{int,jit,llc,custom}** + option. + +EXIT STATUS +----------- + +If **bugpoint** succeeds in finding a problem, it will exit with 0. Otherwise, +if an error occurs, it will exit with a non-zero value. + +SEE ALSO +-------- + +opt|opt diff --git a/docs/CommandGuide/index.rst b/docs/CommandGuide/index.rst new file mode 100644 index 00000000..d50542dd --- /dev/null +++ b/docs/CommandGuide/index.rst @@ -0,0 +1,52 @@ +LLVM Command Guide +------------------ + +The following documents are command descriptions for all of the LLVM tools. +These pages describe how to use the LLVM commands and what their options are. +Note that these pages do not describe all of the options available for all +tools. To get a complete listing, pass the ``--help`` (general options) or +``--help-hidden`` (general and debugging options) arguments to the tool you are +interested in. + +Basic Commands +~~~~~~~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + llvm-as + llvm-dis + opt + llc + lli + llvm-link + llvm-ar + llvm-nm + llvm-prof + llvm-config + llvm-diff + llvm-cov + llvm-stress + llvm-symbolizer + +Debugging Tools +~~~~~~~~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + bugpoint + llvm-extract + llvm-bcanalyzer + +Developer Tools +~~~~~~~~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + FileCheck + tblgen + lit + llvm-build + llvm-readobj diff --git a/docs/CommandGuide/lit.rst b/docs/CommandGuide/lit.rst new file mode 100644 index 00000000..4d84be63 --- /dev/null +++ b/docs/CommandGuide/lit.rst @@ -0,0 +1,414 @@ +lit - LLVM Integrated Tester +============================ + +SYNOPSIS +-------- + +:program:`lit` [*options*] [*tests*] + +DESCRIPTION +----------- + +:program:`lit` is a portable tool for executing LLVM and Clang style test +suites, summarizing their results, and providing indication of failures. +:program:`lit` is designed to be a lightweight testing tool with as simple a +user interface as possible. + +:program:`lit` should be run with one or more *tests* to run specified on the +command line. Tests can be either individual test files or directories to +search for tests (see :ref:`test-discovery`). + +Each specified test will be executed (potentially in parallel) and once all +tests have been run :program:`lit` will print summary information on the number +of tests which passed or failed (see :ref:`test-status-results`). The +:program:`lit` program will execute with a non-zero exit code if any tests +fail. + +By default :program:`lit` will use a succinct progress display and will only +print summary information for test failures. See :ref:`output-options` for +options controlling the :program:`lit` progress display and output. + +:program:`lit` also includes a number of options for controlling how tests are +executed (specific features may depend on the particular test format). See +:ref:`execution-options` for more information. + +Finally, :program:`lit` also supports additional options for only running a +subset of the options specified on the command line, see +:ref:`selection-options` for more information. + +Users interested in the :program:`lit` architecture or designing a +:program:`lit` testing implementation should see :ref:`lit-infrastructure`. + +GENERAL OPTIONS +--------------- + +.. option:: -h, --help + + Show the :program:`lit` help message. + +.. option:: -j N, --threads=N + + Run ``N`` tests in parallel. By default, this is automatically chosen to + match the number of detected available CPUs. + +.. option:: --config-prefix=NAME + + Search for :file:`{NAME}.cfg` and :file:`{NAME}.site.cfg` when searching for + test suites, instead of :file:`lit.cfg` and :file:`lit.site.cfg`. + +.. option:: --param NAME, --param NAME=VALUE + + Add a user defined parameter ``NAME`` with the given ``VALUE`` (or the empty + string if not given). The meaning and use of these parameters is test suite + dependent. + +.. _output-options: + +OUTPUT OPTIONS +-------------- + +.. option:: -q, --quiet + + Suppress any output except for test failures. + +.. option:: -s, --succinct + + Show less output, for example don't show information on tests that pass. + +.. option:: -v, --verbose + + Show more information on test failures, for example the entire test output + instead of just the test result. + +.. option:: --no-progress-bar + + Do not use curses based progress bar. + +.. _execution-options: + +EXECUTION OPTIONS +----------------- + +.. option:: --path=PATH + + Specify an additional ``PATH`` to use when searching for executables in tests. + +.. option:: --vg + + Run individual tests under valgrind (using the memcheck tool). The + ``--error-exitcode`` argument for valgrind is used so that valgrind failures + will cause the program to exit with a non-zero status. + + When this option is enabled, :program:`lit` will also automatically provide a + "``valgrind``" feature that can be used to conditionally disable (or expect + failure in) certain tests. + +.. option:: --vg-arg=ARG + + When :option:`--vg` is used, specify an additional argument to pass to + :program:`valgrind` itself. + +.. option:: --vg-leak + + When :option:`--vg` is used, enable memory leak checks. When this option is + enabled, :program:`lit` will also automatically provide a "``vg_leak``" + feature that can be used to conditionally disable (or expect failure in) + certain tests. + +.. option:: --time-tests + + Track the wall time individual tests take to execute and includes the results + in the summary output. This is useful for determining which tests in a test + suite take the most time to execute. Note that this option is most useful + with ``-j 1``. + +.. _selection-options: + +SELECTION OPTIONS +----------------- + +.. option:: --max-tests=N + + Run at most ``N`` tests and then terminate. + +.. option:: --max-time=N + + Spend at most ``N`` seconds (approximately) running tests and then terminate. + +.. option:: --shuffle + + Run the tests in a random order. + +ADDITIONAL OPTIONS +------------------ + +.. option:: --debug + + Run :program:`lit` in debug mode, for debugging configuration issues and + :program:`lit` itself. + +.. option:: --show-suites + + List the discovered test suites and exit. + +.. option:: --show-tests + + List all of the the discovered tests and exit. + +EXIT STATUS +----------- + +:program:`lit` will exit with an exit code of 1 if there are any FAIL or XPASS +results. Otherwise, it will exit with the status 0. Other exit codes are used +for non-test related failures (for example a user error or an internal program +error). + +.. _test-discovery: + +TEST DISCOVERY +-------------- + +The inputs passed to :program:`lit` can be either individual tests, or entire +directories or hierarchies of tests to run. When :program:`lit` starts up, the +first thing it does is convert the inputs into a complete list of tests to run +as part of *test discovery*. + +In the :program:`lit` model, every test must exist inside some *test suite*. +:program:`lit` resolves the inputs specified on the command line to test suites +by searching upwards from the input path until it finds a :file:`lit.cfg` or +:file:`lit.site.cfg` file. These files serve as both a marker of test suites +and as configuration files which :program:`lit` loads in order to understand +how to find and run the tests inside the test suite. + +Once :program:`lit` has mapped the inputs into test suites it traverses the +list of inputs adding tests for individual files and recursively searching for +tests in directories. + +This behavior makes it easy to specify a subset of tests to run, while still +allowing the test suite configuration to control exactly how tests are +interpreted. In addition, :program:`lit` always identifies tests by the test +suite they are in, and their relative path inside the test suite. For +appropriately configured projects, this allows :program:`lit` to provide +convenient and flexible support for out-of-tree builds. + +.. _test-status-results: + +TEST STATUS RESULTS +------------------- + +Each test ultimately produces one of the following six results: + +**PASS** + + The test succeeded. + +**XFAIL** + + The test failed, but that is expected. This is used for test formats which allow + specifying that a test does not currently work, but wish to leave it in the test + suite. + +**XPASS** + + The test succeeded, but it was expected to fail. This is used for tests which + were specified as expected to fail, but are now succeeding (generally because + the feature they test was broken and has been fixed). + +**FAIL** + + The test failed. + +**UNRESOLVED** + + The test result could not be determined. For example, this occurs when the test + could not be run, the test itself is invalid, or the test was interrupted. + +**UNSUPPORTED** + + The test is not supported in this environment. This is used by test formats + which can report unsupported tests. + +Depending on the test format tests may produce additional information about +their status (generally only for failures). See the :ref:`output-options` +section for more information. + +.. _lit-infrastructure: + +LIT INFRASTRUCTURE +------------------ + +This section describes the :program:`lit` testing architecture for users interested in +creating a new :program:`lit` testing implementation, or extending an existing one. + +:program:`lit` proper is primarily an infrastructure for discovering and running +arbitrary tests, and to expose a single convenient interface to these +tests. :program:`lit` itself doesn't know how to run tests, rather this logic is +defined by *test suites*. + +TEST SUITES +~~~~~~~~~~~ + +As described in :ref:`test-discovery`, tests are always located inside a *test +suite*. Test suites serve to define the format of the tests they contain, the +logic for finding those tests, and any additional information to run the tests. + +:program:`lit` identifies test suites as directories containing ``lit.cfg`` or +``lit.site.cfg`` files (see also :option:`--config-prefix`). Test suites are +initially discovered by recursively searching up the directory hierarchy for +all the input files passed on the command line. You can use +:option:`--show-suites` to display the discovered test suites at startup. + +Once a test suite is discovered, its config file is loaded. Config files +themselves are Python modules which will be executed. When the config file is +executed, two important global variables are predefined: + +**lit** + + The global **lit** configuration object (a *LitConfig* instance), which defines + the builtin test formats, global configuration parameters, and other helper + routines for implementing test configurations. + +**config** + + This is the config object (a *TestingConfig* instance) for the test suite, + which the config file is expected to populate. The following variables are also + available on the *config* object, some of which must be set by the config and + others are optional or predefined: + + **name** *[required]* The name of the test suite, for use in reports and + diagnostics. + + **test_format** *[required]* The test format object which will be used to + discover and run tests in the test suite. Generally this will be a builtin test + format available from the *lit.formats* module. + + **test_source_root** The filesystem path to the test suite root. For out-of-dir + builds this is the directory that will be scanned for tests. + + **test_exec_root** For out-of-dir builds, the path to the test suite root inside + the object directory. This is where tests will be run and temporary output files + placed. + + **environment** A dictionary representing the environment to use when executing + tests in the suite. + + **suffixes** For **lit** test formats which scan directories for tests, this + variable is a list of suffixes to identify test files. Used by: *ShTest*. + + **substitutions** For **lit** test formats which substitute variables into a test + script, the list of substitutions to perform. Used by: *ShTest*. + + **unsupported** Mark an unsupported directory, all tests within it will be + reported as unsupported. Used by: *ShTest*. + + **parent** The parent configuration, this is the config object for the directory + containing the test suite, or None. + + **root** The root configuration. This is the top-most :program:`lit` configuration in + the project. + + **on_clone** The config is actually cloned for every subdirectory inside a test + suite, to allow local configuration on a per-directory basis. The *on_clone* + variable can be set to a Python function which will be called whenever a + configuration is cloned (for a subdirectory). The function should takes three + arguments: (1) the parent configuration, (2) the new configuration (which the + *on_clone* function will generally modify), and (3) the test path to the new + directory being scanned. + + **pipefail** Normally a test using a shell pipe fails if any of the commands + on the pipe fail. If this is not desired, setting this variable to false + makes the test fail only if the last command in the pipe fails. + +TEST DISCOVERY +~~~~~~~~~~~~~~ + +Once test suites are located, :program:`lit` recursively traverses the source +directory (following *test_source_root*) looking for tests. When :program:`lit` +enters a sub-directory, it first checks to see if a nested test suite is +defined in that directory. If so, it loads that test suite recursively, +otherwise it instantiates a local test config for the directory (see +:ref:`local-configuration-files`). + +Tests are identified by the test suite they are contained within, and the +relative path inside that suite. Note that the relative path may not refer to +an actual file on disk; some test formats (such as *GoogleTest*) define +"virtual tests" which have a path that contains both the path to the actual +test file and a subpath to identify the virtual test. + +.. _local-configuration-files: + +LOCAL CONFIGURATION FILES +~~~~~~~~~~~~~~~~~~~~~~~~~ + +When :program:`lit` loads a subdirectory in a test suite, it instantiates a +local test configuration by cloning the configuration for the parent direction +--- the root of this configuration chain will always be a test suite. Once the +test configuration is cloned :program:`lit` checks for a *lit.local.cfg* file +in the subdirectory. If present, this file will be loaded and can be used to +specialize the configuration for each individual directory. This facility can +be used to define subdirectories of optional tests, or to change other +configuration parameters --- for example, to change the test format, or the +suffixes which identify test files. + +TEST RUN OUTPUT FORMAT +~~~~~~~~~~~~~~~~~~~~~~ + +The :program:`lit` output for a test run conforms to the following schema, in +both short and verbose modes (although in short mode no PASS lines will be +shown). This schema has been chosen to be relatively easy to reliably parse by +a machine (for example in buildbot log scraping), and for other tools to +generate. + +Each test result is expected to appear on a line that matches: + +.. code-block:: none + + : () + +where ```` is a standard test result such as PASS, FAIL, XFAIL, +XPASS, UNRESOLVED, or UNSUPPORTED. The performance result codes of IMPROVED and +REGRESSED are also allowed. + +The ```` field can consist of an arbitrary string containing no +newline. + +The ```` field can be used to report progress information such +as (1/300) or can be empty, but even when empty the parentheses are required. + +Each test result may include additional (multiline) log information in the +following format: + +.. code-block:: none + + TEST '()' + ... log message ... + + +where ```` should be the name of a preceding reported test, ```` is a string of "*" characters *at least* four characters long +(the recommended length is 20), and ```` is an arbitrary +(unparsed) string. + +The following is an example of a test run output which consists of four tests A, +B, C, and D, and a log message for the failing test C: + +.. code-block:: none + + PASS: A (1 of 4) + PASS: B (2 of 4) + FAIL: C (3 of 4) + ******************** TEST 'C' FAILED ******************** + Test 'C' failed as a result of exit code 1. + ******************** + PASS: D (4 of 4) + +LIT EXAMPLE TESTS +~~~~~~~~~~~~~~~~~ + +The :program:`lit` distribution contains several example implementations of +test suites in the *ExampleTests* directory. + +SEE ALSO +-------- + +valgrind(1) diff --git a/docs/CommandGuide/llc.rst b/docs/CommandGuide/llc.rst new file mode 100644 index 00000000..02ad798c --- /dev/null +++ b/docs/CommandGuide/llc.rst @@ -0,0 +1,195 @@ +llc - LLVM static compiler +========================== + +SYNOPSIS +-------- + +:program:`llc` [*options*] [*filename*] + +DESCRIPTION +----------- + +The :program:`llc` command compiles LLVM source inputs into assembly language +for a specified architecture. The assembly language output can then be passed +through a native assembler and linker to generate a native executable. + +The choice of architecture for the output assembly code is automatically +determined from the input file, unless the :option:`-march` option is used to +override the default. + +OPTIONS +------- + +If ``filename`` is "``-``" or omitted, :program:`llc` reads from standard input. +Otherwise, it will from ``filename``. Inputs can be in either the LLVM assembly +language format (``.ll``) or the LLVM bitcode format (``.bc``). + +If the :option:`-o` option is omitted, then :program:`llc` will send its output +to standard output if the input is from standard input. If the :option:`-o` +option specifies "``-``", then the output will also be sent to standard output. + +If no :option:`-o` option is specified and an input file other than "``-``" is +specified, then :program:`llc` creates the output filename by taking the input +filename, removing any existing ``.bc`` extension, and adding a ``.s`` suffix. + +Other :program:`llc` options are described below. + +End-user Options +~~~~~~~~~~~~~~~~ + +.. option:: -help + + Print a summary of command line options. + +.. option:: -O=uint + + Generate code at different optimization levels. These correspond to the + ``-O0``, ``-O1``, ``-O2``, and ``-O3`` optimization levels used by + :program:`llvm-gcc` and :program:`clang`. + +.. option:: -mtriple= + + Override the target triple specified in the input file with the specified + string. + +.. option:: -march= + + Specify the architecture for which to generate assembly, overriding the target + encoded in the input file. See the output of ``llc -help`` for a list of + valid architectures. By default this is inferred from the target triple or + autodetected to the current architecture. + +.. option:: -mcpu= + + Specify a specific chip in the current architecture to generate code for. + By default this is inferred from the target triple and autodetected to + the current architecture. For a list of available CPUs, use: + + .. code-block:: none + + llvm-as < /dev/null | llc -march=xyz -mcpu=help + +.. option:: -filetype= + + Specify what kind of output ``llc`` should generated. Options are: ``asm`` + for textual assembly ( ``'.s'``), ``obj`` for native object files (``'.o'``) + and ``null`` for not emitting anything (for performance testing). + + Note that not all targets support all options. + +.. option:: -mattr=a1,+a2,-a3,... + + Override or control specific attributes of the target, such as whether SIMD + operations are enabled or not. The default set of attributes is set by the + current CPU. For a list of available attributes, use: + + .. code-block:: none + + llvm-as < /dev/null | llc -march=xyz -mattr=help + +.. option:: --disable-fp-elim + + Disable frame pointer elimination optimization. + +.. option:: --disable-excess-fp-precision + + Disable optimizations that may produce excess precision for floating point. + Note that this option can dramatically slow down code on some systems + (e.g. X86). + +.. option:: --enable-no-infs-fp-math + + Enable optimizations that assume no Inf values. + +.. option:: --enable-no-nans-fp-math + + Enable optimizations that assume no NAN values. + +.. option:: --enable-unsafe-fp-math + + Enable optimizations that make unsafe assumptions about IEEE math (e.g. that + addition is associative) or may not work for all input ranges. These + optimizations allow the code generator to make use of some instructions which + would otherwise not be usable (such as ``fsin`` on X86). + +.. option:: --enable-correct-eh-support + + Instruct the **lowerinvoke** pass to insert code for correct exception + handling support. This is expensive and is by default omitted for efficiency. + +.. option:: --stats + + Print statistics recorded by code-generation passes. + +.. option:: --time-passes + + Record the amount of time needed for each pass and print a report to standard + error. + +.. option:: --load= + + Dynamically load ``dso_path`` (a path to a dynamically shared object) that + implements an LLVM target. This will permit the target name to be used with + the :option:`-march` option so that code can be generated for that target. + +Tuning/Configuration Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. option:: --print-machineinstrs + + Print generated machine code between compilation phases (useful for debugging). + +.. option:: --regalloc= + + Specify the register allocator to use. + Valid register allocators are: + + *basic* + + Basic register allocator. + + *fast* + + Fast register allocator. It is the default for unoptimized code. + + *greedy* + + Greedy register allocator. It is the default for optimized code. + + *pbqp* + + Register allocator based on 'Partitioned Boolean Quadratic Programming'. + +.. option:: --spiller= + + Specify the spiller to use for register allocators that support it. Currently + this option is used only by the linear scan register allocator. The default + ``spiller`` is *local*. Valid spillers are: + + *simple* + + Simple spiller + + *local* + + Local spiller + +Intel IA-32-specific Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. option:: --x86-asm-syntax=[att|intel] + + Specify whether to emit assembly code in AT&T syntax (the default) or Intel + syntax. + +EXIT STATUS +----------- + +If :program:`llc` succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. + +SEE ALSO +-------- + +lli + diff --git a/docs/CommandGuide/lli.rst b/docs/CommandGuide/lli.rst new file mode 100644 index 00000000..a9aaf310 --- /dev/null +++ b/docs/CommandGuide/lli.rst @@ -0,0 +1,300 @@ +lli - directly execute programs from LLVM bitcode +================================================= + + +SYNOPSIS +-------- + + +**lli** [*options*] [*filename*] [*program args*] + + +DESCRIPTION +----------- + + +**lli** directly executes programs in LLVM bitcode format. It takes a program +in LLVM bitcode format and executes it using a just-in-time compiler, if one is +available for the current architecture, or an interpreter. **lli** takes all of +the same code generator options as llc|llc, but they are only effective when +**lli** is using the just-in-time compiler. + +If *filename* is not specified, then **lli** reads the LLVM bitcode for the +program from standard input. + +The optional *args* specified on the command line are passed to the program as +arguments. + + +GENERAL OPTIONS +--------------- + + + +**-fake-argv0**\ =\ *executable* + + Override the ``argv[0]`` value passed into the executing program. + + + +**-force-interpreter**\ =\ *{false,true}* + + If set to true, use the interpreter even if a just-in-time compiler is available + for this architecture. Defaults to false. + + + +**-help** + + Print a summary of command line options. + + + +**-load**\ =\ *pluginfilename* + + Causes **lli** to load the plugin (shared object) named *pluginfilename* and use + it for optimization. + + + +**-stats** + + Print statistics from the code-generation passes. This is only meaningful for + the just-in-time compiler, at present. + + + +**-time-passes** + + Record the amount of time needed for each code-generation pass and print it to + standard error. + + + +**-version** + + Print out the version of **lli** and exit without doing anything else. + + + + +TARGET OPTIONS +-------------- + + + +**-mtriple**\ =\ *target triple* + + Override the target triple specified in the input bitcode file with the + specified string. This may result in a crash if you pick an + architecture which is not compatible with the current system. + + + +**-march**\ =\ *arch* + + Specify the architecture for which to generate assembly, overriding the target + encoded in the bitcode file. See the output of **llc -help** for a list of + valid architectures. By default this is inferred from the target triple or + autodetected to the current architecture. + + + +**-mcpu**\ =\ *cpuname* + + Specify a specific chip in the current architecture to generate code for. + By default this is inferred from the target triple and autodetected to + the current architecture. For a list of available CPUs, use: + **llvm-as < /dev/null | llc -march=xyz -mcpu=help** + + + +**-mattr**\ =\ *a1,+a2,-a3,...* + + Override or control specific attributes of the target, such as whether SIMD + operations are enabled or not. The default set of attributes is set by the + current CPU. For a list of available attributes, use: + **llvm-as < /dev/null | llc -march=xyz -mattr=help** + + + + +FLOATING POINT OPTIONS +---------------------- + + + +**-disable-excess-fp-precision** + + Disable optimizations that may increase floating point precision. + + + +**-enable-no-infs-fp-math** + + Enable optimizations that assume no Inf values. + + + +**-enable-no-nans-fp-math** + + Enable optimizations that assume no NAN values. + + + +**-enable-unsafe-fp-math** + + Causes **lli** to enable optimizations that may decrease floating point + precision. + + + +**-soft-float** + + Causes **lli** to generate software floating point library calls instead of + equivalent hardware instructions. + + + + +CODE GENERATION OPTIONS +----------------------- + + + +**-code-model**\ =\ *model* + + Choose the code model from: + + + .. code-block:: perl + + default: Target default code model + small: Small code model + kernel: Kernel code model + medium: Medium code model + large: Large code model + + + + +**-disable-post-RA-scheduler** + + Disable scheduling after register allocation. + + + +**-disable-spill-fusing** + + Disable fusing of spill code into instructions. + + + +**-enable-correct-eh-support** + + Make the -lowerinvoke pass insert expensive, but correct, EH code. + + + +**-jit-enable-eh** + + Exception handling should be enabled in the just-in-time compiler. + + + +**-join-liveintervals** + + Coalesce copies (default=true). + + + +**-nozero-initialized-in-bss** Don't place zero-initialized symbols into the BSS section. + + + +**-pre-RA-sched**\ =\ *scheduler* + + Instruction schedulers available (before register allocation): + + + .. code-block:: perl + + =default: Best scheduler for the target + =none: No scheduling: breadth first sequencing + =simple: Simple two pass scheduling: minimize critical path and maximize processor utilization + =simple-noitin: Simple two pass scheduling: Same as simple except using generic latency + =list-burr: Bottom-up register reduction list scheduling + =list-tdrr: Top-down register reduction list scheduling + =list-td: Top-down list scheduler -print-machineinstrs - Print generated machine code + + + + +**-regalloc**\ =\ *allocator* + + Register allocator to use (default=linearscan) + + + .. code-block:: perl + + =bigblock: Big-block register allocator + =linearscan: linear scan register allocator =local - local register allocator + =simple: simple register allocator + + + + +**-relocation-model**\ =\ *model* + + Choose relocation model from: + + + .. code-block:: perl + + =default: Target default relocation model + =static: Non-relocatable code =pic - Fully relocatable, position independent code + =dynamic-no-pic: Relocatable external references, non-relocatable code + + + + +**-spiller** + + Spiller to use (default=local) + + + .. code-block:: perl + + =simple: simple spiller + =local: local spiller + + + + +**-x86-asm-syntax**\ =\ *syntax* + + Choose style of code to emit from X86 backend: + + + .. code-block:: perl + + =att: Emit AT&T-style assembly + =intel: Emit Intel-style assembly + + + + + +EXIT STATUS +----------- + + +If **lli** fails to load the program, it will exit with an exit code of 1. +Otherwise, it will return the exit code of the program it executes. + + +SEE ALSO +-------- + + +llc|llc diff --git a/docs/CommandGuide/llvm-ar.rst b/docs/CommandGuide/llvm-ar.rst new file mode 100644 index 00000000..d3ee993f --- /dev/null +++ b/docs/CommandGuide/llvm-ar.rst @@ -0,0 +1,367 @@ +llvm-ar - LLVM archiver +======================= + + +SYNOPSIS +-------- + + +**llvm-ar** [-]{dmpqrtx}[Rabfikou] [relpos] [count] [files...] + + +DESCRIPTION +----------- + + +The **llvm-ar** command is similar to the common Unix utility, ``ar``. It +archives several files together into a single file. The intent for this is +to produce archive libraries by LLVM bitcode that can be linked into an +LLVM program. However, the archive can contain any kind of file. By default, +**llvm-ar** generates a symbol table that makes linking faster because +only the symbol table needs to be consulted, not each individual file member +of the archive. + +The **llvm-ar** command can be used to *read* SVR4, GNU and BSD style archive +files. However, right now it can only write in the GNU format. If an +SVR4 or BSD style archive is used with the ``r`` (replace) or ``q`` (quick +update) operations, the archive will be reconstructed in GNU format. + +Here's where **llvm-ar** departs from previous ``ar`` implementations: + + +*Symbol Table* + + Since **llvm-ar** supports bitcode files. The symbol table it creates + is in GNU format and includes both native and bitcode files. + + +*Long Paths* + + Currently **llvm-ar** can read GNU and BSD long file names, but only writes + archives with the GNU format. + + + +OPTIONS +------- + + +The options to **llvm-ar** are compatible with other ``ar`` implementations. +However, there are a few modifiers (*R*) that are not found in other ``ar`` +implementations. The options to **llvm-ar** specify a single basic operation to +perform on the archive, a variety of modifiers for that operation, the name of +the archive file, and an optional list of file names. These options are used to +determine how **llvm-ar** should process the archive file. + +The Operations and Modifiers are explained in the sections below. The minimal +set of options is at least one operator and the name of the archive. Typically +archive files end with a ``.a`` suffix, but this is not required. Following +the *archive-name* comes a list of *files* that indicate the specific members +of the archive to operate on. If the *files* option is not specified, it +generally means either "none" or "all" members, depending on the operation. + +Operations +~~~~~~~~~~ + + + +d + + Delete files from the archive. No modifiers are applicable to this operation. + The *files* options specify which members should be removed from the + archive. It is not an error if a specified file does not appear in the archive. + If no *files* are specified, the archive is not modified. + + + +m[abi] + + Move files from one location in the archive to another. The *a*, *b*, and + *i* modifiers apply to this operation. The *files* will all be moved + to the location given by the modifiers. If no modifiers are used, the files + will be moved to the end of the archive. If no *files* are specified, the + archive is not modified. + + + +p + + Print files to the standard output. This operation simply prints the + *files* indicated to the standard output. If no *files* are + specified, the entire archive is printed. Printing bitcode files is + ill-advised as they might confuse your terminal settings. The *p* + operation never modifies the archive. + + + +q + + Quickly append files to the end of the archive. This operation quickly adds the + *files* to the archive without checking for duplicates that should be + removed first. If no *files* are specified, the archive is not modified. + Because of the way that **llvm-ar** constructs the archive file, its dubious + whether the *q* operation is any faster than the *r* operation. + + + +r[abu] + + Replace or insert file members. The *a*, *b*, and *u* + modifiers apply to this operation. This operation will replace existing + *files* or insert them at the end of the archive if they do not exist. If no + *files* are specified, the archive is not modified. + + + +t[v] + + Print the table of contents. Without any modifiers, this operation just prints + the names of the members to the standard output. With the *v* modifier, + **llvm-ar** also prints out the file type (B=bitcode, S=symbol + table, blank=regular file), the permission mode, the owner and group, the + size, and the date. If any *files* are specified, the listing is only for + those files. If no *files* are specified, the table of contents for the + whole archive is printed. + + + +x[oP] + + Extract archive members back to files. The *o* modifier applies to this + operation. This operation retrieves the indicated *files* from the archive + and writes them back to the operating system's file system. If no + *files* are specified, the entire archive is extract. + + + + +Modifiers (operation specific) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +The modifiers below are specific to certain operations. See the Operations +section (above) to determine which modifiers are applicable to which operations. + + +[a] + + When inserting or moving member files, this option specifies the destination of + the new files as being after the *relpos* member. If *relpos* is not found, + the files are placed at the end of the archive. + + + +[b] + + When inserting or moving member files, this option specifies the destination of + the new files as being before the *relpos* member. If *relpos* is not + found, the files are placed at the end of the archive. This modifier is + identical to the *i* modifier. + + + +[i] + + A synonym for the *b* option. + + + +[o] + + When extracting files, this option will cause **llvm-ar** to preserve the + original modification times of the files it writes. + + + +[u] + + When replacing existing files in the archive, only replace those files that have + a time stamp than the time stamp of the member in the archive. + + + + +Modifiers (generic) +~~~~~~~~~~~~~~~~~~~ + + +The modifiers below may be applied to any operation. + + +[c] + + For all operations, **llvm-ar** will always create the archive if it doesn't + exist. Normally, **llvm-ar** will print a warning message indicating that the + archive is being created. Using this modifier turns off that warning. + + + +[s] + + This modifier requests that an archive index (or symbol table) be added to the + archive. This is the default mode of operation. The symbol table will contain + all the externally visible functions and global variables defined by all the + bitcode files in the archive. + + + +[S] + + This modifier is the opposite of the *s* modifier. It instructs **llvm-ar** to + not build the symbol table. If both *s* and *S* are used, the last modifier to + occur in the options will prevail. + + + +[v] + + This modifier instructs **llvm-ar** to be verbose about what it is doing. Each + editing operation taken against the archive will produce a line of output saying + what is being done. + + + + + +STANDARDS +--------- + + +The **llvm-ar** utility is intended to provide a superset of the IEEE Std 1003.2 +(POSIX.2) functionality for ``ar``. **llvm-ar** can read both SVR4 and BSD4.4 (or +Mac OS X) archives. If the ``f`` modifier is given to the ``x`` or ``r`` operations +then **llvm-ar** will write SVR4 compatible archives. Without this modifier, +**llvm-ar** will write BSD4.4 compatible archives that have long names +immediately after the header and indicated using the "#1/ddd" notation for the +name in the header. + + +FILE FORMAT +----------- + + +The file format for LLVM Archive files is similar to that of BSD 4.4 or Mac OSX +archive files. In fact, except for the symbol table, the ``ar`` commands on those +operating systems should be able to read LLVM archive files. The details of the +file format follow. + +Each archive begins with the archive magic number which is the eight printable +characters "!\n" where \n represents the newline character (0x0A). +Following the magic number, the file is composed of even length members that +begin with an archive header and end with a \n padding character if necessary +(to make the length even). Each file member is composed of a header (defined +below), an optional newline-terminated "long file name" and the contents of +the file. + +The fields of the header are described in the items below. All fields of the +header contain only ASCII characters, are left justified and are right padded +with space characters. + + +name - char[16] + + This field of the header provides the name of the archive member. If the name is + longer than 15 characters or contains a slash (/) character, then this field + contains ``#1/nnn`` where ``nnn`` provides the length of the name and the ``#1/`` + is literal. In this case, the actual name of the file is provided in the ``nnn`` + bytes immediately following the header. If the name is 15 characters or less, it + is contained directly in this field and terminated with a slash (/) character. + + + +date - char[12] + + This field provides the date of modification of the file in the form of a + decimal encoded number that provides the number of seconds since the epoch + (since 00:00:00 Jan 1, 1970) per Posix specifications. + + + +uid - char[6] + + This field provides the user id of the file encoded as a decimal ASCII string. + This field might not make much sense on non-Unix systems. On Unix, it is the + same value as the st_uid field of the stat structure returned by the stat(2) + operating system call. + + + +gid - char[6] + + This field provides the group id of the file encoded as a decimal ASCII string. + This field might not make much sense on non-Unix systems. On Unix, it is the + same value as the st_gid field of the stat structure returned by the stat(2) + operating system call. + + + +mode - char[8] + + This field provides the access mode of the file encoded as an octal ASCII + string. This field might not make much sense on non-Unix systems. On Unix, it + is the same value as the st_mode field of the stat structure returned by the + stat(2) operating system call. + + + +size - char[10] + + This field provides the size of the file, in bytes, encoded as a decimal ASCII + string. + + + +fmag - char[2] + + This field is the archive file member magic number. Its content is always the + two characters back tick (0x60) and newline (0x0A). This provides some measure + utility in identifying archive files that have been corrupted. + + +offset - vbr encoded 32-bit integer + + The offset item provides the offset into the archive file where the bitcode + member is stored that is associated with the symbol. The offset value is 0 + based at the start of the first "normal" file member. To derive the actual + file offset of the member, you must add the number of bytes occupied by the file + signature (8 bytes) and the symbol tables. The value of this item is encoded + using variable bit rate encoding to reduce the size of the symbol table. + Variable bit rate encoding uses the high bit (0x80) of each byte to indicate + if there are more bytes to follow. The remaining 7 bits in each byte carry bits + from the value. The final byte does not have the high bit set. + + + +length - vbr encoded 32-bit integer + + The length item provides the length of the symbol that follows. Like this + *offset* item, the length is variable bit rate encoded. + + + +symbol - character array + + The symbol item provides the text of the symbol that is associated with the + *offset*. The symbol is not terminated by any character. Its length is provided + by the *length* field. Note that is allowed (but unwise) to use non-printing + characters (even 0x00) in the symbol. This allows for multiple encodings of + symbol names. + + + + +EXIT STATUS +----------- + + +If **llvm-ar** succeeds, it will exit with 0. A usage error, results +in an exit code of 1. A hard (file system typically) error results in an +exit code of 2. Miscellaneous or unknown errors result in an +exit code of 3. + + +SEE ALSO +-------- + + +ar(1) diff --git a/docs/CommandGuide/llvm-as.rst b/docs/CommandGuide/llvm-as.rst new file mode 100644 index 00000000..1b499bbe --- /dev/null +++ b/docs/CommandGuide/llvm-as.rst @@ -0,0 +1,56 @@ +llvm-as - LLVM assembler +======================== + +SYNOPSIS +-------- + +**llvm-as** [*options*] [*filename*] + +DESCRIPTION +----------- + +**llvm-as** is the LLVM assembler. It reads a file containing human-readable +LLVM assembly language, translates it to LLVM bitcode, and writes the result +into a file or to standard output. + +If *filename* is omitted or is ``-``, then **llvm-as** reads its input from +standard input. + +If an output file is not specified with the **-o** option, then +**llvm-as** sends its output to a file or standard output by following +these rules: + +* If the input is standard input, then the output is standard output. + +* If the input is a file that ends with ``.ll``, then the output file is of the + same name, except that the suffix is changed to ``.bc``. + +* If the input is a file that does not end with the ``.ll`` suffix, then the + output file has the same name as the input file, except that the ``.bc`` + suffix is appended. + +OPTIONS +------- + +**-f** + Enable binary output on terminals. Normally, **llvm-as** will refuse to + write raw bitcode output if the output stream is a terminal. With this option, + **llvm-as** will write raw bitcode regardless of the output device. + +**-help** + Print a summary of command line options. + +**-o** *filename* + Specify the output file name. If *filename* is ``-``, then **llvm-as** + sends its output to standard output. + +EXIT STATUS +----------- + +If **llvm-as** succeeds, it will exit with 0. Otherwise, if an error occurs, it +will exit with a non-zero value. + +SEE ALSO +-------- + +llvm-dis|llvm-dis, gccas|gccas diff --git a/docs/CommandGuide/llvm-bcanalyzer.rst b/docs/CommandGuide/llvm-bcanalyzer.rst new file mode 100644 index 00000000..7254088e --- /dev/null +++ b/docs/CommandGuide/llvm-bcanalyzer.rst @@ -0,0 +1,305 @@ +llvm-bcanalyzer - LLVM bitcode analyzer +======================================= + +SYNOPSIS +-------- + +:program:`llvm-bcanalyzer` [*options*] [*filename*] + +DESCRIPTION +----------- + +The :program:`llvm-bcanalyzer` command is a small utility for analyzing bitcode +files. The tool reads a bitcode file (such as generated with the +:program:`llvm-as` tool) and produces a statistical report on the contents of +the bitcode file. The tool can also dump a low level but human readable +version of the bitcode file. This tool is probably not of much interest or +utility except for those working directly with the bitcode file format. Most +LLVM users can just ignore this tool. + +If *filename* is omitted or is ``-``, then :program:`llvm-bcanalyzer` reads its +input from standard input. This is useful for combining the tool into a +pipeline. Output is written to the standard output. + +OPTIONS +------- + +.. program:: llvm-bcanalyzer + +.. option:: -nodetails + + Causes :program:`llvm-bcanalyzer` to abbreviate its output by writing out only + a module level summary. The details for individual functions are not + displayed. + +.. option:: -dump + + Causes :program:`llvm-bcanalyzer` to dump the bitcode in a human readable + format. This format is significantly different from LLVM assembly and + provides details about the encoding of the bitcode file. + +.. option:: -verify + + Causes :program:`llvm-bcanalyzer` to verify the module produced by reading the + bitcode. This ensures that the statistics generated are based on a consistent + module. + +.. option:: -help + + Print a summary of command line options. + +EXIT STATUS +----------- + +If :program:`llvm-bcanalyzer` succeeds, it will exit with 0. Otherwise, if an +error occurs, it will exit with a non-zero value, usually 1. + +SUMMARY OUTPUT DEFINITIONS +-------------------------- + +The following items are always printed by llvm-bcanalyzer. They comprize the +summary output. + +**Bitcode Analysis Of Module** + + This just provides the name of the module for which bitcode analysis is being + generated. + +**Bitcode Version Number** + + The bitcode version (not LLVM version) of the file read by the analyzer. + +**File Size** + + The size, in bytes, of the entire bitcode file. + +**Module Bytes** + + The size, in bytes, of the module block. Percentage is relative to File Size. + +**Function Bytes** + + The size, in bytes, of all the function blocks. Percentage is relative to File + Size. + +**Global Types Bytes** + + The size, in bytes, of the Global Types Pool. Percentage is relative to File + Size. This is the size of the definitions of all types in the bitcode file. + +**Constant Pool Bytes** + + The size, in bytes, of the Constant Pool Blocks Percentage is relative to File + Size. + +**Module Globals Bytes** + + Ths size, in bytes, of the Global Variable Definitions and their initializers. + Percentage is relative to File Size. + +**Instruction List Bytes** + + The size, in bytes, of all the instruction lists in all the functions. + Percentage is relative to File Size. Note that this value is also included in + the Function Bytes. + +**Compaction Table Bytes** + + The size, in bytes, of all the compaction tables in all the functions. + Percentage is relative to File Size. Note that this value is also included in + the Function Bytes. + +**Symbol Table Bytes** + + The size, in bytes, of all the symbol tables in all the functions. Percentage is + relative to File Size. Note that this value is also included in the Function + Bytes. + +**Dependent Libraries Bytes** + + The size, in bytes, of the list of dependent libraries in the module. Percentage + is relative to File Size. Note that this value is also included in the Module + Global Bytes. + +**Number Of Bitcode Blocks** + + The total number of blocks of any kind in the bitcode file. + +**Number Of Functions** + + The total number of function definitions in the bitcode file. + +**Number Of Types** + + The total number of types defined in the Global Types Pool. + +**Number Of Constants** + + The total number of constants (of any type) defined in the Constant Pool. + +**Number Of Basic Blocks** + + The total number of basic blocks defined in all functions in the bitcode file. + +**Number Of Instructions** + + The total number of instructions defined in all functions in the bitcode file. + +**Number Of Long Instructions** + + The total number of long instructions defined in all functions in the bitcode + file. Long instructions are those taking greater than 4 bytes. Typically long + instructions are GetElementPtr with several indices, PHI nodes, and calls to + functions with large numbers of arguments. + +**Number Of Operands** + + The total number of operands used in all instructions in the bitcode file. + +**Number Of Compaction Tables** + + The total number of compaction tables in all functions in the bitcode file. + +**Number Of Symbol Tables** + + The total number of symbol tables in all functions in the bitcode file. + +**Number Of Dependent Libs** + + The total number of dependent libraries found in the bitcode file. + +**Total Instruction Size** + + The total size of the instructions in all functions in the bitcode file. + +**Average Instruction Size** + + The average number of bytes per instruction across all functions in the bitcode + file. This value is computed by dividing Total Instruction Size by Number Of + Instructions. + +**Maximum Type Slot Number** + + The maximum value used for a type's slot number. Larger slot number values take + more bytes to encode. + +**Maximum Value Slot Number** + + The maximum value used for a value's slot number. Larger slot number values take + more bytes to encode. + +**Bytes Per Value** + + The average size of a Value definition (of any type). This is computed by + dividing File Size by the total number of values of any type. + +**Bytes Per Global** + + The average size of a global definition (constants and global variables). + +**Bytes Per Function** + + The average number of bytes per function definition. This is computed by + dividing Function Bytes by Number Of Functions. + +**# of VBR 32-bit Integers** + + The total number of 32-bit integers encoded using the Variable Bit Rate + encoding scheme. + +**# of VBR 64-bit Integers** + + The total number of 64-bit integers encoded using the Variable Bit Rate encoding + scheme. + +**# of VBR Compressed Bytes** + + The total number of bytes consumed by the 32-bit and 64-bit integers that use + the Variable Bit Rate encoding scheme. + +**# of VBR Expanded Bytes** + + The total number of bytes that would have been consumed by the 32-bit and 64-bit + integers had they not been compressed with the Variable Bit Rage encoding + scheme. + +**Bytes Saved With VBR** + + The total number of bytes saved by using the Variable Bit Rate encoding scheme. + The percentage is relative to # of VBR Expanded Bytes. + +DETAILED OUTPUT DEFINITIONS +--------------------------- + +The following definitions occur only if the -nodetails option was not given. +The detailed output provides additional information on a per-function basis. + +**Type** + + The type signature of the function. + +**Byte Size** + + The total number of bytes in the function's block. + +**Basic Blocks** + + The number of basic blocks defined by the function. + +**Instructions** + + The number of instructions defined by the function. + +**Long Instructions** + + The number of instructions using the long instruction format in the function. + +**Operands** + + The number of operands used by all instructions in the function. + +**Instruction Size** + + The number of bytes consumed by instructions in the function. + +**Average Instruction Size** + + The average number of bytes consumed by the instructions in the function. + This value is computed by dividing Instruction Size by Instructions. + +**Bytes Per Instruction** + + The average number of bytes used by the function per instruction. This value + is computed by dividing Byte Size by Instructions. Note that this is not the + same as Average Instruction Size. It computes a number relative to the total + function size not just the size of the instruction list. + +**Number of VBR 32-bit Integers** + + The total number of 32-bit integers found in this function (for any use). + +**Number of VBR 64-bit Integers** + + The total number of 64-bit integers found in this function (for any use). + +**Number of VBR Compressed Bytes** + + The total number of bytes in this function consumed by the 32-bit and 64-bit + integers that use the Variable Bit Rate encoding scheme. + +**Number of VBR Expanded Bytes** + + The total number of bytes in this function that would have been consumed by + the 32-bit and 64-bit integers had they not been compressed with the Variable + Bit Rate encoding scheme. + +**Bytes Saved With VBR** + + The total number of bytes saved in this function by using the Variable Bit + Rate encoding scheme. The percentage is relative to # of VBR Expanded Bytes. + +SEE ALSO +-------- + +:doc:`/CommandGuide/llvm-dis`, :doc:`/BitCodeFormat` + diff --git a/docs/CommandGuide/llvm-build.rst b/docs/CommandGuide/llvm-build.rst new file mode 100644 index 00000000..f788f7c5 --- /dev/null +++ b/docs/CommandGuide/llvm-build.rst @@ -0,0 +1,102 @@ +llvm-build - LLVM Project Build Utility +======================================= + + +SYNOPSIS +-------- + + +**llvm-build** [*options*] + + +DESCRIPTION +----------- + + +**llvm-build** is a tool for working with LLVM projects that use the LLVMBuild +system for describing their components. + +At heart, **llvm-build** is responsible for loading, verifying, and manipulating +the project's component data. The tool is primarily designed for use in +implementing build systems and tools which need access to the project structure +information. + + +OPTIONS +------- + + + +**-h**, **--help** + + Print the builtin program help. + + + +**--source-root**\ =\ *PATH* + + If given, load the project at the given source root path. If this option is not + given, the location of the project sources will be inferred from the location of + the **llvm-build** script itself. + + + +**--print-tree** + + Print the component tree for the project. + + + +**--write-library-table** + + Write out the C++ fragment which defines the components, library names, and + required libraries. This C++ fragment is built into llvm-config|llvm-config + in order to provide clients with the list of required libraries for arbitrary + component combinations. + + + +**--write-llvmbuild** + + Write out new *LLVMBuild.txt* files based on the loaded components. This is + useful for auto-upgrading the schema of the files. **llvm-build** will try to a + limited extent to preserve the comments which were written in the original + source file, although at this time it only preserves block comments that precede + the section names in the *LLVMBuild* files. + + + +**--write-cmake-fragment** + + Write out the LLVMBuild in the form of a CMake fragment, so it can easily be + consumed by the CMake based build system. The exact contents and format of this + file are closely tied to how LLVMBuild is integrated with CMake, see LLVM's + top-level CMakeLists.txt. + + + +**--write-make-fragment** + + Write out the LLVMBuild in the form of a Makefile fragment, so it can easily be + consumed by a Make based build system. The exact contents and format of this + file are closely tied to how LLVMBuild is integrated with the Makefiles, see + LLVM's Makefile.rules. + + + +**--llvmbuild-source-root**\ =\ *PATH* + + If given, expect the *LLVMBuild* files for the project to be rooted at the + given path, instead of inside the source tree itself. This option is primarily + designed for use in conjunction with **--write-llvmbuild** to test changes to + *LLVMBuild* schema. + + + + +EXIT STATUS +----------- + + +**llvm-build** exits with 0 if operation was successful. Otherwise, it will exist +with a non-zero value. diff --git a/docs/CommandGuide/llvm-config.rst b/docs/CommandGuide/llvm-config.rst new file mode 100644 index 00000000..0ebb344c --- /dev/null +++ b/docs/CommandGuide/llvm-config.rst @@ -0,0 +1,176 @@ +llvm-config - Print LLVM compilation options +============================================ + + +SYNOPSIS +-------- + + +**llvm-config** *option* [*components*...] + + +DESCRIPTION +----------- + + +**llvm-config** makes it easier to build applications that use LLVM. It can +print the compiler flags, linker flags and object libraries needed to link +against LLVM. + + +EXAMPLES +-------- + + +To link against the JIT: + + +.. code-block:: sh + + g++ `llvm-config --cxxflags` -o HowToUseJIT.o -c HowToUseJIT.cpp + g++ `llvm-config --ldflags` -o HowToUseJIT HowToUseJIT.o \ + `llvm-config --libs engine bcreader scalaropts` + + + +OPTIONS +------- + + + +**--version** + + Print the version number of LLVM. + + + +**-help** + + Print a summary of **llvm-config** arguments. + + + +**--prefix** + + Print the installation prefix for LLVM. + + + +**--src-root** + + Print the source root from which LLVM was built. + + + +**--obj-root** + + Print the object root used to build LLVM. + + + +**--bindir** + + Print the installation directory for LLVM binaries. + + + +**--includedir** + + Print the installation directory for LLVM headers. + + + +**--libdir** + + Print the installation directory for LLVM libraries. + + + +**--cxxflags** + + Print the C++ compiler flags needed to use LLVM headers. + + + +**--ldflags** + + Print the flags needed to link against LLVM libraries. + + + +**--libs** + + Print all the libraries needed to link against the specified LLVM + *components*, including any dependencies. + + + +**--libnames** + + Similar to **--libs**, but prints the bare filenames of the libraries + without **-l** or pathnames. Useful for linking against a not-yet-installed + copy of LLVM. + + + +**--libfiles** + + Similar to **--libs**, but print the full path to each library file. This is + useful when creating makefile dependencies, to ensure that a tool is relinked if + any library it uses changes. + + + +**--components** + + Print all valid component names. + + + +**--targets-built** + + Print the component names for all targets supported by this copy of LLVM. + + + +**--build-mode** + + Print the build mode used when LLVM was built (e.g. Debug or Release) + + + + +COMPONENTS +---------- + + +To print a list of all available components, run **llvm-config +--components**. In most cases, components correspond directly to LLVM +libraries. Useful "virtual" components include: + + +**all** + + Includes all LLVM libaries. The default if no components are specified. + + + +**backend** + + Includes either a native backend or the C backend. + + + +**engine** + + Includes either a native JIT or the bitcode interpreter. + + + + +EXIT STATUS +----------- + + +If **llvm-config** succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. diff --git a/docs/CommandGuide/llvm-cov.rst b/docs/CommandGuide/llvm-cov.rst new file mode 100644 index 00000000..524f2408 --- /dev/null +++ b/docs/CommandGuide/llvm-cov.rst @@ -0,0 +1,39 @@ +llvm-cov - emit coverage information +==================================== + +SYNOPSIS +-------- + +:program:`llvm-cov` [-gcno=filename] [-gcda=filename] [dump] + +DESCRIPTION +----------- + +The experimental :program:`llvm-cov` tool reads in description file generated +by compiler and coverage data file generated by instrumented program. This +program assumes that the description and data file uses same format as gcov +files. + +OPTIONS +------- + +.. option:: -gcno=filename + + This option selects input description file generated by compiler while + instrumenting program. + +.. option:: -gcda=filename + + This option selects coverage data file generated by instrumented compiler. + +.. option:: -dump + + This options enables output dump that is suitable for a developer to help + debug :program:`llvm-cov` itself. + +EXIT STATUS +----------- + +:program:`llvm-cov` returns 1 if it cannot read input files. Otherwise, it +exits with zero. + diff --git a/docs/CommandGuide/llvm-diff.rst b/docs/CommandGuide/llvm-diff.rst new file mode 100644 index 00000000..991d4fec --- /dev/null +++ b/docs/CommandGuide/llvm-diff.rst @@ -0,0 +1,56 @@ +llvm-diff - LLVM structural 'diff' +================================== + + +SYNOPSIS +-------- + + +**llvm-diff** [*options*] *module 1* *module 2* [*global name ...*] + + +DESCRIPTION +----------- + + +**llvm-diff** compares the structure of two LLVM modules, primarily +focusing on differences in function definitions. Insignificant +differences, such as changes in the ordering of globals or in the +names of local values, are ignored. + +An input module will be interpreted as an assembly file if its name +ends in '.ll'; otherwise it will be read in as a bitcode file. + +If a list of global names is given, just the values with those names +are compared; otherwise, all global values are compared, and +diagnostics are produced for globals which only appear in one module +or the other. + +**llvm-diff** compares two functions by comparing their basic blocks, +beginning with the entry blocks. If the terminators seem to match, +then the corresponding successors are compared; otherwise they are +ignored. This algorithm is very sensitive to changes in control flow, +which tend to stop any downstream changes from being detected. + +**llvm-diff** is intended as a debugging tool for writers of LLVM +passes and frontends. It does not have a stable output format. + + +EXIT STATUS +----------- + + +If **llvm-diff** finds no differences between the modules, it will exit +with 0 and produce no output. Otherwise it will exit with a non-zero +value. + + +BUGS +---- + + +Many important differences, like changes in linkage or function +attributes, are not diagnosed. + +Changes in memory behavior (for example, coalescing loads) can cause +massive detected differences in blocks. diff --git a/docs/CommandGuide/llvm-dis.rst b/docs/CommandGuide/llvm-dis.rst new file mode 100644 index 00000000..85cdca85 --- /dev/null +++ b/docs/CommandGuide/llvm-dis.rst @@ -0,0 +1,69 @@ +llvm-dis - LLVM disassembler +============================ + + +SYNOPSIS +-------- + + +**llvm-dis** [*options*] [*filename*] + + +DESCRIPTION +----------- + + +The **llvm-dis** command is the LLVM disassembler. It takes an LLVM +bitcode file and converts it into human-readable LLVM assembly language. + +If filename is omitted or specified as ``-``, **llvm-dis** reads its +input from standard input. + +If the input is being read from standard input, then **llvm-dis** +will send its output to standard output by default. Otherwise, the +output will be written to a file named after the input file, with +a ``.ll`` suffix added (any existing ``.bc`` suffix will first be +removed). You can override the choice of output file using the +**-o** option. + + +OPTIONS +------- + + + +**-f** + + Enable binary output on terminals. Normally, **llvm-dis** will refuse to + write raw bitcode output if the output stream is a terminal. With this option, + **llvm-dis** will write raw bitcode regardless of the output device. + + + +**-help** + + Print a summary of command line options. + + + +**-o** *filename* + + Specify the output file name. If *filename* is -, then the output is sent + to standard output. + + + + +EXIT STATUS +----------- + + +If **llvm-dis** succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. + + +SEE ALSO +-------- + + +llvm-as|llvm-as diff --git a/docs/CommandGuide/llvm-extract.rst b/docs/CommandGuide/llvm-extract.rst new file mode 100644 index 00000000..d0e9c1c2 --- /dev/null +++ b/docs/CommandGuide/llvm-extract.rst @@ -0,0 +1,79 @@ +llvm-extract - extract a function from an LLVM module +===================================================== + +SYNOPSIS +-------- + +:program:`llvm-extract` [*options*] **--func** *function-name* [*filename*] + +DESCRIPTION +----------- + +The :program:`llvm-extract` command takes the name of a function and extracts +it from the specified LLVM bitcode file. It is primarily used as a debugging +tool to reduce test cases from larger programs that are triggering a bug. + +In addition to extracting the bitcode of the specified function, +:program:`llvm-extract` will also remove unreachable global variables, +prototypes, and unused types. + +The :program:`llvm-extract` command reads its input from standard input if +filename is omitted or if filename is ``-``. The output is always written to +standard output, unless the **-o** option is specified (see below). + +OPTIONS +------- + +**-f** + + Enable binary output on terminals. Normally, :program:`llvm-extract` will + refuse to write raw bitcode output if the output stream is a terminal. With + this option, :program:`llvm-extract` will write raw bitcode regardless of the + output device. + +**--func** *function-name* + + Extract the function named *function-name* from the LLVM bitcode. May be + specified multiple times to extract multiple functions at once. + +**--rfunc** *function-regular-expr* + + Extract the function(s) matching *function-regular-expr* from the LLVM bitcode. + All functions matching the regular expression will be extracted. May be + specified multiple times. + +**--glob** *global-name* + + Extract the global variable named *global-name* from the LLVM bitcode. May be + specified multiple times to extract multiple global variables at once. + +**--rglob** *glob-regular-expr* + + Extract the global variable(s) matching *global-regular-expr* from the LLVM + bitcode. All global variables matching the regular expression will be + extracted. May be specified multiple times. + +**-help** + + Print a summary of command line options. + +**-o** *filename* + + Specify the output filename. If filename is "-" (the default), then + :program:`llvm-extract` sends its output to standard output. + +**-S** + + Write output in LLVM intermediate language (instead of bitcode). + +EXIT STATUS +----------- + +If :program:`llvm-extract` succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. + +SEE ALSO +-------- + +bugpoint + diff --git a/docs/CommandGuide/llvm-link.rst b/docs/CommandGuide/llvm-link.rst new file mode 100644 index 00000000..3bcfa68c --- /dev/null +++ b/docs/CommandGuide/llvm-link.rst @@ -0,0 +1,56 @@ +llvm-link - LLVM bitcode linker +=============================== + +SYNOPSIS +-------- + +:program:`llvm-link` [*options*] *filename ...* + +DESCRIPTION +----------- + +:program:`llvm-link` takes several LLVM bitcode files and links them together +into a single LLVM bitcode file. It writes the output file to standard output, +unless the :option:`-o` option is used to specify a filename. + +OPTIONS +------- + +.. option:: -f + + Enable binary output on terminals. Normally, :program:`llvm-link` will refuse + to write raw bitcode output if the output stream is a terminal. With this + option, :program:`llvm-link` will write raw bitcode regardless of the output + device. + +.. option:: -o filename + + Specify the output file name. If ``filename`` is "``-``", then + :program:`llvm-link` will write its output to standard output. + +.. option:: -S + + Write output in LLVM intermediate language (instead of bitcode). + +.. option:: -d + + If specified, :program:`llvm-link` prints a human-readable version of the + output bitcode file to standard error. + +.. option:: -help + + Print a summary of command line options. + +.. option:: -v + + Verbose mode. Print information about what :program:`llvm-link` is doing. + This typically includes a message for each bitcode file linked in and for each + library found. + +EXIT STATUS +----------- + +If :program:`llvm-link` succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. + + diff --git a/docs/CommandGuide/llvm-nm.rst b/docs/CommandGuide/llvm-nm.rst new file mode 100644 index 00000000..83d9fbaf --- /dev/null +++ b/docs/CommandGuide/llvm-nm.rst @@ -0,0 +1,146 @@ +llvm-nm - list LLVM bitcode and object file's symbol table +========================================================== + +SYNOPSIS +-------- + +:program:`llvm-nm` [*options*] [*filenames...*] + +DESCRIPTION +----------- + +The :program:`llvm-nm` utility lists the names of symbols from the LLVM bitcode +files, object files, or :program:`ar` archives containing them, named on the +command line. Each symbol is listed along with some simple information about +its provenance. If no file name is specified, or *-* is used as a file name, +:program:`llvm-nm` will process a file on its standard input stream. + +:program:`llvm-nm`'s default output format is the traditional BSD :program:`nm` +output format. Each such output record consists of an (optional) 8-digit +hexadecimal address, followed by a type code character, followed by a name, for +each symbol. One record is printed per line; fields are separated by spaces. +When the address is omitted, it is replaced by 8 spaces. + +Type code characters currently supported, and their meanings, are as follows: + +U + + Named object is referenced but undefined in this bitcode file + +C + + Common (multiple definitions link together into one def) + +W + + Weak reference (multiple definitions link together into zero or one definitions) + +t + + Local function (text) object + +T + + Global function (text) object + +d + + Local data object + +D + + Global data object + +? + + Something unrecognizable + +Because LLVM bitcode files typically contain objects that are not considered to +have addresses until they are linked into an executable image or dynamically +compiled "just-in-time", :program:`llvm-nm` does not print an address for any +symbol in an LLVM bitcode file, even symbols which are defined in the bitcode +file. + +OPTIONS +------- + +.. program:: llvm-nm + +.. option:: -B (default) + + Use BSD output format. Alias for :option:`--format=bsd`. + +.. option:: -P + + Use POSIX.2 output format. Alias for :option:`--format=posix`. + +.. option:: --debug-syms, -a + + Show all symbols, even debugger only. + +.. option:: --defined-only + + Print only symbols defined in this file (as opposed to + symbols which may be referenced by objects in this file, but not + defined in this file.) + +.. option:: --dynamic, -D + + Display dynamic symbols instead of normal symbols. + +.. option:: --extern-only, -g + + Print only symbols whose definitions are external; that is, accessible + from other files. + +.. option:: --format=format, -f format + + Select an output format; *format* may be *sysv*, *posix*, or *bsd*. The default + is *bsd*. + +.. option:: -help + + Print a summary of command-line options and their meanings. + +.. option:: --no-sort, -p + + Shows symbols in order encountered. + +.. option:: --numeric-sort, -n, -v + + Sort symbols by address. + +.. option:: --print-file-name, -A, -o + + Precede each symbol with the file it came from. + +.. option:: --print-size, -S + + Show symbol size instead of address. + +.. option:: --size-sort + + Sort symbols by size. + +.. option:: --undefined-only, -u + + Print only symbols referenced but not defined in this file. + +BUGS +---- + + * :program:`llvm-nm` cannot demangle C++ mangled names, like GNU :program:`nm` + can. + + * :program:`llvm-nm` does not support the full set of arguments that GNU + :program:`nm` does. + +EXIT STATUS +----------- + +:program:`llvm-nm` exits with an exit code of zero. + +SEE ALSO +-------- + +llvm-dis, ar(1), nm(1) diff --git a/docs/CommandGuide/llvm-prof.rst b/docs/CommandGuide/llvm-prof.rst new file mode 100644 index 00000000..e8d0b19c --- /dev/null +++ b/docs/CommandGuide/llvm-prof.rst @@ -0,0 +1,63 @@ +llvm-prof - print execution profile of LLVM program +=================================================== + + +SYNOPSIS +-------- + + +**llvm-prof** [*options*] [*bitcode file*] [*llvmprof.out*] + + +DESCRIPTION +----------- + + +The **llvm-prof** tool reads in an *llvmprof.out* file (which can +optionally use a specific file with the third program argument), a bitcode file +for the program, and produces a human readable report, suitable for determining +where the program hotspots are. + +This program is often used in conjunction with the *utils/profile.pl* +script. This script automatically instruments a program, runs it with the JIT, +then runs **llvm-prof** to format a report. To get more information about +*utils/profile.pl*, execute it with the **-help** option. + + +OPTIONS +------- + + + +**--annotated-llvm** or **-A** + + In addition to the normal report printed, print out the code for the + program, annotated with execution frequency information. This can be + particularly useful when trying to visualize how frequently basic blocks + are executed. This is most useful with basic block profiling + information or better. + + + +**--print-all-code** + + Using this option enables the **--annotated-llvm** option, but it + prints the entire module, instead of just the most commonly executed + functions. + + + +**--time-passes** + + Record the amount of time needed for each pass and print it to standard + error. + + + + +EXIT STATUS +----------- + + +**llvm-prof** returns 1 if it cannot load the bitcode file or the profile +information. Otherwise, it exits with zero. diff --git a/docs/CommandGuide/llvm-readobj.rst b/docs/CommandGuide/llvm-readobj.rst new file mode 100644 index 00000000..b1918b54 --- /dev/null +++ b/docs/CommandGuide/llvm-readobj.rst @@ -0,0 +1,86 @@ +llvm-readobj - LLVM Object Reader +================================= + +SYNOPSIS +-------- + +:program:`llvm-readobj` [*options*] [*input...*] + +DESCRIPTION +----------- + +The :program:`llvm-readobj` tool displays low-level format-specific information +about one or more object files. The tool and its output is primarily designed +for use in FileCheck-based tests. + +OPTIONS +------- + +If ``input`` is "``-``" or omitted, :program:`llvm-readobj` reads from standard +input. Otherwise, it will read from the specified ``filenames``. + +.. option:: -help + + Print a summary of command line options. + +.. option:: -version + + Display the version of this program + +.. option:: -file-headers, -h + + Display file headers. + +.. option:: -sections, -s + + Display all sections. + +.. option:: -section-data, -sd + + When used with ``-sections``, display section data for each section shown. + +.. option:: -section-relocations, -sr + + When used with ``-sections``, display relocations for each section shown. + +.. option:: -section-symbols, -st + + When used with ``-sections``, display symbols for each section shown. + +.. option:: -relocations, -r + + Display the relocation entries in the file. + +.. option:: -symbols, -t + + Display the symbol table. + +.. option:: -dyn-symbols + + Display the dynamic symbol table (only for ELF object files). + +.. option:: -unwind, -u + + Display unwind information. + +.. option:: -expand-relocs + + When used with ``-relocations``, display each relocation in an expanded + multi-line format. + +.. option:: -dynamic-table + + Display the ELF .dynamic section table (only for ELF object files). + +.. option:: -needed-libs + + Display the needed libraries (only for ELF object files). + +.. option:: -program-headers + + Display the ELF program headers (only for ELF object files). + +EXIT STATUS +----------- + +:program:`llvm-readobj` returns 0. diff --git a/docs/CommandGuide/llvm-stress.rst b/docs/CommandGuide/llvm-stress.rst new file mode 100644 index 00000000..fb006f56 --- /dev/null +++ b/docs/CommandGuide/llvm-stress.rst @@ -0,0 +1,34 @@ +llvm-stress - generate random .ll files +======================================= + +SYNOPSIS +-------- + +:program:`llvm-stress` [-size=filesize] [-seed=initialseed] [-o=outfile] + +DESCRIPTION +----------- + +The :program:`llvm-stress` tool is used to generate random ``.ll`` files that +can be used to test different components of LLVM. + +OPTIONS +------- + +.. option:: -o filename + + Specify the output filename. + +.. option:: -size size + + Specify the size of the generated ``.ll`` file. + +.. option:: -seed seed + + Specify the seed to be used for the randomly generated instructions. + +EXIT STATUS +----------- + +:program:`llvm-stress` returns 0. + diff --git a/docs/CommandGuide/llvm-symbolizer.rst b/docs/CommandGuide/llvm-symbolizer.rst new file mode 100644 index 00000000..e03be9b1 --- /dev/null +++ b/docs/CommandGuide/llvm-symbolizer.rst @@ -0,0 +1,81 @@ +llvm-symbolizer - convert addresses into source code locations +============================================================== + +SYNOPSIS +-------- + +:program:`llvm-symbolizer` [options] + +DESCRIPTION +----------- + +:program:`llvm-symbolizer` reads object file names and addresses from standard +input and prints corresponding source code locations to standard output. This +program uses debug info sections and symbol table in the object files. + +EXAMPLE +-------- + +.. code-block:: console + + $ cat addr.txt + a.out 0x4004f4 + /tmp/b.out 0x400528 + /tmp/c.so 0x710 + /tmp/mach_universal_binary:i386 0x1f84 + /tmp/mach_universal_binary:x86_64 0x100000f24 + $ llvm-symbolizer < addr.txt + main + /tmp/a.cc:4 + + f(int, int) + /tmp/b.cc:11 + + h_inlined_into_g + /tmp/header.h:2 + g_inlined_into_f + /tmp/header.h:7 + f_inlined_into_main + /tmp/source.cc:3 + main + /tmp/source.cc:8 + + _main + /tmp/source_i386.cc:8 + + _main + /tmp/source_x86_64.cc:8 + +OPTIONS +------- + +.. option:: -functions + + Print function names as well as source file/line locations. Defaults to true. + +.. option:: -use-symbol-table + + Prefer function names stored in symbol table to function names + in debug info sections. Defaults to true. + +.. option:: -demangle + + Print demangled function names. Defaults to true. + +.. option:: -inlining + + If a source code location is in an inlined function, prints all the + inlnied frames. Defaults to true. + +.. option:: -default-arch + + If a binary contains object files for multiple architectures (e.g. it is a + Mach-O universal binary), symbolize the object file for a given architecture. + You can also specify architecture by writing ``binary_name:arch_name`` in the + input (see example above). If architecture is not specified in either way, + address will not be symbolized. Defaults to empty string. + +EXIT STATUS +----------- + +:program:`llvm-symbolizer` returns 0. Other exit codes imply internal program error. diff --git a/docs/CommandGuide/opt.rst b/docs/CommandGuide/opt.rst new file mode 100644 index 00000000..179c297c --- /dev/null +++ b/docs/CommandGuide/opt.rst @@ -0,0 +1,143 @@ +opt - LLVM optimizer +==================== + +SYNOPSIS +-------- + +:program:`opt` [*options*] [*filename*] + +DESCRIPTION +----------- + +The :program:`opt` command is the modular LLVM optimizer and analyzer. It +takes LLVM source files as input, runs the specified optimizations or analyses +on it, and then outputs the optimized file or the analysis results. The +function of :program:`opt` depends on whether the :option:`-analyze` option is +given. + +When :option:`-analyze` is specified, :program:`opt` performs various analyses +of the input source. It will usually print the results on standard output, but +in a few cases, it will print output to standard error or generate a file with +the analysis output, which is usually done when the output is meant for another +program. + +While :option:`-analyze` is *not* given, :program:`opt` attempts to produce an +optimized output file. The optimizations available via :program:`opt` depend +upon what libraries were linked into it as well as any additional libraries +that have been loaded with the :option:`-load` option. Use the :option:`-help` +option to determine what optimizations you can use. + +If ``filename`` is omitted from the command line or is "``-``", :program:`opt` +reads its input from standard input. Inputs can be in either the LLVM assembly +language format (``.ll``) or the LLVM bitcode format (``.bc``). + +If an output filename is not specified with the :option:`-o` option, +:program:`opt` writes its output to the standard output. + +OPTIONS +------- + +.. option:: -f + + Enable binary output on terminals. Normally, :program:`opt` will refuse to + write raw bitcode output if the output stream is a terminal. With this option, + :program:`opt` will write raw bitcode regardless of the output device. + +.. option:: -help + + Print a summary of command line options. + +.. option:: -o + + Specify the output filename. + +.. option:: -S + + Write output in LLVM intermediate language (instead of bitcode). + +.. option:: -{passname} + + :program:`opt` provides the ability to run any of LLVM's optimization or + analysis passes in any order. The :option:`-help` option lists all the passes + available. The order in which the options occur on the command line are the + order in which they are executed (within pass constraints). + +.. option:: -std-compile-opts + + This is short hand for a standard list of *compile time optimization* passes. + This is typically used to optimize the output from the llvm-gcc front end. It + might be useful for other front end compilers as well. To discover the full + set of options available, use the following command: + + .. code-block:: sh + + llvm-as < /dev/null | opt -std-compile-opts -disable-output -debug-pass=Arguments + +.. option:: -disable-inlining + + This option is only meaningful when :option:`-std-compile-opts` is given. It + simply removes the inlining pass from the standard list. + +.. option:: -disable-opt + + This option is only meaningful when :option:`-std-compile-opts` is given. It + disables most, but not all, of the :option:`-std-compile-opts`. The ones that + remain are :option:`-verify`, :option:`-lower-setjmp`, and + :option:`-funcresolve`. + +.. option:: -strip-debug + + This option causes opt to strip debug information from the module before + applying other optimizations. It is essentially the same as :option:`-strip` + but it ensures that stripping of debug information is done first. + +.. option:: -verify-each + + This option causes opt to add a verify pass after every pass otherwise + specified on the command line (including :option:`-verify`). This is useful + for cases where it is suspected that a pass is creating an invalid module but + it is not clear which pass is doing it. The combination of + :option:`-std-compile-opts` and :option:`-verify-each` can quickly track down + this kind of problem. + +.. option:: -profile-info-file + + Specify the name of the file loaded by the ``-profile-loader`` option. + +.. option:: -stats + + Print statistics. + +.. option:: -time-passes + + Record the amount of time needed for each pass and print it to standard + error. + +.. option:: -debug + + If this is a debug build, this option will enable debug printouts from passes + which use the ``DEBUG()`` macro. See the `LLVM Programmer's Manual + <../ProgrammersManual.html>`_, section ``#DEBUG`` for more information. + +.. option:: -load= + + Load the dynamic object ``plugin``. This object should register new + optimization or analysis passes. Once loaded, the object will add new command + line options to enable various optimizations or analyses. To see the new + complete list of optimizations, use the :option:`-help` and :option:`-load` + options together. For example: + + .. code-block:: sh + + opt -load=plugin.so -help + +.. option:: -p + + Print module after each transformation. + +EXIT STATUS +----------- + +If :program:`opt` succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. + diff --git a/docs/CommandGuide/tblgen.rst b/docs/CommandGuide/tblgen.rst new file mode 100644 index 00000000..1c468283 --- /dev/null +++ b/docs/CommandGuide/tblgen.rst @@ -0,0 +1,131 @@ +tblgen - Target Description To C++ Code Generator +================================================= + +SYNOPSIS +-------- + +:program:`tblgen` [*options*] [*filename*] + +DESCRIPTION +----------- + +:program:`tblgen` translates from target description (``.td``) files into C++ +code that can be included in the definition of an LLVM target library. Most +users of LLVM will not need to use this program. It is only for assisting with +writing an LLVM target backend. + +The input and output of :program:`tblgen` is beyond the scope of this short +introduction. Please see :doc:`../TableGenFundamentals`. + +The *filename* argument specifies the name of a Target Description (``.td``) +file to read as input. + +OPTIONS +------- + +.. program:: tblgen + +.. option:: -help + + Print a summary of command line options. + +.. option:: -o filename + + Specify the output file name. If ``filename`` is ``-``, then + :program:`tblgen` sends its output to standard output. + +.. option:: -I directory + + Specify where to find other target description files for inclusion. The + ``directory`` value should be a full or partial path to a directory that + contains target description files. + +.. option:: -asmparsernum N + + Make -gen-asm-parser emit assembly writer number ``N``. + +.. option:: -asmwriternum N + + Make -gen-asm-writer emit assembly writer number ``N``. + +.. option:: -class className + + Print the enumeration list for this class. + +.. option:: -print-records + + Print all records to standard output (default). + +.. option:: -print-enums + + Print enumeration values for a class. + +.. option:: -print-sets + + Print expanded sets for testing DAG exprs. + +.. option:: -gen-emitter + + Generate machine code emitter. + +.. option:: -gen-register-info + + Generate registers and register classes info. + +.. option:: -gen-instr-info + + Generate instruction descriptions. + +.. option:: -gen-asm-writer + + Generate the assembly writer. + +.. option:: -gen-disassembler + + Generate disassembler. + +.. option:: -gen-pseudo-lowering + + Generate pseudo instruction lowering. + +.. option:: -gen-dag-isel + + Generate a DAG (Directed Acycle Graph) instruction selector. + +.. option:: -gen-asm-matcher + + Generate assembly instruction matcher. + +.. option:: -gen-dfa-packetizer + + Generate DFA Packetizer for VLIW targets. + +.. option:: -gen-fast-isel + + Generate a "fast" instruction selector. + +.. option:: -gen-subtarget + + Generate subtarget enumerations. + +.. option:: -gen-intrinsic + + Generate intrinsic information. + +.. option:: -gen-tgt-intrinsic + + Generate target intrinsic information. + +.. option:: -gen-enhanced-disassembly-info + + Generate enhanced disassembly info. + +.. option:: -version + + Show the version number of this program. + +EXIT STATUS +----------- + +If :program:`tblgen` succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. diff --git a/docs/CommandLine.rst b/docs/CommandLine.rst new file mode 100644 index 00000000..4c84d232 --- /dev/null +++ b/docs/CommandLine.rst @@ -0,0 +1,1743 @@ +============================== +CommandLine 2.0 Library Manual +============================== + +.. contents:: + :local: + +Introduction +============ + +This document describes the CommandLine argument processing library. It will +show you how to use it, and what it can do. The CommandLine library uses a +declarative approach to specifying the command line options that your program +takes. By default, these options declarations implicitly hold the value parsed +for the option declared (of course this `can be changed`_). + +Although there are a **lot** of command line argument parsing libraries out +there in many different languages, none of them fit well with what I needed. By +looking at the features and problems of other libraries, I designed the +CommandLine library to have the following features: + +#. Speed: The CommandLine library is very quick and uses little resources. The + parsing time of the library is directly proportional to the number of + arguments parsed, not the number of options recognized. Additionally, + command line argument values are captured transparently into user defined + global variables, which can be accessed like any other variable (and with the + same performance). + +#. Type Safe: As a user of CommandLine, you don't have to worry about + remembering the type of arguments that you want (is it an int? a string? a + bool? an enum?) and keep casting it around. Not only does this help prevent + error prone constructs, it also leads to dramatically cleaner source code. + +#. No subclasses required: To use CommandLine, you instantiate variables that + correspond to the arguments that you would like to capture, you don't + subclass a parser. This means that you don't have to write **any** + boilerplate code. + +#. Globally accessible: Libraries can specify command line arguments that are + automatically enabled in any tool that links to the library. This is + possible because the application doesn't have to keep a list of arguments to + pass to the parser. This also makes supporting `dynamically loaded options`_ + trivial. + +#. Cleaner: CommandLine supports enum and other types directly, meaning that + there is less error and more security built into the library. You don't have + to worry about whether your integral command line argument accidentally got + assigned a value that is not valid for your enum type. + +#. Powerful: The CommandLine library supports many different types of arguments, + from simple `boolean flags`_ to `scalars arguments`_ (`strings`_, + `integers`_, `enums`_, `doubles`_), to `lists of arguments`_. This is + possible because CommandLine is... + +#. Extensible: It is very simple to add a new argument type to CommandLine. + Simply specify the parser that you want to use with the command line option + when you declare it. `Custom parsers`_ are no problem. + +#. Labor Saving: The CommandLine library cuts down on the amount of grunt work + that you, the user, have to do. For example, it automatically provides a + ``-help`` option that shows the available command line options for your tool. + Additionally, it does most of the basic correctness checking for you. + +#. Capable: The CommandLine library can handle lots of different forms of + options often found in real programs. For example, `positional`_ arguments, + ``ls`` style `grouping`_ options (to allow processing '``ls -lad``' + naturally), ``ld`` style `prefix`_ options (to parse '``-lmalloc + -L/usr/lib``'), and interpreter style options. + +This document will hopefully let you jump in and start using CommandLine in your +utility quickly and painlessly. Additionally it should be a simple reference +manual to figure out how stuff works. + +Quick Start Guide +================= + +This section of the manual runs through a simple CommandLine'ification of a +basic compiler tool. This is intended to show you how to jump into using the +CommandLine library in your own program, and show you some of the cool things it +can do. + +To start out, you need to include the CommandLine header file into your program: + +.. code-block:: c++ + + #include "llvm/Support/CommandLine.h" + +Additionally, you need to add this as the first line of your main program: + +.. code-block:: c++ + + int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv); + ... + } + +... which actually parses the arguments and fills in the variable declarations. + +Now that you are ready to support command line arguments, we need to tell the +system which ones we want, and what type of arguments they are. The CommandLine +library uses a declarative syntax to model command line arguments with the +global variable declarations that capture the parsed values. This means that +for every command line option that you would like to support, there should be a +global variable declaration to capture the result. For example, in a compiler, +we would like to support the Unix-standard '``-o ``' option to specify +where to put the output. With the CommandLine library, this is represented like +this: + +.. _scalars arguments: +.. _here: + +.. code-block:: c++ + + cl::opt OutputFilename("o", cl::desc("Specify output filename"), cl::value_desc("filename")); + +This declares a global variable "``OutputFilename``" that is used to capture the +result of the "``o``" argument (first parameter). We specify that this is a +simple scalar option by using the "``cl::opt``" template (as opposed to the +"``cl::list``" template), and tell the CommandLine library that the data +type that we are parsing is a string. + +The second and third parameters (which are optional) are used to specify what to +output for the "``-help``" option. In this case, we get a line that looks like +this: + +:: + + USAGE: compiler [options] + + OPTIONS: + -help - display available options (-help-hidden for more) + -o - Specify output filename + +Because we specified that the command line option should parse using the +``string`` data type, the variable declared is automatically usable as a real +string in all contexts that a normal C++ string object may be used. For +example: + +.. code-block:: c++ + + ... + std::ofstream Output(OutputFilename.c_str()); + if (Output.good()) ... + ... + +There are many different options that you can use to customize the command line +option handling library, but the above example shows the general interface to +these options. The options can be specified in any order, and are specified +with helper functions like `cl::desc(...)`_, so there are no positional +dependencies to remember. The available options are discussed in detail in the +`Reference Guide`_. + +Continuing the example, we would like to have our compiler take an input +filename as well as an output filename, but we do not want the input filename to +be specified with a hyphen (ie, not ``-filename.c``). To support this style of +argument, the CommandLine library allows for `positional`_ arguments to be +specified for the program. These positional arguments are filled with command +line parameters that are not in option form. We use this feature like this: + +.. code-block:: c++ + + + cl::opt InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +This declaration indicates that the first positional argument should be treated +as the input filename. Here we use the `cl::init`_ option to specify an initial +value for the command line option, which is used if the option is not specified +(if you do not specify a `cl::init`_ modifier for an option, then the default +constructor for the data type is used to initialize the value). Command line +options default to being optional, so if we would like to require that the user +always specify an input filename, we would add the `cl::Required`_ flag, and we +could eliminate the `cl::init`_ modifier, like this: + +.. code-block:: c++ + + cl::opt InputFilename(cl::Positional, cl::desc(""), cl::Required); + +Again, the CommandLine library does not require the options to be specified in +any particular order, so the above declaration is equivalent to: + +.. code-block:: c++ + + cl::opt InputFilename(cl::Positional, cl::Required, cl::desc("")); + +By simply adding the `cl::Required`_ flag, the CommandLine library will +automatically issue an error if the argument is not specified, which shifts all +of the command line option verification code out of your application into the +library. This is just one example of how using flags can alter the default +behaviour of the library, on a per-option basis. By adding one of the +declarations above, the ``-help`` option synopsis is now extended to: + +:: + + USAGE: compiler [options] + + OPTIONS: + -help - display available options (-help-hidden for more) + -o - Specify output filename + +... indicating that an input filename is expected. + +Boolean Arguments +----------------- + +In addition to input and output filenames, we would like the compiler example to +support three boolean flags: "``-f``" to force writing binary output to a +terminal, "``--quiet``" to enable quiet mode, and "``-q``" for backwards +compatibility with some of our users. We can support these by declaring options +of boolean type like this: + +.. code-block:: c++ + + cl::opt Force ("f", cl::desc("Enable binary output on terminals")); + cl::opt Quiet ("quiet", cl::desc("Don't print informational messages")); + cl::opt Quiet2("q", cl::desc("Don't print informational messages"), cl::Hidden); + +This does what you would expect: it declares three boolean variables +("``Force``", "``Quiet``", and "``Quiet2``") to recognize these options. Note +that the "``-q``" option is specified with the "`cl::Hidden`_" flag. This +modifier prevents it from being shown by the standard "``-help``" output (note +that it is still shown in the "``-help-hidden``" output). + +The CommandLine library uses a `different parser`_ for different data types. +For example, in the string case, the argument passed to the option is copied +literally into the content of the string variable... we obviously cannot do that +in the boolean case, however, so we must use a smarter parser. In the case of +the boolean parser, it allows no options (in which case it assigns the value of +true to the variable), or it allows the values "``true``" or "``false``" to be +specified, allowing any of the following inputs: + +:: + + compiler -f # No value, 'Force' == true + compiler -f=true # Value specified, 'Force' == true + compiler -f=TRUE # Value specified, 'Force' == true + compiler -f=FALSE # Value specified, 'Force' == false + +... you get the idea. The `bool parser`_ just turns the string values into +boolean values, and rejects things like '``compiler -f=foo``'. Similarly, the +`float`_, `double`_, and `int`_ parsers work like you would expect, using the +'``strtol``' and '``strtod``' C library calls to parse the string value into the +specified data type. + +With the declarations above, "``compiler -help``" emits this: + +:: + + USAGE: compiler [options] + + OPTIONS: + -f - Enable binary output on terminals + -o - Override output filename + -quiet - Don't print informational messages + -help - display available options (-help-hidden for more) + +and "``compiler -help-hidden``" prints this: + +:: + + USAGE: compiler [options] + + OPTIONS: + -f - Enable binary output on terminals + -o - Override output filename + -q - Don't print informational messages + -quiet - Don't print informational messages + -help - display available options (-help-hidden for more) + +This brief example has shown you how to use the '`cl::opt`_' class to parse +simple scalar command line arguments. In addition to simple scalar arguments, +the CommandLine library also provides primitives to support CommandLine option +`aliases`_, and `lists`_ of options. + +.. _aliases: + +Argument Aliases +---------------- + +So far, the example works well, except for the fact that we need to check the +quiet condition like this now: + +.. code-block:: c++ + + ... + if (!Quiet && !Quiet2) printInformationalMessage(...); + ... + +... which is a real pain! Instead of defining two values for the same +condition, we can use the "`cl::alias`_" class to make the "``-q``" option an +**alias** for the "``-quiet``" option, instead of providing a value itself: + +.. code-block:: c++ + + cl::opt Force ("f", cl::desc("Overwrite output files")); + cl::opt Quiet ("quiet", cl::desc("Don't print informational messages")); + cl::alias QuietA("q", cl::desc("Alias for -quiet"), cl::aliasopt(Quiet)); + +The third line (which is the only one we modified from above) defines a "``-q``" +alias that updates the "``Quiet``" variable (as specified by the `cl::aliasopt`_ +modifier) whenever it is specified. Because aliases do not hold state, the only +thing the program has to query is the ``Quiet`` variable now. Another nice +feature of aliases is that they automatically hide themselves from the ``-help`` +output (although, again, they are still visible in the ``-help-hidden output``). + +Now the application code can simply use: + +.. code-block:: c++ + + ... + if (!Quiet) printInformationalMessage(...); + ... + +... which is much nicer! The "`cl::alias`_" can be used to specify an +alternative name for any variable type, and has many uses. + +.. _unnamed alternatives using the generic parser: + +Selecting an alternative from a set of possibilities +---------------------------------------------------- + +So far we have seen how the CommandLine library handles builtin types like +``std::string``, ``bool`` and ``int``, but how does it handle things it doesn't +know about, like enums or '``int*``'s? + +The answer is that it uses a table-driven generic parser (unless you specify +your own parser, as described in the `Extension Guide`_). This parser maps +literal strings to whatever type is required, and requires you to tell it what +this mapping should be. + +Let's say that we would like to add four optimization levels to our optimizer, +using the standard flags "``-g``", "``-O0``", "``-O1``", and "``-O2``". We +could easily implement this with boolean options like above, but there are +several problems with this strategy: + +#. A user could specify more than one of the options at a time, for example, + "``compiler -O3 -O2``". The CommandLine library would not be able to catch + this erroneous input for us. + +#. We would have to test 4 different variables to see which ones are set. + +#. This doesn't map to the numeric levels that we want... so we cannot easily + see if some level >= "``-O1``" is enabled. + +To cope with these problems, we can use an enum value, and have the CommandLine +library fill it in with the appropriate level directly, which is used like this: + +.. code-block:: c++ + + enum OptLevel { + g, O1, O2, O3 + }; + + cl::opt OptimizationLevel(cl::desc("Choose optimization level:"), + cl::values( + clEnumVal(g , "No optimizations, enable debugging"), + clEnumVal(O1, "Enable trivial optimizations"), + clEnumVal(O2, "Enable default optimizations"), + clEnumVal(O3, "Enable expensive optimizations"), + clEnumValEnd)); + + ... + if (OptimizationLevel >= O2) doPartialRedundancyElimination(...); + ... + +This declaration defines a variable "``OptimizationLevel``" of the +"``OptLevel``" enum type. This variable can be assigned any of the values that +are listed in the declaration (Note that the declaration list must be terminated +with the "``clEnumValEnd``" argument!). The CommandLine library enforces that +the user can only specify one of the options, and it ensure that only valid enum +values can be specified. The "``clEnumVal``" macros ensure that the command +line arguments matched the enum values. With this option added, our help output +now is: + +:: + + USAGE: compiler [options] + + OPTIONS: + Choose optimization level: + -g - No optimizations, enable debugging + -O1 - Enable trivial optimizations + -O2 - Enable default optimizations + -O3 - Enable expensive optimizations + -f - Enable binary output on terminals + -help - display available options (-help-hidden for more) + -o - Specify output filename + -quiet - Don't print informational messages + +In this case, it is sort of awkward that flag names correspond directly to enum +names, because we probably don't want a enum definition named "``g``" in our +program. Because of this, we can alternatively write this example like this: + +.. code-block:: c++ + + enum OptLevel { + Debug, O1, O2, O3 + }; + + cl::opt OptimizationLevel(cl::desc("Choose optimization level:"), + cl::values( + clEnumValN(Debug, "g", "No optimizations, enable debugging"), + clEnumVal(O1 , "Enable trivial optimizations"), + clEnumVal(O2 , "Enable default optimizations"), + clEnumVal(O3 , "Enable expensive optimizations"), + clEnumValEnd)); + + ... + if (OptimizationLevel == Debug) outputDebugInfo(...); + ... + +By using the "``clEnumValN``" macro instead of "``clEnumVal``", we can directly +specify the name that the flag should get. In general a direct mapping is nice, +but sometimes you can't or don't want to preserve the mapping, which is when you +would use it. + +Named Alternatives +------------------ + +Another useful argument form is a named alternative style. We shall use this +style in our compiler to specify different debug levels that can be used. +Instead of each debug level being its own switch, we want to support the +following options, of which only one can be specified at a time: +"``--debug-level=none``", "``--debug-level=quick``", +"``--debug-level=detailed``". To do this, we use the exact same format as our +optimization level flags, but we also specify an option name. For this case, +the code looks like this: + +.. code-block:: c++ + + enum DebugLev { + nodebuginfo, quick, detailed + }; + + // Enable Debug Options to be specified on the command line + cl::opt DebugLevel("debug_level", cl::desc("Set the debugging level:"), + cl::values( + clEnumValN(nodebuginfo, "none", "disable debug information"), + clEnumVal(quick, "enable quick debug information"), + clEnumVal(detailed, "enable detailed debug information"), + clEnumValEnd)); + +This definition defines an enumerated command line variable of type "``enum +DebugLev``", which works exactly the same way as before. The difference here is +just the interface exposed to the user of your program and the help output by +the "``-help``" option: + +:: + + USAGE: compiler [options] + + OPTIONS: + Choose optimization level: + -g - No optimizations, enable debugging + -O1 - Enable trivial optimizations + -O2 - Enable default optimizations + -O3 - Enable expensive optimizations + -debug_level - Set the debugging level: + =none - disable debug information + =quick - enable quick debug information + =detailed - enable detailed debug information + -f - Enable binary output on terminals + -help - display available options (-help-hidden for more) + -o - Specify output filename + -quiet - Don't print informational messages + +Again, the only structural difference between the debug level declaration and +the optimization level declaration is that the debug level declaration includes +an option name (``"debug_level"``), which automatically changes how the library +processes the argument. The CommandLine library supports both forms so that you +can choose the form most appropriate for your application. + +.. _lists: + +Parsing a list of options +------------------------- + +Now that we have the standard run-of-the-mill argument types out of the way, +lets get a little wild and crazy. Lets say that we want our optimizer to accept +a **list** of optimizations to perform, allowing duplicates. For example, we +might want to run: "``compiler -dce -constprop -inline -dce -strip``". In this +case, the order of the arguments and the number of appearances is very +important. This is what the "``cl::list``" template is for. First, start by +defining an enum of the optimizations that you would like to perform: + +.. code-block:: c++ + + enum Opts { + // 'inline' is a C++ keyword, so name it 'inlining' + dce, constprop, inlining, strip + }; + +Then define your "``cl::list``" variable: + +.. code-block:: c++ + + cl::list OptimizationList(cl::desc("Available Optimizations:"), + cl::values( + clEnumVal(dce , "Dead Code Elimination"), + clEnumVal(constprop , "Constant Propagation"), + clEnumValN(inlining, "inline", "Procedure Integration"), + clEnumVal(strip , "Strip Symbols"), + clEnumValEnd)); + +This defines a variable that is conceptually of the type +"``std::vector``". Thus, you can access it with standard vector +methods: + +.. code-block:: c++ + + for (unsigned i = 0; i != OptimizationList.size(); ++i) + switch (OptimizationList[i]) + ... + +... to iterate through the list of options specified. + +Note that the "``cl::list``" template is completely general and may be used with +any data types or other arguments that you can use with the "``cl::opt``" +template. One especially useful way to use a list is to capture all of the +positional arguments together if there may be more than one specified. In the +case of a linker, for example, the linker takes several '``.o``' files, and +needs to capture them into a list. This is naturally specified as: + +.. code-block:: c++ + + ... + cl::list InputFilenames(cl::Positional, cl::desc(""), cl::OneOrMore); + ... + +This variable works just like a "``vector``" object. As such, accessing +the list is simple, just like above. In this example, we used the +`cl::OneOrMore`_ modifier to inform the CommandLine library that it is an error +if the user does not specify any ``.o`` files on our command line. Again, this +just reduces the amount of checking we have to do. + +Collecting options as a set of flags +------------------------------------ + +Instead of collecting sets of options in a list, it is also possible to gather +information for enum values in a **bit vector**. The representation used by the +`cl::bits`_ class is an ``unsigned`` integer. An enum value is represented by a +0/1 in the enum's ordinal value bit position. 1 indicating that the enum was +specified, 0 otherwise. As each specified value is parsed, the resulting enum's +bit is set in the option's bit vector: + +.. code-block:: c++ + + bits |= 1 << (unsigned)enum; + +Options that are specified multiple times are redundant. Any instances after +the first are discarded. + +Reworking the above list example, we could replace `cl::list`_ with `cl::bits`_: + +.. code-block:: c++ + + cl::bits OptimizationBits(cl::desc("Available Optimizations:"), + cl::values( + clEnumVal(dce , "Dead Code Elimination"), + clEnumVal(constprop , "Constant Propagation"), + clEnumValN(inlining, "inline", "Procedure Integration"), + clEnumVal(strip , "Strip Symbols"), + clEnumValEnd)); + +To test to see if ``constprop`` was specified, we can use the ``cl:bits::isSet`` +function: + +.. code-block:: c++ + + if (OptimizationBits.isSet(constprop)) { + ... + } + +It's also possible to get the raw bit vector using the ``cl::bits::getBits`` +function: + +.. code-block:: c++ + + unsigned bits = OptimizationBits.getBits(); + +Finally, if external storage is used, then the location specified must be of +**type** ``unsigned``. In all other ways a `cl::bits`_ option is equivalent to a +`cl::list`_ option. + +.. _additional extra text: + +Adding freeform text to help output +----------------------------------- + +As our program grows and becomes more mature, we may decide to put summary +information about what it does into the help output. The help output is styled +to look similar to a Unix ``man`` page, providing concise information about a +program. Unix ``man`` pages, however often have a description about what the +program does. To add this to your CommandLine program, simply pass a third +argument to the `cl::ParseCommandLineOptions`_ call in main. This additional +argument is then printed as the overview information for your program, allowing +you to include any additional information that you want. For example: + +.. code-block:: c++ + + int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv, " CommandLine compiler example\n\n" + " This program blah blah blah...\n"); + ... + } + +would yield the help output: + +:: + + **OVERVIEW: CommandLine compiler example + + This program blah blah blah...** + + USAGE: compiler [options] + + OPTIONS: + ... + -help - display available options (-help-hidden for more) + -o - Specify output filename + +.. _grouping options into categories: + +Grouping options into categories +-------------------------------- + +If our program has a large number of options it may become difficult for users +of our tool to navigate the output of ``-help``. To alleviate this problem we +can put our options into categories. This can be done by declaring option +categories (`cl::OptionCategory`_ objects) and then placing our options into +these categories using the `cl::cat`_ option attribute. For example: + +.. code-block:: c++ + + cl::OptionCategory StageSelectionCat("Stage Selection Options", + "These control which stages are run."); + + cl::opt Preprocessor("E",cl::desc("Run preprocessor stage."), + cl::cat(StageSelectionCat)); + + cl::opt NoLink("c",cl::desc("Run all stages except linking."), + cl::cat(StageSelectionCat)); + +The output of ``-help`` will become categorized if an option category is +declared. The output looks something like :: + + OVERVIEW: This is a small program to demo the LLVM CommandLine API + USAGE: Sample [options] + + OPTIONS: + + General options: + + -help - Display available options (-help-hidden for more) + -help-list - Display list of available options (-help-list-hidden for more) + + + Stage Selection Options: + These control which stages are run. + + -E - Run preprocessor stage. + -c - Run all stages except linking. + +In addition to the behaviour of ``-help`` changing when an option category is +declared, the command line option ``-help-list`` becomes visible which will +print the command line options as uncategorized list. + +Note that Options that are not explicitly categorized will be placed in the +``cl::GeneralCategory`` category. + +.. _Reference Guide: + +Reference Guide +=============== + +Now that you know the basics of how to use the CommandLine library, this section +will give you the detailed information you need to tune how command line options +work, as well as information on more "advanced" command line option processing +capabilities. + +.. _positional: +.. _positional argument: +.. _Positional Arguments: +.. _Positional arguments section: +.. _positional options: + +Positional Arguments +-------------------- + +Positional arguments are those arguments that are not named, and are not +specified with a hyphen. Positional arguments should be used when an option is +specified by its position alone. For example, the standard Unix ``grep`` tool +takes a regular expression argument, and an optional filename to search through +(which defaults to standard input if a filename is not specified). Using the +CommandLine library, this would be specified as: + +.. code-block:: c++ + + cl::opt Regex (cl::Positional, cl::desc(""), cl::Required); + cl::opt Filename(cl::Positional, cl::desc(""), cl::init("-")); + +Given these two option declarations, the ``-help`` output for our grep +replacement would look like this: + +:: + + USAGE: spiffygrep [options] + + OPTIONS: + -help - display available options (-help-hidden for more) + +... and the resultant program could be used just like the standard ``grep`` +tool. + +Positional arguments are sorted by their order of construction. This means that +command line options will be ordered according to how they are listed in a .cpp +file, but will not have an ordering defined if the positional arguments are +defined in multiple .cpp files. The fix for this problem is simply to define +all of your positional arguments in one .cpp file. + +Specifying positional options with hyphens +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes you may want to specify a value to your positional argument that +starts with a hyphen (for example, searching for '``-foo``' in a file). At +first, you will have trouble doing this, because it will try to find an argument +named '``-foo``', and will fail (and single quotes will not save you). Note +that the system ``grep`` has the same problem: + +:: + + $ spiffygrep '-foo' test.txt + Unknown command line argument '-foo'. Try: spiffygrep -help' + + $ grep '-foo' test.txt + grep: illegal option -- f + grep: illegal option -- o + grep: illegal option -- o + Usage: grep -hblcnsviw pattern file . . . + +The solution for this problem is the same for both your tool and the system +version: use the '``--``' marker. When the user specifies '``--``' on the +command line, it is telling the program that all options after the '``--``' +should be treated as positional arguments, not options. Thus, we can use it +like this: + +:: + + $ spiffygrep -- -foo test.txt + ...output... + +Determining absolute position with getPosition() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes an option can affect or modify the meaning of another option. For +example, consider ``gcc``'s ``-x LANG`` option. This tells ``gcc`` to ignore the +suffix of subsequent positional arguments and force the file to be interpreted +as if it contained source code in language ``LANG``. In order to handle this +properly, you need to know the absolute position of each argument, especially +those in lists, so their interaction(s) can be applied correctly. This is also +useful for options like ``-llibname`` which is actually a positional argument +that starts with a dash. + +So, generally, the problem is that you have two ``cl::list`` variables that +interact in some way. To ensure the correct interaction, you can use the +``cl::list::getPosition(optnum)`` method. This method returns the absolute +position (as found on the command line) of the ``optnum`` item in the +``cl::list``. + +The idiom for usage is like this: + +.. code-block:: c++ + + static cl::list Files(cl::Positional, cl::OneOrMore); + static cl::list Libraries("l", cl::ZeroOrMore); + + int main(int argc, char**argv) { + // ... + std::vector::iterator fileIt = Files.begin(); + std::vector::iterator libIt = Libraries.begin(); + unsigned libPos = 0, filePos = 0; + while ( 1 ) { + if ( libIt != Libraries.end() ) + libPos = Libraries.getPosition( libIt - Libraries.begin() ); + else + libPos = 0; + if ( fileIt != Files.end() ) + filePos = Files.getPosition( fileIt - Files.begin() ); + else + filePos = 0; + + if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) { + // Source File Is next + ++fileIt; + } + else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) { + // Library is next + ++libIt; + } + else + break; // we're done with the list + } + } + +Note that, for compatibility reasons, the ``cl::opt`` also supports an +``unsigned getPosition()`` option that will provide the absolute position of +that option. You can apply the same approach as above with a ``cl::opt`` and a +``cl::list`` option as you can with two lists. + +.. _interpreter style options: +.. _cl::ConsumeAfter: +.. _this section for more information: + +The ``cl::ConsumeAfter`` modifier +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::ConsumeAfter`` `formatting option`_ is used to construct programs that +use "interpreter style" option processing. With this style of option +processing, all arguments specified after the last positional argument are +treated as special interpreter arguments that are not interpreted by the command +line argument. + +As a concrete example, lets say we are developing a replacement for the standard +Unix Bourne shell (``/bin/sh``). To run ``/bin/sh``, first you specify options +to the shell itself (like ``-x`` which turns on trace output), then you specify +the name of the script to run, then you specify arguments to the script. These +arguments to the script are parsed by the Bourne shell command line option +processor, but are not interpreted as options to the shell itself. Using the +CommandLine library, we would specify this as: + +.. code-block:: c++ + + cl::opt Script(cl::Positional, cl::desc(""), cl::init("-")); + cl::list Argv(cl::ConsumeAfter, cl::desc("...")); + cl::opt Trace("x", cl::desc("Enable trace output")); + +which automatically provides the help output: + +:: + + USAGE: spiffysh [options] ... + + OPTIONS: + -help - display available options (-help-hidden for more) + -x - Enable trace output + +At runtime, if we run our new shell replacement as ```spiffysh -x test.sh -a -x +-y bar``', the ``Trace`` variable will be set to true, the ``Script`` variable +will be set to "``test.sh``", and the ``Argv`` list will contain ``["-a", "-x", +"-y", "bar"]``, because they were specified after the last positional argument +(which is the script name). + +There are several limitations to when ``cl::ConsumeAfter`` options can be +specified. For example, only one ``cl::ConsumeAfter`` can be specified per +program, there must be at least one `positional argument`_ specified, there must +not be any `cl::list`_ positional arguments, and the ``cl::ConsumeAfter`` option +should be a `cl::list`_ option. + +.. _can be changed: +.. _Internal vs External Storage: + +Internal vs External Storage +---------------------------- + +By default, all command line options automatically hold the value that they +parse from the command line. This is very convenient in the common case, +especially when combined with the ability to define command line options in the +files that use them. This is called the internal storage model. + +Sometimes, however, it is nice to separate the command line option processing +code from the storage of the value parsed. For example, lets say that we have a +'``-debug``' option that we would like to use to enable debug information across +the entire body of our program. In this case, the boolean value controlling the +debug code should be globally accessible (in a header file, for example) yet the +command line option processing code should not be exposed to all of these +clients (requiring lots of .cpp files to ``#include CommandLine.h``). + +To do this, set up your .h file with your option, like this for example: + +.. code-block:: c++ + + // DebugFlag.h - Get access to the '-debug' command line option + // + + // DebugFlag - This boolean is set to true if the '-debug' command line option + // is specified. This should probably not be referenced directly, instead, use + // the DEBUG macro below. + // + extern bool DebugFlag; + + // DEBUG macro - This macro should be used by code to emit debug information. + // In the '-debug' option is specified on the command line, and if this is a + // debug build, then the code specified as the option to the macro will be + // executed. Otherwise it will not be. + #ifdef NDEBUG + #define DEBUG(X) + #else + #define DEBUG(X) do { if (DebugFlag) { X; } } while (0) + #endif + +This allows clients to blissfully use the ``DEBUG()`` macro, or the +``DebugFlag`` explicitly if they want to. Now we just need to be able to set +the ``DebugFlag`` boolean when the option is set. To do this, we pass an +additional argument to our command line argument processor, and we specify where +to fill in with the `cl::location`_ attribute: + +.. code-block:: c++ + + bool DebugFlag; // the actual value + static cl::opt // The parser + Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::location(DebugFlag)); + +In the above example, we specify "``true``" as the second argument to the +`cl::opt`_ template, indicating that the template should not maintain a copy of +the value itself. In addition to this, we specify the `cl::location`_ +attribute, so that ``DebugFlag`` is automatically set. + +Option Attributes +----------------- + +This section describes the basic attributes that you can specify on options. + +* The option name attribute (which is required for all options, except + `positional options`_) specifies what the option name is. This option is + specified in simple double quotes: + + .. code-block:: c++ + + cl::opt Quiet("quiet"); + +.. _cl::desc(...): + +* The **cl::desc** attribute specifies a description for the option to be + shown in the ``-help`` output for the program. This attribute supports + multi-line descriptions with lines separated by '\n'. + +.. _cl::value_desc: + +* The **cl::value_desc** attribute specifies a string that can be used to + fine tune the ``-help`` output for a command line option. Look `here`_ for an + example. + +.. _cl::init: + +* The **cl::init** attribute specifies an initial value for a `scalar`_ + option. If this attribute is not specified then the command line option value + defaults to the value created by the default constructor for the + type. + + .. warning:: + + If you specify both **cl::init** and **cl::location** for an option, you + must specify **cl::location** first, so that when the command-line parser + sees **cl::init**, it knows where to put the initial value. (You will get an + error at runtime if you don't put them in the right order.) + +.. _cl::location: + +* The **cl::location** attribute where to store the value for a parsed command + line option if using external storage. See the section on `Internal vs + External Storage`_ for more information. + +.. _cl::aliasopt: + +* The **cl::aliasopt** attribute specifies which option a `cl::alias`_ option is + an alias for. + +.. _cl::values: + +* The **cl::values** attribute specifies the string-to-value mapping to be used + by the generic parser. It takes a **clEnumValEnd terminated** list of + (option, value, description) triplets that specify the option name, the value + mapped to, and the description shown in the ``-help`` for the tool. Because + the generic parser is used most frequently with enum values, two macros are + often useful: + + #. The **clEnumVal** macro is used as a nice simple way to specify a triplet + for an enum. This macro automatically makes the option name be the same as + the enum name. The first option to the macro is the enum, the second is + the description for the command line option. + + #. The **clEnumValN** macro is used to specify macro options where the option + name doesn't equal the enum name. For this macro, the first argument is + the enum value, the second is the flag name, and the second is the + description. + + You will get a compile time error if you try to use cl::values with a parser + that does not support it. + +.. _cl::multi_val: + +* The **cl::multi_val** attribute specifies that this option takes has multiple + values (example: ``-sectalign segname sectname sectvalue``). This attribute + takes one unsigned argument - the number of values for the option. This + attribute is valid only on ``cl::list`` options (and will fail with compile + error if you try to use it with other option types). It is allowed to use all + of the usual modifiers on multi-valued options (besides + ``cl::ValueDisallowed``, obviously). + +.. _cl::cat: + +* The **cl::cat** attribute specifies the option category that the option + belongs to. The category should be a `cl::OptionCategory`_ object. + +Option Modifiers +---------------- + +Option modifiers are the flags and expressions that you pass into the +constructors for `cl::opt`_ and `cl::list`_. These modifiers give you the +ability to tweak how options are parsed and how ``-help`` output is generated to +fit your application well. + +These options fall into five main categories: + +#. Hiding an option from ``-help`` output + +#. Controlling the number of occurrences required and allowed + +#. Controlling whether or not a value must be specified + +#. Controlling other formatting options + +#. Miscellaneous option modifiers + +It is not possible to specify two options from the same category (you'll get a +runtime error) to a single option, except for options in the miscellaneous +category. The CommandLine library specifies defaults for all of these settings +that are the most useful in practice and the most common, which mean that you +usually shouldn't have to worry about these. + +Hiding an option from ``-help`` output +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::NotHidden``, ``cl::Hidden``, and ``cl::ReallyHidden`` modifiers are +used to control whether or not an option appears in the ``-help`` and +``-help-hidden`` output for the compiled program: + +.. _cl::NotHidden: + +* The **cl::NotHidden** modifier (which is the default for `cl::opt`_ and + `cl::list`_ options) indicates the option is to appear in both help + listings. + +.. _cl::Hidden: + +* The **cl::Hidden** modifier (which is the default for `cl::alias`_ options) + indicates that the option should not appear in the ``-help`` output, but + should appear in the ``-help-hidden`` output. + +.. _cl::ReallyHidden: + +* The **cl::ReallyHidden** modifier indicates that the option should not appear + in any help output. + +Controlling the number of occurrences required and allowed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This group of options is used to control how many time an option is allowed (or +required) to be specified on the command line of your program. Specifying a +value for this setting allows the CommandLine library to do error checking for +you. + +The allowed values for this option group are: + +.. _cl::Optional: + +* The **cl::Optional** modifier (which is the default for the `cl::opt`_ and + `cl::alias`_ classes) indicates that your program will allow either zero or + one occurrence of the option to be specified. + +.. _cl::ZeroOrMore: + +* The **cl::ZeroOrMore** modifier (which is the default for the `cl::list`_ + class) indicates that your program will allow the option to be specified zero + or more times. + +.. _cl::Required: + +* The **cl::Required** modifier indicates that the specified option must be + specified exactly one time. + +.. _cl::OneOrMore: + +* The **cl::OneOrMore** modifier indicates that the option must be specified at + least one time. + +* The **cl::ConsumeAfter** modifier is described in the `Positional arguments + section`_. + +If an option is not specified, then the value of the option is equal to the +value specified by the `cl::init`_ attribute. If the ``cl::init`` attribute is +not specified, the option value is initialized with the default constructor for +the data type. + +If an option is specified multiple times for an option of the `cl::opt`_ class, +only the last value will be retained. + +Controlling whether or not a value must be specified +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This group of options is used to control whether or not the option allows a +value to be present. In the case of the CommandLine library, a value is either +specified with an equal sign (e.g. '``-index-depth=17``') or as a trailing +string (e.g. '``-o a.out``'). + +The allowed values for this option group are: + +.. _cl::ValueOptional: + +* The **cl::ValueOptional** modifier (which is the default for ``bool`` typed + options) specifies that it is acceptable to have a value, or not. A boolean + argument can be enabled just by appearing on the command line, or it can have + an explicit '``-foo=true``'. If an option is specified with this mode, it is + illegal for the value to be provided without the equal sign. Therefore + '``-foo true``' is illegal. To get this behavior, you must use + the `cl::ValueRequired`_ modifier. + +.. _cl::ValueRequired: + +* The **cl::ValueRequired** modifier (which is the default for all other types + except for `unnamed alternatives using the generic parser`_) specifies that a + value must be provided. This mode informs the command line library that if an + option is not provides with an equal sign, that the next argument provided + must be the value. This allows things like '``-o a.out``' to work. + +.. _cl::ValueDisallowed: + +* The **cl::ValueDisallowed** modifier (which is the default for `unnamed + alternatives using the generic parser`_) indicates that it is a runtime error + for the user to specify a value. This can be provided to disallow users from + providing options to boolean options (like '``-foo=true``'). + +In general, the default values for this option group work just like you would +want them to. As mentioned above, you can specify the `cl::ValueDisallowed`_ +modifier to a boolean argument to restrict your command line parser. These +options are mostly useful when `extending the library`_. + +.. _formatting option: + +Controlling other formatting options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The formatting option group is used to specify that the command line option has +special abilities and is otherwise different from other command line arguments. +As usual, you can only specify one of these arguments at most. + +.. _cl::NormalFormatting: + +* The **cl::NormalFormatting** modifier (which is the default all options) + specifies that this option is "normal". + +.. _cl::Positional: + +* The **cl::Positional** modifier specifies that this is a positional argument + that does not have a command line option associated with it. See the + `Positional Arguments`_ section for more information. + +* The **cl::ConsumeAfter** modifier specifies that this option is used to + capture "interpreter style" arguments. See `this section for more + information`_. + +.. _prefix: +.. _cl::Prefix: + +* The **cl::Prefix** modifier specifies that this option prefixes its value. + With 'Prefix' options, the equal sign does not separate the value from the + option name specified. Instead, the value is everything after the prefix, + including any equal sign if present. This is useful for processing odd + arguments like ``-lmalloc`` and ``-L/usr/lib`` in a linker tool or + ``-DNAME=value`` in a compiler tool. Here, the '``l``', '``D``' and '``L``' + options are normal string (or list) options, that have the **cl::Prefix** + modifier added to allow the CommandLine library to recognize them. Note that + **cl::Prefix** options must not have the **cl::ValueDisallowed** modifier + specified. + +.. _grouping: +.. _cl::Grouping: + +* The **cl::Grouping** modifier is used to implement Unix-style tools (like + ``ls``) that have lots of single letter arguments, but only require a single + dash. For example, the '``ls -labF``' command actually enables four different + options, all of which are single letters. Note that **cl::Grouping** options + cannot have values. + +The CommandLine library does not restrict how you use the **cl::Prefix** or +**cl::Grouping** modifiers, but it is possible to specify ambiguous argument +settings. Thus, it is possible to have multiple letter options that are prefix +or grouping options, and they will still work as designed. + +To do this, the CommandLine library uses a greedy algorithm to parse the input +option into (potentially multiple) prefix and grouping options. The strategy +basically looks like this: + +:: + + parse(string OrigInput) { + + 1. string input = OrigInput; + 2. if (isOption(input)) return getOption(input).parse(); // Normal option + 3. while (!isOption(input) && !input.empty()) input.pop_back(); // Remove the last letter + 4. if (input.empty()) return error(); // No matching option + 5. if (getOption(input).isPrefix()) + return getOption(input).parse(input); + 6. while (!input.empty()) { // Must be grouping options + getOption(input).parse(); + OrigInput.erase(OrigInput.begin(), OrigInput.begin()+input.length()); + input = OrigInput; + while (!isOption(input) && !input.empty()) input.pop_back(); + } + 7. if (!OrigInput.empty()) error(); + + } + +Miscellaneous option modifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The miscellaneous option modifiers are the only flags where you can specify more +than one flag from the set: they are not mutually exclusive. These flags +specify boolean properties that modify the option. + +.. _cl::CommaSeparated: + +* The **cl::CommaSeparated** modifier indicates that any commas specified for an + option's value should be used to split the value up into multiple values for + the option. For example, these two options are equivalent when + ``cl::CommaSeparated`` is specified: "``-foo=a -foo=b -foo=c``" and + "``-foo=a,b,c``". This option only makes sense to be used in a case where the + option is allowed to accept one or more values (i.e. it is a `cl::list`_ + option). + +.. _cl::PositionalEatsArgs: + +* The **cl::PositionalEatsArgs** modifier (which only applies to positional + arguments, and only makes sense for lists) indicates that positional argument + should consume any strings after it (including strings that start with a "-") + up until another recognized positional argument. For example, if you have two + "eating" positional arguments, "``pos1``" and "``pos2``", the string "``-pos1 + -foo -bar baz -pos2 -bork``" would cause the "``-foo -bar -baz``" strings to + be applied to the "``-pos1``" option and the "``-bork``" string to be applied + to the "``-pos2``" option. + +.. _cl::Sink: + +* The **cl::Sink** modifier is used to handle unknown options. If there is at + least one option with ``cl::Sink`` modifier specified, the parser passes + unrecognized option strings to it as values instead of signaling an error. As + with ``cl::CommaSeparated``, this modifier only makes sense with a `cl::list`_ + option. + +So far, these are the only three miscellaneous option modifiers. + +.. _response files: + +Response files +^^^^^^^^^^^^^^ + +Some systems, such as certain variants of Microsoft Windows and some older +Unices have a relatively low limit on command-line length. It is therefore +customary to use the so-called 'response files' to circumvent this +restriction. These files are mentioned on the command-line (using the "@file") +syntax. The program reads these files and inserts the contents into argv, +thereby working around the command-line length limits. Response files are +enabled by an optional fourth argument to `cl::ParseEnvironmentOptions`_ and +`cl::ParseCommandLineOptions`_. + +Top-Level Classes and Functions +------------------------------- + +Despite all of the built-in flexibility, the CommandLine option library really +only consists of one function `cl::ParseCommandLineOptions`_) and three main +classes: `cl::opt`_, `cl::list`_, and `cl::alias`_. This section describes +these three classes in detail. + +.. _cl::getRegisteredOptions: + +The ``cl::getRegisteredOptions`` function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::getRegisteredOptions`` function is designed to give a programmer +access to declared non positional command line options so that how they appear +in ``-help`` can be modified prior to calling `cl::ParseCommandLineOptions`_. +Note this method should not be called during any static initialisation because +it cannot be guaranteed that all options will have been initialised. Hence it +should be called from ``main``. + +This function can be used to gain access to options declared in libraries that +the tool writter may not have direct access to. + +The function retrieves a :ref:`StringMap ` that maps the option +string (e.g. ``-help``) to an ``Option*``. + +Here is an example of how the function could be used: + +.. code-block:: c++ + + using namespace llvm; + int main(int argc, char **argv) { + cl::OptionCategory AnotherCategory("Some options"); + + StringMap Map; + cl::getRegisteredOptions(Map); + + //Unhide useful option and put it in a different category + assert(Map.count("print-all-options") > 0); + Map["print-all-options"]->setHiddenFlag(cl::NotHidden); + Map["print-all-options"]->setCategory(AnotherCategory); + + //Hide an option we don't want to see + assert(Map.count("enable-no-infs-fp-math") > 0); + Map["enable-no-infs-fp-math"]->setHiddenFlag(cl::Hidden); + + //Change --version to --show-version + assert(Map.count("version") > 0); + Map["version"]->setArgStr("show-version"); + + //Change --help description + assert(Map.count("help") > 0); + Map["help"]->setDescription("Shows help"); + + cl::ParseCommandLineOptions(argc, argv, "This is a small program to demo the LLVM CommandLine API"); + ... + } + + +.. _cl::ParseCommandLineOptions: + +The ``cl::ParseCommandLineOptions`` function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::ParseCommandLineOptions`` function is designed to be called directly +from ``main``, and is used to fill in the values of all of the command line +option variables once ``argc`` and ``argv`` are available. + +The ``cl::ParseCommandLineOptions`` function requires two parameters (``argc`` +and ``argv``), but may also take an optional third parameter which holds +`additional extra text`_ to emit when the ``-help`` option is invoked, and a +fourth boolean parameter that enables `response files`_. + +.. _cl::ParseEnvironmentOptions: + +The ``cl::ParseEnvironmentOptions`` function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::ParseEnvironmentOptions`` function has mostly the same effects as +`cl::ParseCommandLineOptions`_, except that it is designed to take values for +options from an environment variable, for those cases in which reading the +command line is not convenient or desired. It fills in the values of all the +command line option variables just like `cl::ParseCommandLineOptions`_ does. + +It takes four parameters: the name of the program (since ``argv`` may not be +available, it can't just look in ``argv[0]``), the name of the environment +variable to examine, the optional `additional extra text`_ to emit when the +``-help`` option is invoked, and the boolean switch that controls whether +`response files`_ should be read. + +``cl::ParseEnvironmentOptions`` will break the environment variable's value up +into words and then process them using `cl::ParseCommandLineOptions`_. +**Note:** Currently ``cl::ParseEnvironmentOptions`` does not support quoting, so +an environment variable containing ``-option "foo bar"`` will be parsed as three +words, ``-option``, ``"foo``, and ``bar"``, which is different from what you +would get from the shell with the same input. + +The ``cl::SetVersionPrinter`` function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::SetVersionPrinter`` function is designed to be called directly from +``main`` and *before* ``cl::ParseCommandLineOptions``. Its use is optional. It +simply arranges for a function to be called in response to the ``--version`` +option instead of having the ``CommandLine`` library print out the usual version +string for LLVM. This is useful for programs that are not part of LLVM but wish +to use the ``CommandLine`` facilities. Such programs should just define a small +function that takes no arguments and returns ``void`` and that prints out +whatever version information is appropriate for the program. Pass the address of +that function to ``cl::SetVersionPrinter`` to arrange for it to be called when +the ``--version`` option is given by the user. + +.. _cl::opt: +.. _scalar: + +The ``cl::opt`` class +^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::opt`` class is the class used to represent scalar command line +options, and is the one used most of the time. It is a templated class which +can take up to three arguments (all except for the first have default values +though): + +.. code-block:: c++ + + namespace cl { + template > + class opt; + } + +The first template argument specifies what underlying data type the command line +argument is, and is used to select a default parser implementation. The second +template argument is used to specify whether the option should contain the +storage for the option (the default) or whether external storage should be used +to contain the value parsed for the option (see `Internal vs External Storage`_ +for more information). + +The third template argument specifies which parser to use. The default value +selects an instantiation of the ``parser`` class based on the underlying data +type of the option. In general, this default works well for most applications, +so this option is only used when using a `custom parser`_. + +.. _lists of arguments: +.. _cl::list: + +The ``cl::list`` class +^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::list`` class is the class used to represent a list of command line +options. It too is a templated class which can take up to three arguments: + +.. code-block:: c++ + + namespace cl { + template > + class list; + } + +This class works the exact same as the `cl::opt`_ class, except that the second +argument is the **type** of the external storage, not a boolean value. For this +class, the marker type '``bool``' is used to indicate that internal storage +should be used. + +.. _cl::bits: + +The ``cl::bits`` class +^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::bits`` class is the class used to represent a list of command line +options in the form of a bit vector. It is also a templated class which can +take up to three arguments: + +.. code-block:: c++ + + namespace cl { + template > + class bits; + } + +This class works the exact same as the `cl::list`_ class, except that the second +argument must be of **type** ``unsigned`` if external storage is used. + +.. _cl::alias: + +The ``cl::alias`` class +^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::alias`` class is a nontemplated class that is used to form aliases for +other arguments. + +.. code-block:: c++ + + namespace cl { + class alias; + } + +The `cl::aliasopt`_ attribute should be used to specify which option this is an +alias for. Alias arguments default to being `cl::Hidden`_, and use the aliased +options parser to do the conversion from string to data. + +.. _cl::extrahelp: + +The ``cl::extrahelp`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::extrahelp`` class is a nontemplated class that allows extra help text +to be printed out for the ``-help`` option. + +.. code-block:: c++ + + namespace cl { + struct extrahelp; + } + +To use the extrahelp, simply construct one with a ``const char*`` parameter to +the constructor. The text passed to the constructor will be printed at the +bottom of the help message, verbatim. Note that multiple ``cl::extrahelp`` +**can** be used, but this practice is discouraged. If your tool needs to print +additional help information, put all that help into a single ``cl::extrahelp`` +instance. + +For example: + +.. code-block:: c++ + + cl::extrahelp("\nADDITIONAL HELP:\n\n This is the extra help\n"); + +.. _cl::OptionCategory: + +The ``cl::OptionCategory`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``cl::OptionCategory`` class is a simple class for declaring +option categories. + +.. code-block:: c++ + + namespace cl { + class OptionCategory; + } + +An option category must have a name and optionally a description which are +passed to the constructor as ``const char*``. + +Note that declaring an option category and associating it with an option before +parsing options (e.g. statically) will change the output of ``-help`` from +uncategorized to categorized. If an option category is declared but not +associated with an option then it will be hidden from the output of ``-help`` +but will be shown in the output of ``-help-hidden``. + +.. _different parser: +.. _discussed previously: + +Builtin parsers +--------------- + +Parsers control how the string value taken from the command line is translated +into a typed value, suitable for use in a C++ program. By default, the +CommandLine library uses an instance of ``parser`` if the command line +option specifies that it uses values of type '``type``'. Because of this, +custom option processing is specified with specializations of the '``parser``' +class. + +The CommandLine library provides the following builtin parser specializations, +which are sufficient for most applications. It can, however, also be extended to +work with new data types and new ways of interpreting the same data. See the +`Writing a Custom Parser`_ for more details on this type of library extension. + +.. _enums: +.. _cl::parser: + +* The generic ``parser`` parser can be used to map strings values to any data + type, through the use of the `cl::values`_ property, which specifies the + mapping information. The most common use of this parser is for parsing enum + values, which allows you to use the CommandLine library for all of the error + checking to make sure that only valid enum values are specified (as opposed to + accepting arbitrary strings). Despite this, however, the generic parser class + can be used for any data type. + +.. _boolean flags: +.. _bool parser: + +* The **parser specialization** is used to convert boolean strings to a + boolean value. Currently accepted strings are "``true``", "``TRUE``", + "``True``", "``1``", "``false``", "``FALSE``", "``False``", and "``0``". + +* The **parser specialization** is used for cases where the value + is boolean, but we also need to know whether the option was specified at all. + boolOrDefault is an enum with 3 values, BOU_UNSET, BOU_TRUE and BOU_FALSE. + This parser accepts the same strings as **``parser``**. + +.. _strings: + +* The **parser specialization** simply stores the parsed string into the + string value specified. No conversion or modification of the data is + performed. + +.. _integers: +.. _int: + +* The **parser specialization** uses the C ``strtol`` function to parse the + string input. As such, it will accept a decimal number (with an optional '+' + or '-' prefix) which must start with a non-zero digit. It accepts octal + numbers, which are identified with a '``0``' prefix digit, and hexadecimal + numbers with a prefix of '``0x``' or '``0X``'. + +.. _doubles: +.. _float: +.. _double: + +* The **parser** and **parser specializations** use the standard + C ``strtod`` function to convert floating point strings into floating point + values. As such, a broad range of string formats is supported, including + exponential notation (ex: ``1.7e15``) and properly supports locales. + +.. _Extension Guide: +.. _extending the library: + +Extension Guide +=============== + +Although the CommandLine library has a lot of functionality built into it +already (as discussed previously), one of its true strengths lie in its +extensibility. This section discusses how the CommandLine library works under +the covers and illustrates how to do some simple, common, extensions. + +.. _Custom parsers: +.. _custom parser: +.. _Writing a Custom Parser: + +Writing a custom parser +----------------------- + +One of the simplest and most common extensions is the use of a custom parser. +As `discussed previously`_, parsers are the portion of the CommandLine library +that turns string input from the user into a particular parsed data type, +validating the input in the process. + +There are two ways to use a new parser: + +#. Specialize the `cl::parser`_ template for your custom data type. + + This approach has the advantage that users of your custom data type will + automatically use your custom parser whenever they define an option with a + value type of your data type. The disadvantage of this approach is that it + doesn't work if your fundamental data type is something that is already + supported. + +#. Write an independent class, using it explicitly from options that need it. + + This approach works well in situations where you would line to parse an + option using special syntax for a not-very-special data-type. The drawback + of this approach is that users of your parser have to be aware that they are + using your parser instead of the builtin ones. + +To guide the discussion, we will discuss a custom parser that accepts file +sizes, specified with an optional unit after the numeric size. For example, we +would like to parse "102kb", "41M", "1G" into the appropriate integer value. In +this case, the underlying data type we want to parse into is '``unsigned``'. We +choose approach #2 above because we don't want to make this the default for all +``unsigned`` options. + +To start out, we declare our new ``FileSizeParser`` class: + +.. code-block:: c++ + + struct FileSizeParser : public cl::basic_parser { + // parse - Return true on error. + bool parse(cl::Option &O, const char *ArgName, const std::string &ArgValue, + unsigned &Val); + }; + +Our new class inherits from the ``cl::basic_parser`` template class to fill in +the default, boiler plate code for us. We give it the data type that we parse +into, the last argument to the ``parse`` method, so that clients of our custom +parser know what object type to pass in to the parse method. (Here we declare +that we parse into '``unsigned``' variables.) + +For most purposes, the only method that must be implemented in a custom parser +is the ``parse`` method. The ``parse`` method is called whenever the option is +invoked, passing in the option itself, the option name, the string to parse, and +a reference to a return value. If the string to parse is not well-formed, the +parser should output an error message and return true. Otherwise it should +return false and set '``Val``' to the parsed value. In our example, we +implement ``parse`` as: + +.. code-block:: c++ + + bool FileSizeParser::parse(cl::Option &O, const char *ArgName, + const std::string &Arg, unsigned &Val) { + const char *ArgStart = Arg.c_str(); + char *End; + + // Parse integer part, leaving 'End' pointing to the first non-integer char + Val = (unsigned)strtol(ArgStart, &End, 0); + + while (1) { + switch (*End++) { + case 0: return false; // No error + case 'i': // Ignore the 'i' in KiB if people use that + case 'b': case 'B': // Ignore B suffix + break; + + case 'g': case 'G': Val *= 1024*1024*1024; break; + case 'm': case 'M': Val *= 1024*1024; break; + case 'k': case 'K': Val *= 1024; break; + + default: + // Print an error message if unrecognized character! + return O.error("'" + Arg + "' value invalid for file size argument!"); + } + } + } + +This function implements a very simple parser for the kinds of strings we are +interested in. Although it has some holes (it allows "``123KKK``" for example), +it is good enough for this example. Note that we use the option itself to print +out the error message (the ``error`` method always returns true) in order to get +a nice error message (shown below). Now that we have our parser class, we can +use it like this: + +.. code-block:: c++ + + static cl::opt + MFS("max-file-size", cl::desc("Maximum file size to accept"), + cl::value_desc("size")); + +Which adds this to the output of our program: + +:: + + OPTIONS: + -help - display available options (-help-hidden for more) + ... + -max-file-size= - Maximum file size to accept + +And we can test that our parse works correctly now (the test program just prints +out the max-file-size argument value): + +:: + + $ ./test + MFS: 0 + $ ./test -max-file-size=123MB + MFS: 128974848 + $ ./test -max-file-size=3G + MFS: 3221225472 + $ ./test -max-file-size=dog + -max-file-size option: 'dog' value invalid for file size argument! + +It looks like it works. The error message that we get is nice and helpful, and +we seem to accept reasonable file sizes. This wraps up the "custom parser" +tutorial. + +Exploiting external storage +--------------------------- + +Several of the LLVM libraries define static ``cl::opt`` instances that will +automatically be included in any program that links with that library. This is +a feature. However, sometimes it is necessary to know the value of the command +line option outside of the library. In these cases the library does or should +provide an external storage location that is accessible to users of the +library. Examples of this include the ``llvm::DebugFlag`` exported by the +``lib/Support/Debug.cpp`` file and the ``llvm::TimePassesIsEnabled`` flag +exported by the ``lib/VMCore/PassManager.cpp`` file. + +.. todo:: + + TODO: complete this section + +.. _dynamically loaded options: + +Dynamically adding command line options + +.. todo:: + + TODO: fill in this section diff --git a/docs/CompilerWriterInfo.rst b/docs/CompilerWriterInfo.rst new file mode 100644 index 00000000..7b02a787 --- /dev/null +++ b/docs/CompilerWriterInfo.rst @@ -0,0 +1,155 @@ +======================================================== +Architecture & Platform Information for Compiler Writers +======================================================== + +.. contents:: + :local: + +.. note:: + + This document is a work-in-progress. Additions and clarifications are + welcome. + +Hardware +======== + +ARM +--- + +* `ARM documentation `_ (`Processor Cores `_ Cores) + +* `ABI `_ + +* `ABI Addenda and Errata `_ + +* `ARM C Language Extensions `_ + +AArch64 +------- + +* `ARMv8 Instruction Set Overview `_ + +* `ARM C Language Extensions `_ + +Itanium (ia64) +-------------- + +* `Itanium documentation `_ + +MIPS +---- + +* `MIPS Processor Architecture `_ + +PowerPC +------- + +IBM - Official manuals and docs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* `Power Instruction Set Architecture, Versions 2.03 through 2.06 (authentication required, free sign-up) `_ + +* `PowerPC Compiler Writer's Guide `_ + +* `Intro to PowerPC Architecture `_ + +* `PowerPC Processor Manuals (embedded) `_ + +* `Various IBM specifications and white papers `_ + +* `IBM AIX/5L for POWER Assembly Reference `_ + +Other documents, collections, notes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* `PowerPC ABI documents `_ +* `PowerPC64 alignment of long doubles (from GCC) `_ +* `Long branch stubs for powerpc64-linux (from binutils) `_ + +R600 +---- + +* `AMD R6xx shader ISA `_ +* `AMD R7xx shader ISA `_ +* `AMD Evergreen shader ISA `_ +* `AMD Cayman/Trinity shader ISA `_ +* `AMD Southern Islands Series ISA `_ +* `AMD GPU Programming Guide `_ +* `AMD Compute Resources `_ + +SPARC +----- + +* `SPARC resources `_ +* `SPARC standards `_ + +SystemZ +------- + +* `z/Architecture Principles of Operation (registration required, free sign-up) `_ + +X86 +--- + +AMD - Official manuals and docs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* `AMD processor manuals `_ +* `X86-64 ABI `_ + +Intel - Official manuals and docs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* `Intel 64 and IA-32 manuals `_ +* `Intel Itanium documentation `_ + +Other x86-specific information +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* `Calling conventions for different C++ compilers and operating systems `_ + +Other relevant lists +-------------------- + +* `GCC reading list `_ + +ABI +=== + +* `System V Application Binary Interface `_ +* `Itanium C++ ABI `_ + +Linux +----- + +* `PowerPC 64-bit ELF ABI Supplement `_ +* `Procedure Call Standard for the AArch64 Architecture `_ +* `ELF for the ARM Architecture `_ +* `ELF for the ARM 64-bit Architecture (AArch64) `_ +* `System z ELF ABI Supplement `_ + +OS X +---- + +* `Mach-O Runtime Architecture `_ +* `Notes on Mach-O ABI `_ + +Windows +------- + +* `Microsoft PE/COFF Specification `_ + +NVPTX +===== + +* `CUDA Documentation `_ includes the PTX + ISA and Driver API documentation + +Miscellaneous Resources +======================= + +* `Executable File Format library `_ + +* `GCC prefetch project `_ page has a + good survey of the prefetching capabilities of a variety of modern + processors. diff --git a/docs/DebuggingJITedCode.rst b/docs/DebuggingJITedCode.rst new file mode 100644 index 00000000..d6101d51 --- /dev/null +++ b/docs/DebuggingJITedCode.rst @@ -0,0 +1,143 @@ +============================== +Debugging JIT-ed Code With GDB +============================== + +Background +========== + +Without special runtime support, debugging dynamically generated code with +GDB (as well as most debuggers) can be quite painful. Debuggers generally +read debug information from the object file of the code, but for JITed +code, there is no such file to look for. + +In order to communicate the necessary debug info to GDB, an interface for +registering JITed code with debuggers has been designed and implemented for +GDB and LLVM MCJIT. At a high level, whenever MCJIT generates new machine code, +it does so in an in-memory object file that contains the debug information in +DWARF format. MCJIT then adds this in-memory object file to a global list of +dynamically generated object files and calls a special function +(``__jit_debug_register_code``) marked noinline that GDB knows about. When +GDB attaches to a process, it puts a breakpoint in this function and loads all +of the object files in the global list. When MCJIT calls the registration +function, GDB catches the breakpoint signal, loads the new object file from +the inferior's memory, and resumes the execution. In this way, GDB can get the +necessary debug information. + +GDB Version +=========== + +In order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is +available on most modern distributions of Linux. The version of GDB that +Apple ships with Xcode has been frozen at 6.3 for a while. LLDB may be a +better option for debugging JIT-ed code on Mac OS X. + + +Debugging MCJIT-ed code +======================= + +The emerging MCJIT component of LLVM allows full debugging of JIT-ed code with +GDB. This is due to MCJIT's ability to use the MC emitter to provide full +DWARF debugging information to GDB. + +Note that lli has to be passed the ``-use-mcjit`` flag to JIT the code with +MCJIT instead of the old JIT. + +Example +------- + +Consider the following C code (with line numbers added to make the example +easier to follow): + +.. + FIXME: + Sphinx has the ability to automatically number these lines by adding + :linenos: on the line immediately following the `.. code-block:: c`, but + it looks like garbage; the line numbers don't even line up with the + lines. Is this a Sphinx bug, or is it a CSS problem? + +.. code-block:: c + + 1 int compute_factorial(int n) + 2 { + 3 if (n <= 1) + 4 return 1; + 5 + 6 int f = n; + 7 while (--n > 1) + 8 f *= n; + 9 return f; + 10 } + 11 + 12 + 13 int main(int argc, char** argv) + 14 { + 15 if (argc < 2) + 16 return -1; + 17 char firstletter = argv[1][0]; + 18 int result = compute_factorial(firstletter - '0'); + 19 + 20 // Returned result is clipped at 255... + 21 return result; + 22 } + +Here is a sample command line session that shows how to build and run this +code via ``lli`` inside GDB: + +.. code-block:: bash + + $ $BINPATH/clang -cc1 -O0 -g -emit-llvm showdebug.c + $ gdb --quiet --args $BINPATH/lli -use-mcjit showdebug.ll 5 + Reading symbols from $BINPATH/lli...done. + (gdb) b showdebug.c:6 + No source file named showdebug.c. + Make breakpoint pending on future shared library load? (y or [n]) y + Breakpoint 1 (showdebug.c:6) pending. + (gdb) r + Starting program: $BINPATH/lli -use-mcjit showdebug.ll 5 + [Thread debugging using libthread_db enabled] + + Breakpoint 1, compute_factorial (n=5) at showdebug.c:6 + 6 int f = n; + (gdb) p n + $1 = 5 + (gdb) p f + $2 = 0 + (gdb) n + 7 while (--n > 1) + (gdb) p f + $3 = 5 + (gdb) b showdebug.c:9 + Breakpoint 2 at 0x7ffff7ed404c: file showdebug.c, line 9. + (gdb) c + Continuing. + + Breakpoint 2, compute_factorial (n=1) at showdebug.c:9 + 9 return f; + (gdb) p f + $4 = 120 + (gdb) bt + #0 compute_factorial (n=1) at showdebug.c:9 + #1 0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18 + #2 0x3500000001652748 in ?? () + #3 0x00000000016677e0 in ?? () + #4 0x0000000000000002 in ?? () + #5 0x0000000000d953b3 in llvm::MCJIT::runFunction (this=0x16151f0, F=0x1603020, ArgValues=...) at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/MCJIT/MCJIT.cpp:161 + #6 0x0000000000dc8872 in llvm::ExecutionEngine::runFunctionAsMain (this=0x16151f0, Fn=0x1603020, argv=..., envp=0x7fffffffe040) + at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/ExecutionEngine.cpp:397 + #7 0x000000000059c583 in main (argc=4, argv=0x7fffffffe018, envp=0x7fffffffe040) at /home/ebenders_test/llvm_svn_rw/tools/lli/lli.cpp:324 + (gdb) finish + Run till exit from #0 compute_factorial (n=1) at showdebug.c:9 + 0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18 + 18 int result = compute_factorial(firstletter - '0'); + Value returned is $5 = 120 + (gdb) p result + $6 = 23406408 + (gdb) n + 21 return result; + (gdb) p result + $7 = 120 + (gdb) c + Continuing. + + Program exited with code 0170. + (gdb) diff --git a/docs/DeveloperPolicy.rst b/docs/DeveloperPolicy.rst new file mode 100644 index 00000000..ea5a7d1b --- /dev/null +++ b/docs/DeveloperPolicy.rst @@ -0,0 +1,533 @@ +===================== +LLVM Developer Policy +===================== + +.. contents:: + :local: + +Introduction +============ + +This document contains the LLVM Developer Policy which defines the project's +policy towards developers and their contributions. The intent of this policy is +to eliminate miscommunication, rework, and confusion that might arise from the +distributed nature of LLVM's development. By stating the policy in clear terms, +we hope each developer can know ahead of time what to expect when making LLVM +contributions. This policy covers all llvm.org subprojects, including Clang, +LLDB, libc++, etc. + +This policy is also designed to accomplish the following objectives: + +#. Attract both users and developers to the LLVM project. + +#. Make life as simple and easy for contributors as possible. + +#. Keep the top of Subversion trees as stable as possible. + +#. Establish awareness of the project's :ref:`copyright, license, and patent + policies ` with contributors to the project. + +This policy is aimed at frequent contributors to LLVM. People interested in +contributing one-off patches can do so in an informal way by sending them to the +`llvm-commits mailing list +`_ and engaging another +developer to see it through the process. + +Developer Policies +================== + +This section contains policies that pertain to frequent LLVM developers. We +always welcome `one-off patches`_ from people who do not routinely contribute to +LLVM, but we expect more from frequent contributors to keep the system as +efficient as possible for everyone. Frequent LLVM contributors are expected to +meet the following requirements in order for LLVM to maintain a high standard of +quality. + +Stay Informed +------------- + +Developers should stay informed by reading at least the "dev" mailing list for +the projects you are interested in, such as `llvmdev +`_ for LLVM, `cfe-dev +`_ for Clang, or `lldb-dev +`_ for LLDB. If you are +doing anything more than just casual work on LLVM, it is suggested that you also +subscribe to the "commits" mailing list for the subproject you're interested in, +such as `llvm-commits +`_, `cfe-commits +`_, or `lldb-commits +`_. Reading the +"commits" list and paying attention to changes being made by others is a good +way to see what other people are interested in and watching the flow of the +project as a whole. + +We recommend that active developers register an email account with `LLVM +Bugzilla `_ and preferably subscribe to the `llvm-bugs +`_ email list to keep track +of bugs and enhancements occurring in LLVM. We really appreciate people who are +proactive at catching incoming bugs in their components and dealing with them +promptly. + +Please be aware that all public LLVM mailing lists are public and archived, and +that notices of confidentiality or non-disclosure cannot be respected. + +.. _patch: +.. _one-off patches: + +Making a Patch +-------------- + +When making a patch for review, the goal is to make it as easy for the reviewer +to read it as possible. As such, we recommend that you: + +#. Make your patch against the Subversion trunk, not a branch, and not an old + version of LLVM. This makes it easy to apply the patch. For information on + how to check out SVN trunk, please see the `Getting Started + Guide `_. + +#. Similarly, patches should be submitted soon after they are generated. Old + patches may not apply correctly if the underlying code changes between the + time the patch was created and the time it is applied. + +#. Patches should be made with ``svn diff``, or similar. If you use a + different tool, make sure it uses the ``diff -u`` format and that it + doesn't contain clutter which makes it hard to read. + +#. If you are modifying generated files, such as the top-level ``configure`` + script, please separate out those changes into a separate patch from the rest + of your changes. + +When sending a patch to a mailing list, it is a good idea to send it as an +*attachment* to the message, not embedded into the text of the message. This +ensures that your mailer will not mangle the patch when it sends it (e.g. by +making whitespace changes or by wrapping lines). + +*For Thunderbird users:* Before submitting a patch, please open *Preferences > +Advanced > General > Config Editor*, find the key +``mail.content_disposition_type``, and set its value to ``1``. Without this +setting, Thunderbird sends your attachment using ``Content-Disposition: inline`` +rather than ``Content-Disposition: attachment``. Apple Mail gamely displays such +a file inline, making it difficult to work with for reviewers using that +program. + +When submitting patches, please do not add confidentiality or non-disclosure +notices to the patches themselves. These notices conflict with the `LLVM +License`_ and may result in your contribution being excluded. + +.. _code review: + +Code Reviews +------------ + +LLVM has a code review policy. Code review is one way to increase the quality of +software. We generally follow these policies: + +#. All developers are required to have significant changes reviewed before they + are committed to the repository. + +#. Code reviews are conducted by email, usually on the llvm-commits list. + +#. Code can be reviewed either before it is committed or after. We expect major + changes to be reviewed before being committed, but smaller changes (or + changes where the developer owns the component) can be reviewed after commit. + +#. The developer responsible for a code change is also responsible for making + all necessary review-related changes. + +#. Code review can be an iterative process, which continues until the patch is + ready to be committed. Specifically, once a patch is sent out for review, it + needs an explicit "looks good" before it is submitted. Do not assume silent + approval, or request active objections to the patch with a deadline. + +Sometimes code reviews will take longer than you would hope for, especially for +larger features. Accepted ways to speed up review times for your patches are: + +* Review other people's patches. If you help out, everybody will be more + willing to do the same for you; goodwill is our currency. +* Ping the patch. If it is urgent, provide reasons why it is important to you to + get this patch landed and ping it every couple of days. If it is + not urgent, the common courtesy ping rate is one week. Remember that you're + asking for valuable time from other professional developers. +* Ask for help on IRC. Developers on IRC will be able to either help you + directly, or tell you who might be a good reviewer. +* Split your patch into multiple smaller patches that build on each other. The + smaller your patch, the higher the probability that somebody will take a quick + look at it. + +Developers should participate in code reviews as both reviewers and +reviewees. If someone is kind enough to review your code, you should return the +favor for someone else. Note that anyone is welcome to review and give feedback +on a patch, but only people with Subversion write access can approve it. + +There is a web based code review tool that can optionally be used +for code reviews. See :doc:`Phabricator`. + +Code Owners +----------- + +The LLVM Project relies on two features of its process to maintain rapid +development in addition to the high quality of its source base: the combination +of code review plus post-commit review for trusted maintainers. Having both is +a great way for the project to take advantage of the fact that most people do +the right thing most of the time, and only commit patches without pre-commit +review when they are confident they are right. + +The trick to this is that the project has to guarantee that all patches that are +committed are reviewed after they go in: you don't want everyone to assume +someone else will review it, allowing the patch to go unreviewed. To solve this +problem, we have a notion of an 'owner' for a piece of the code. The sole +responsibility of a code owner is to ensure that a commit to their area of the +code is appropriately reviewed, either by themself or by someone else. The list +of current code owners can be found in the file +`CODE_OWNERS.TXT `_ +in the root of the LLVM source tree. + +Note that code ownership is completely different than reviewers: anyone can +review a piece of code, and we welcome code review from anyone who is +interested. Code owners are the "last line of defense" to guarantee that all +patches that are committed are actually reviewed. + +Being a code owner is a somewhat unglamorous position, but it is incredibly +important for the ongoing success of the project. Because people get busy, +interests change, and unexpected things happen, code ownership is purely opt-in, +and anyone can choose to resign their "title" at any time. For now, we do not +have an official policy on how one gets elected to be a code owner. + +.. _include a testcase: + +Test Cases +---------- + +Developers are required to create test cases for any bugs fixed and any new +features added. Some tips for getting your testcase approved: + +* All feature and regression test cases are added to the ``llvm/test`` + directory. The appropriate sub-directory should be selected (see the + :doc:`Testing Guide ` for details). + +* Test cases should be written in `LLVM assembly language `_ + unless the feature or regression being tested requires another language + (e.g. the bug being fixed or feature being implemented is in the llvm-gcc C++ + front-end, in which case it must be written in C++). + +* Test cases, especially for regressions, should be reduced as much as possible, + by `bugpoint `_ or manually. It is unacceptable to place an + entire failing program into ``llvm/test`` as this creates a *time-to-test* + burden on all developers. Please keep them short. + +Note that llvm/test and clang/test are designed for regression and small feature +tests only. More extensive test cases (e.g., entire applications, benchmarks, +etc) should be added to the ``llvm-test`` test suite. The llvm-test suite is +for coverage (correctness, performance, etc) testing, not feature or regression +testing. + +Quality +------- + +The minimum quality standards that any change must satisfy before being +committed to the main development branch are: + +#. Code must adhere to the `LLVM Coding Standards `_. + +#. Code must compile cleanly (no errors, no warnings) on at least one platform. + +#. Bug fixes and new features should `include a testcase`_ so we know if the + fix/feature ever regresses in the future. + +#. Code must pass the ``llvm/test`` test suite. + +#. The code must not cause regressions on a reasonable subset of llvm-test, + where "reasonable" depends on the contributor's judgement and the scope of + the change (more invasive changes require more testing). A reasonable subset + might be something like "``llvm-test/MultiSource/Benchmarks``". + +Additionally, the committer is responsible for addressing any problems found in +the future that the change is responsible for. For example: + +* The code should compile cleanly on all supported platforms. + +* The changes should not cause any correctness regressions in the ``llvm-test`` + suite and must not cause any major performance regressions. + +* The change set should not cause performance or correctness regressions for the + LLVM tools. + +* The changes should not cause performance or correctness regressions in code + compiled by LLVM on all applicable targets. + +* You are expected to address any `Bugzilla bugs `_ that + result from your change. + +We prefer for this to be handled before submission but understand that it isn't +possible to test all of this for every submission. Our build bots and nightly +testing infrastructure normally finds these problems. A good rule of thumb is +to check the nightly testers for regressions the day after your change. Build +bots will directly email you if a group of commits that included yours caused a +failure. You are expected to check the build bot messages to see if they are +your fault and, if so, fix the breakage. + +Commits that violate these quality standards (e.g. are very broken) may be +reverted. This is necessary when the change blocks other developers from making +progress. The developer is welcome to re-commit the change after the problem has +been fixed. + +Obtaining Commit Access +----------------------- + +We grant commit access to contributors with a track record of submitting high +quality patches. If you would like commit access, please send an email to +`Chris `_ with the following information: + +#. The user name you want to commit with, e.g. "hacker". + +#. The full name and email address you want message to llvm-commits to come + from, e.g. "J. Random Hacker ". + +#. A "password hash" of the password you want to use, e.g. "``2ACR96qjUqsyM``". + Note that you don't ever tell us what your password is; you just give it to + us in an encrypted form. To get this, run "``htpasswd``" (a utility that + comes with apache) in crypt mode (often enabled with "``-d``"), or find a web + page that will do it for you. + +Once you've been granted commit access, you should be able to check out an LLVM +tree with an SVN URL of "https://username@llvm.org/..." instead of the normal +anonymous URL of "http://llvm.org/...". The first time you commit you'll have +to type in your password. Note that you may get a warning from SVN about an +untrusted key; you can ignore this. To verify that your commit access works, +please do a test commit (e.g. change a comment or add a blank line). Your first +commit to a repository may require the autogenerated email to be approved by a +mailing list. This is normal and will be done when the mailing list owner has +time. + +If you have recently been granted commit access, these policies apply: + +#. You are granted *commit-after-approval* to all parts of LLVM. To get + approval, submit a `patch`_ to `llvm-commits + `_. When approved, + you may commit it yourself. + +#. You are allowed to commit patches without approval which you think are + obvious. This is clearly a subjective decision --- we simply expect you to + use good judgement. Examples include: fixing build breakage, reverting + obviously broken patches, documentation/comment changes, any other minor + changes. + +#. You are allowed to commit patches without approval to those portions of LLVM + that you have contributed or maintain (i.e., have been assigned + responsibility for), with the proviso that such commits must not break the + build. This is a "trust but verify" policy, and commits of this nature are + reviewed after they are committed. + +#. Multiple violations of these policies or a single egregious violation may + cause commit access to be revoked. + +In any case, your changes are still subject to `code review`_ (either before or +after they are committed, depending on the nature of the change). You are +encouraged to review other peoples' patches as well, but you aren't required +to do so. + +.. _discuss the change/gather consensus: + +Making a Major Change +--------------------- + +When a developer begins a major new project with the aim of contributing it back +to LLVM, s/he should inform the community with an email to the `llvmdev +`_ email list, to the extent +possible. The reason for this is to: + +#. keep the community informed about future changes to LLVM, + +#. avoid duplication of effort by preventing multiple parties working on the + same thing and not knowing about it, and + +#. ensure that any technical issues around the proposed work are discussed and + resolved before any significant work is done. + +The design of LLVM is carefully controlled to ensure that all the pieces fit +together well and are as consistent as possible. If you plan to make a major +change to the way LLVM works or want to add a major new extension, it is a good +idea to get consensus with the development community before you start working on +it. + +Once the design of the new feature is finalized, the work itself should be done +as a series of `incremental changes`_, not as a long-term development branch. + +.. _incremental changes: + +Incremental Development +----------------------- + +In the LLVM project, we do all significant changes as a series of incremental +patches. We have a strong dislike for huge changes or long-term development +branches. Long-term development branches have a number of drawbacks: + +#. Branches must have mainline merged into them periodically. If the branch + development and mainline development occur in the same pieces of code, + resolving merge conflicts can take a lot of time. + +#. Other people in the community tend to ignore work on branches. + +#. Huge changes (produced when a branch is merged back onto mainline) are + extremely difficult to `code review`_. + +#. Branches are not routinely tested by our nightly tester infrastructure. + +#. Changes developed as monolithic large changes often don't work until the + entire set of changes is done. Breaking it down into a set of smaller + changes increases the odds that any of the work will be committed to the main + repository. + +To address these problems, LLVM uses an incremental development style and we +require contributors to follow this practice when making a large/invasive +change. Some tips: + +* Large/invasive changes usually have a number of secondary changes that are + required before the big change can be made (e.g. API cleanup, etc). These + sorts of changes can often be done before the major change is done, + independently of that work. + +* The remaining inter-related work should be decomposed into unrelated sets of + changes if possible. Once this is done, define the first increment and get + consensus on what the end goal of the change is. + +* Each change in the set can be stand alone (e.g. to fix a bug), or part of a + planned series of changes that works towards the development goal. + +* Each change should be kept as small as possible. This simplifies your work + (into a logical progression), simplifies code review and reduces the chance + that you will get negative feedback on the change. Small increments also + facilitate the maintenance of a high quality code base. + +* Often, an independent precursor to a big change is to add a new API and slowly + migrate clients to use the new API. Each change to use the new API is often + "obvious" and can be committed without review. Once the new API is in place + and used, it is much easier to replace the underlying implementation of the + API. This implementation change is logically separate from the API + change. + +If you are interested in making a large change, and this scares you, please make +sure to first `discuss the change/gather consensus`_ then ask about the best way +to go about making the change. + +Attribution of Changes +---------------------- + +We believe in correct attribution of contributions to their contributors. +However, we do not want the source code to be littered with random attributions +"this code written by J. Random Hacker" (this is noisy and distracting). In +practice, the revision control system keeps a perfect history of who changed +what, and the CREDITS.txt file describes higher-level contributions. If you +commit a patch for someone else, please say "patch contributed by J. Random +Hacker!" in the commit message. + +Overall, please do not add contributor names to the source code. + +.. _copyright-license-patents: + +Copyright, License, and Patents +=============================== + +.. note:: + + This section deals with legal matters but does not provide legal advice. We + are not lawyers --- please seek legal counsel from an attorney. + +This section addresses the issues of copyright, license and patents for the LLVM +project. The copyright for the code is held by the individual contributors of +the code and the terms of its license to LLVM users and developers is the +`University of Illinois/NCSA Open Source License +`_ (with portions dual licensed +under the `MIT License `_, +see below). As contributor to the LLVM project, you agree to allow any +contributions to the project to licensed under these terms. + +Copyright +--------- + +The LLVM project does not require copyright assignments, which means that the +copyright for the code in the project is held by its respective contributors who +have each agreed to release their contributed code under the terms of the `LLVM +License`_. + +An implication of this is that the LLVM license is unlikely to ever change: +changing it would require tracking down all the contributors to LLVM and getting +them to agree that a license change is acceptable for their contribution. Since +there are no plans to change the license, this is not a cause for concern. + +As a contributor to the project, this means that you (or your company) retain +ownership of the code you contribute, that it cannot be used in a way that +contradicts the license (which is a liberal BSD-style license), and that the +license for your contributions won't change without your approval in the +future. + +.. _LLVM License: + +License +------- + +We intend to keep LLVM perpetually open source and to use a liberal open source +license. **As a contributor to the project, you agree that any contributions be +licensed under the terms of the corresponding subproject.** All of the code in +LLVM is available under the `University of Illinois/NCSA Open Source License +`_, which boils down to +this: + +* You can freely distribute LLVM. +* You must retain the copyright notice if you redistribute LLVM. +* Binaries derived from LLVM must reproduce the copyright notice (e.g. in an + included readme file). +* You can't use our names to promote your LLVM derived products. +* There's no warranty on LLVM at all. + +We believe this fosters the widest adoption of LLVM because it **allows +commercial products to be derived from LLVM** with few restrictions and without +a requirement for making any derived works also open source (i.e. LLVM's +license is not a "copyleft" license like the GPL). We suggest that you read the +`License `_ if further +clarification is needed. + +In addition to the UIUC license, the runtime library components of LLVM +(**compiler_rt, libc++, and libclc**) are also licensed under the `MIT License +`_, which does not contain +the binary redistribution clause. As a user of these runtime libraries, it +means that you can choose to use the code under either license (and thus don't +need the binary redistribution clause), and as a contributor to the code that +you agree that any contributions to these libraries be licensed under both +licenses. We feel that this is important for runtime libraries, because they +are implicitly linked into applications and therefore should not subject those +applications to the binary redistribution clause. This also means that it is ok +to move code from (e.g.) libc++ to the LLVM core without concern, but that code +cannot be moved from the LLVM core to libc++ without the copyright owner's +permission. + +Note that the LLVM Project does distribute llvm-gcc and dragonegg, **which are +GPL.** This means that anything "linked" into llvm-gcc must itself be compatible +with the GPL, and must be releasable under the terms of the GPL. This implies +that **any code linked into llvm-gcc and distributed to others may be subject to +the viral aspects of the GPL** (for example, a proprietary code generator linked +into llvm-gcc must be made available under the GPL). This is not a problem for +code already distributed under a more liberal license (like the UIUC license), +and GPL-containing subprojects are kept in separate SVN repositories whose +LICENSE.txt files specifically indicate that they contain GPL code. + +We have no plans to change the license of LLVM. If you have questions or +comments about the license, please contact the `LLVM Developer's Mailing +List `_. + +Patents +------- + +To the best of our knowledge, LLVM does not infringe on any patents (we have +actually removed code from LLVM in the past that was found to infringe). Having +code in LLVM that infringes on patents would violate an important goal of the +project by making it hard or impossible to reuse the code for arbitrary purposes +(including commercial use). + +When contributing code, we expect contributors to notify us of any potential for +patent-related trouble with their changes (including from third parties). If +you or your employer own the rights to a patent and would like to contribute +code to LLVM that relies on it, we require that the copyright owner sign an +agreement that allows any other user of LLVM to freely use your patent. Please +contact the `oversight group `_ for more +details. diff --git a/docs/Dummy.html b/docs/Dummy.html new file mode 100644 index 00000000..e69de29b diff --git a/docs/ExceptionHandling.rst b/docs/ExceptionHandling.rst new file mode 100644 index 00000000..0a866075 --- /dev/null +++ b/docs/ExceptionHandling.rst @@ -0,0 +1,364 @@ +========================== +Exception Handling in LLVM +========================== + +.. contents:: + :local: + +Introduction +============ + +This document is the central repository for all information pertaining to +exception handling in LLVM. It describes the format that LLVM exception +handling information takes, which is useful for those interested in creating +front-ends or dealing directly with the information. Further, this document +provides specific examples of what exception handling information is used for in +C and C++. + +Itanium ABI Zero-cost Exception Handling +---------------------------------------- + +Exception handling for most programming languages is designed to recover from +conditions that rarely occur during general use of an application. To that end, +exception handling should not interfere with the main flow of an application's +algorithm by performing checkpointing tasks, such as saving the current pc or +register state. + +The Itanium ABI Exception Handling Specification defines a methodology for +providing outlying data in the form of exception tables without inlining +speculative exception handling code in the flow of an application's main +algorithm. Thus, the specification is said to add "zero-cost" to the normal +execution of an application. + +A more complete description of the Itanium ABI exception handling runtime +support of can be found at `Itanium C++ ABI: Exception Handling +`_. A description of the +exception frame format can be found at `Exception Frames +`_, +with details of the DWARF 4 specification at `DWARF 4 Standard +`_. A description for the C++ exception +table formats can be found at `Exception Handling Tables +`_. + +Setjmp/Longjmp Exception Handling +--------------------------------- + +Setjmp/Longjmp (SJLJ) based exception handling uses LLVM intrinsics +`llvm.eh.sjlj.setjmp`_ and `llvm.eh.sjlj.longjmp`_ to handle control flow for +exception handling. + +For each function which does exception processing --- be it ``try``/``catch`` +blocks or cleanups --- that function registers itself on a global frame +list. When exceptions are unwinding, the runtime uses this list to identify +which functions need processing. + +Landing pad selection is encoded in the call site entry of the function +context. The runtime returns to the function via `llvm.eh.sjlj.longjmp`_, where +a switch table transfers control to the appropriate landing pad based on the +index stored in the function context. + +In contrast to DWARF exception handling, which encodes exception regions and +frame information in out-of-line tables, SJLJ exception handling builds and +removes the unwind frame context at runtime. This results in faster exception +handling at the expense of slower execution when no exceptions are thrown. As +exceptions are, by their nature, intended for uncommon code paths, DWARF +exception handling is generally preferred to SJLJ. + +Overview +-------- + +When an exception is thrown in LLVM code, the runtime does its best to find a +handler suited to processing the circumstance. + +The runtime first attempts to find an *exception frame* corresponding to the +function where the exception was thrown. If the programming language supports +exception handling (e.g. C++), the exception frame contains a reference to an +exception table describing how to process the exception. If the language does +not support exception handling (e.g. C), or if the exception needs to be +forwarded to a prior activation, the exception frame contains information about +how to unwind the current activation and restore the state of the prior +activation. This process is repeated until the exception is handled. If the +exception is not handled and no activations remain, then the application is +terminated with an appropriate error message. + +Because different programming languages have different behaviors when handling +exceptions, the exception handling ABI provides a mechanism for +supplying *personalities*. An exception handling personality is defined by +way of a *personality function* (e.g. ``__gxx_personality_v0`` in C++), +which receives the context of the exception, an *exception structure* +containing the exception object type and value, and a reference to the exception +table for the current function. The personality function for the current +compile unit is specified in a *common exception frame*. + +The organization of an exception table is language dependent. For C++, an +exception table is organized as a series of code ranges defining what to do if +an exception occurs in that range. Typically, the information associated with a +range defines which types of exception objects (using C++ *type info*) that are +handled in that range, and an associated action that should take place. Actions +typically pass control to a *landing pad*. + +A landing pad corresponds roughly to the code found in the ``catch`` portion of +a ``try``/``catch`` sequence. When execution resumes at a landing pad, it +receives an *exception structure* and a *selector value* corresponding to the +*type* of exception thrown. The selector is then used to determine which *catch* +should actually process the exception. + +LLVM Code Generation +==================== + +From a C++ developer's perspective, exceptions are defined in terms of the +``throw`` and ``try``/``catch`` statements. In this section we will describe the +implementation of LLVM exception handling in terms of C++ examples. + +Throw +----- + +Languages that support exception handling typically provide a ``throw`` +operation to initiate the exception process. Internally, a ``throw`` operation +breaks down into two steps. + +#. A request is made to allocate exception space for an exception structure. + This structure needs to survive beyond the current activation. This structure + will contain the type and value of the object being thrown. + +#. A call is made to the runtime to raise the exception, passing the exception + structure as an argument. + +In C++, the allocation of the exception structure is done by the +``__cxa_allocate_exception`` runtime function. The exception raising is handled +by ``__cxa_throw``. The type of the exception is represented using a C++ RTTI +structure. + +Try/Catch +--------- + +A call within the scope of a *try* statement can potentially raise an +exception. In those circumstances, the LLVM C++ front-end replaces the call with +an ``invoke`` instruction. Unlike a call, the ``invoke`` has two potential +continuation points: + +#. where to continue when the call succeeds as per normal, and + +#. where to continue if the call raises an exception, either by a throw or the + unwinding of a throw + +The term used to define a the place where an ``invoke`` continues after an +exception is called a *landing pad*. LLVM landing pads are conceptually +alternative function entry points where an exception structure reference and a +type info index are passed in as arguments. The landing pad saves the exception +structure reference and then proceeds to select the catch block that corresponds +to the type info of the exception object. + +The LLVM :ref:`i_landingpad` is used to convey information about the landing +pad to the back end. For C++, the ``landingpad`` instruction returns a pointer +and integer pair corresponding to the pointer to the *exception structure* and +the *selector value* respectively. + +The ``landingpad`` instruction takes a reference to the personality function to +be used for this ``try``/``catch`` sequence. The remainder of the instruction is +a list of *cleanup*, *catch*, and *filter* clauses. The exception is tested +against the clauses sequentially from first to last. The selector value is a +positive number if the exception matched a type info, a negative number if it +matched a filter, and zero if it matched a cleanup. If nothing is matched, the +behavior of the program is `undefined`_. If a type info matched, then the +selector value is the index of the type info in the exception table, which can +be obtained using the `llvm.eh.typeid.for`_ intrinsic. + +Once the landing pad has the type info selector, the code branches to the code +for the first catch. The catch then checks the value of the type info selector +against the index of type info for that catch. Since the type info index is not +known until all the type infos have been gathered in the backend, the catch code +must call the `llvm.eh.typeid.for`_ intrinsic to determine the index for a given +type info. If the catch fails to match the selector then control is passed on to +the next catch. + +Finally, the entry and exit of catch code is bracketed with calls to +``__cxa_begin_catch`` and ``__cxa_end_catch``. + +* ``__cxa_begin_catch`` takes an exception structure reference as an argument + and returns the value of the exception object. + +* ``__cxa_end_catch`` takes no arguments. This function: + + #. Locates the most recently caught exception and decrements its handler + count, + + #. Removes the exception from the *caught* stack if the handler count goes to + zero, and + + #. Destroys the exception if the handler count goes to zero and the exception + was not re-thrown by throw. + + .. note:: + + a rethrow from within the catch may replace this call with a + ``__cxa_rethrow``. + +Cleanups +-------- + +A cleanup is extra code which needs to be run as part of unwinding a scope. C++ +destructors are a typical example, but other languages and language extensions +provide a variety of different kinds of cleanups. In general, a landing pad may +need to run arbitrary amounts of cleanup code before actually entering a catch +block. To indicate the presence of cleanups, a :ref:`i_landingpad` should have +a *cleanup* clause. Otherwise, the unwinder will not stop at the landing pad if +there are no catches or filters that require it to. + +.. note:: + + Do not allow a new exception to propagate out of the execution of a + cleanup. This can corrupt the internal state of the unwinder. Different + languages describe different high-level semantics for these situations: for + example, C++ requires that the process be terminated, whereas Ada cancels both + exceptions and throws a third. + +When all cleanups are finished, if the exception is not handled by the current +function, resume unwinding by calling the `resume +instruction `_, passing in the result of the +``landingpad`` instruction for the original landing pad. + +Throw Filters +------------- + +C++ allows the specification of which exception types may be thrown from a +function. To represent this, a top level landing pad may exist to filter out +invalid types. To express this in LLVM code the :ref:`i_landingpad` will have a +filter clause. The clause consists of an array of type infos. +``landingpad`` will return a negative value +if the exception does not match any of the type infos. If no match is found then +a call to ``__cxa_call_unexpected`` should be made, otherwise +``_Unwind_Resume``. Each of these functions requires a reference to the +exception structure. Note that the most general form of a ``landingpad`` +instruction can have any number of catch, cleanup, and filter clauses (though +having more than one cleanup is pointless). The LLVM C++ front-end can generate +such ``landingpad`` instructions due to inlining creating nested exception +handling scopes. + +.. _undefined: + +Restrictions +------------ + +The unwinder delegates the decision of whether to stop in a call frame to that +call frame's language-specific personality function. Not all unwinders guarantee +that they will stop to perform cleanups. For example, the GNU C++ unwinder +doesn't do so unless the exception is actually caught somewhere further up the +stack. + +In order for inlining to behave correctly, landing pads must be prepared to +handle selector results that they did not originally advertise. Suppose that a +function catches exceptions of type ``A``, and it's inlined into a function that +catches exceptions of type ``B``. The inliner will update the ``landingpad`` +instruction for the inlined landing pad to include the fact that ``B`` is also +caught. If that landing pad assumes that it will only be entered to catch an +``A``, it's in for a rude awakening. Consequently, landing pads must test for +the selector results they understand and then resume exception propagation with +the `resume instruction `_ if none of the conditions +match. + +Exception Handling Intrinsics +============================= + +In addition to the ``landingpad`` and ``resume`` instructions, LLVM uses several +intrinsic functions (name prefixed with ``llvm.eh``) to provide exception +handling information at various points in generated code. + +.. _llvm.eh.typeid.for: + +``llvm.eh.typeid.for`` +---------------------- + +.. code-block:: llvm + + i32 @llvm.eh.typeid.for(i8* %type_info) + + +This intrinsic returns the type info index in the exception table of the current +function. This value can be used to compare against the result of +``landingpad`` instruction. The single argument is a reference to a type info. + +.. _llvm.eh.sjlj.setjmp: + +``llvm.eh.sjlj.setjmp`` +----------------------- + +.. code-block:: llvm + + i32 @llvm.eh.sjlj.setjmp(i8* %setjmp_buf) + +For SJLJ based exception handling, this intrinsic forces register saving for the +current function and stores the address of the following instruction for use as +a destination address by `llvm.eh.sjlj.longjmp`_. The buffer format and the +overall functioning of this intrinsic is compatible with the GCC +``__builtin_setjmp`` implementation allowing code built with the clang and GCC +to interoperate. + +The single parameter is a pointer to a five word buffer in which the calling +context is saved. The front end places the frame pointer in the first word, and +the target implementation of this intrinsic should place the destination address +for a `llvm.eh.sjlj.longjmp`_ in the second word. The following three words are +available for use in a target-specific manner. + +.. _llvm.eh.sjlj.longjmp: + +``llvm.eh.sjlj.longjmp`` +------------------------ + +.. code-block:: llvm + + void @llvm.eh.sjlj.longjmp(i8* %setjmp_buf) + +For SJLJ based exception handling, the ``llvm.eh.sjlj.longjmp`` intrinsic is +used to implement ``__builtin_longjmp()``. The single parameter is a pointer to +a buffer populated by `llvm.eh.sjlj.setjmp`_. The frame pointer and stack +pointer are restored from the buffer, then control is transferred to the +destination address. + +``llvm.eh.sjlj.lsda`` +--------------------- + +.. code-block:: llvm + + i8* @llvm.eh.sjlj.lsda() + +For SJLJ based exception handling, the ``llvm.eh.sjlj.lsda`` intrinsic returns +the address of the Language Specific Data Area (LSDA) for the current +function. The SJLJ front-end code stores this address in the exception handling +function context for use by the runtime. + +``llvm.eh.sjlj.callsite`` +------------------------- + +.. code-block:: llvm + + void @llvm.eh.sjlj.callsite(i32 %call_site_num) + +For SJLJ based exception handling, the ``llvm.eh.sjlj.callsite`` intrinsic +identifies the callsite value associated with the following ``invoke`` +instruction. This is used to ensure that landing pad entries in the LSDA are +generated in matching order. + +Asm Table Formats +================= + +There are two tables that are used by the exception handling runtime to +determine which actions should be taken when an exception is thrown. + +Exception Handling Frame +------------------------ + +An exception handling frame ``eh_frame`` is very similar to the unwind frame +used by DWARF debug info. The frame contains all the information necessary to +tear down the current frame and restore the state of the prior frame. There is +an exception handling frame for each function in a compile unit, plus a common +exception handling frame that defines information common to all functions in the +unit. + +Exception Tables +---------------- + +An exception table contains information about what actions to take when an +exception is thrown in a particular part of a function's code. There is one +exception table per function, except leaf functions and functions that have +calls only to non-throwing functions. They do not need an exception table. diff --git a/docs/ExtendedIntegerResults.txt b/docs/ExtendedIntegerResults.txt new file mode 100644 index 00000000..44e9fbf0 --- /dev/null +++ b/docs/ExtendedIntegerResults.txt @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// Representing sign/zero extension of function results +//===----------------------------------------------------------------------===// + +Mar 25, 2009 - Initial Revision + +Most ABIs specify that functions which return small integers do so in a +specific integer GPR. This is an efficient way to go, but raises the question: +if the returned value is smaller than the register, what do the high bits hold? + +There are three (interesting) possible answers: undefined, zero extended, or +sign extended. The number of bits in question depends on the data-type that +the front-end is referencing (typically i1/i8/i16/i32). + +Knowing the answer to this is important for two reasons: 1) we want to be able +to implement the ABI correctly. If we need to sign extend the result according +to the ABI, we really really do need to do this to preserve correctness. 2) +this information is often useful for optimization purposes, and we want the +mid-level optimizers to be able to process this (e.g. eliminate redundant +extensions). + +For example, lets pretend that X86 requires the caller to properly extend the +result of a return (I'm not sure this is the case, but the argument doesn't +depend on this). Given this, we should compile this: + +int a(); +short b() { return a(); } + +into: + +_b: + subl $12, %esp + call L_a$stub + addl $12, %esp + cwtl + ret + +An optimization example is that we should be able to eliminate the explicit +sign extension in this example: + +short y(); +int z() { + return ((int)y() << 16) >> 16; +} + +_z: + subl $12, %esp + call _y + ;; movswl %ax, %eax -> not needed because eax is already sext'd + addl $12, %esp + ret + +//===----------------------------------------------------------------------===// +// What we have right now. +//===----------------------------------------------------------------------===// + +Currently, these sorts of things are modelled by compiling a function to return +the small type and a signext/zeroext marker is used. For example, we compile +Z into: + +define i32 @z() nounwind { +entry: + %0 = tail call signext i16 (...)* @y() nounwind + %1 = sext i16 %0 to i32 + ret i32 %1 +} + +and b into: + +define signext i16 @b() nounwind { +entry: + %0 = tail call i32 (...)* @a() nounwind ; [#uses=1] + %retval12 = trunc i32 %0 to i16 ; [#uses=1] + ret i16 %retval12 +} + +This has some problems: 1) the actual precise semantics are really poorly +defined (see PR3779). 2) some targets might want the caller to extend, some +might want the callee to extend 3) the mid-level optimizer doesn't know the +size of the GPR, so it doesn't know that %0 is sign extended up to 32-bits +here, and even if it did, it could not eliminate the sext. 4) the code +generator has historically assumed that the result is extended to i32, which is +a problem on PIC16 (and is also probably wrong on alpha and other 64-bit +targets). + +//===----------------------------------------------------------------------===// +// The proposal +//===----------------------------------------------------------------------===// + +I suggest that we have the front-end fully lower out the ABI issues here to +LLVM IR. This makes it 100% explicit what is going on and means that there is +no cause for confusion. For example, the cases above should compile into: + +define i32 @z() nounwind { +entry: + %0 = tail call i32 (...)* @y() nounwind + %1 = trunc i32 %0 to i16 + %2 = sext i16 %1 to i32 + ret i32 %2 +} +define i32 @b() nounwind { +entry: + %0 = tail call i32 (...)* @a() nounwind + %retval12 = trunc i32 %0 to i16 + %tmp = sext i16 %retval12 to i32 + ret i32 %tmp +} + +In this model, no functions will return an i1/i8/i16 (and on a x86-64 target +that extends results to i64, no i32). This solves the ambiguity issue, allows us +to fully describe all possible ABIs, and now allows the optimizers to reason +about and eliminate these extensions. + +The one thing that is missing is the ability for the front-end and optimizer to +specify/infer the guarantees provided by the ABI to allow other optimizations. +For example, in the y/z case, since y is known to return a sign extended value, +the trunc/sext in z should be eliminable. + +This can be done by introducing new sext/zext attributes which mean "I know +that the result of the function is sign extended at least N bits. Given this, +and given that it is stuck on the y function, the mid-level optimizer could +easily eliminate the extensions etc with existing functionality. + +The major disadvantage of doing this sort of thing is that it makes the ABI +lowering stuff even more explicit in the front-end, and that we would like to +eventually move to having the code generator do more of this work. However, +the sad truth of the matter is that this is a) unlikely to happen anytime in +the near future, and b) this is no worse than we have now with the existing +attributes. + +C compilers fundamentally have to reason about the target in many ways. +This is ugly and horrible, but a fact of life. + diff --git a/docs/ExtendingLLVM.rst b/docs/ExtendingLLVM.rst new file mode 100644 index 00000000..60cbf011 --- /dev/null +++ b/docs/ExtendingLLVM.rst @@ -0,0 +1,304 @@ +============================================================ +Extending LLVM: Adding instructions, intrinsics, types, etc. +============================================================ + +Introduction and Warning +======================== + + +During the course of using LLVM, you may wish to customize it for your research +project or for experimentation. At this point, you may realize that you need to +add something to LLVM, whether it be a new fundamental type, a new intrinsic +function, or a whole new instruction. + +When you come to this realization, stop and think. Do you really need to extend +LLVM? Is it a new fundamental capability that LLVM does not support at its +current incarnation or can it be synthesized from already pre-existing LLVM +elements? If you are not sure, ask on the `LLVM-dev +`_ list. The reason is that +extending LLVM will get involved as you need to update all the different passes +that you intend to use with your extension, and there are ``many`` LLVM analyses +and transformations, so it may be quite a bit of work. + +Adding an `intrinsic function`_ is far easier than adding an +instruction, and is transparent to optimization passes. If your added +functionality can be expressed as a function call, an intrinsic function is the +method of choice for LLVM extension. + +Before you invest a significant amount of effort into a non-trivial extension, +**ask on the list** if what you are looking to do can be done with +already-existing infrastructure, or if maybe someone else is already working on +it. You will save yourself a lot of time and effort by doing so. + +.. _intrinsic function: + +Adding a new intrinsic function +=============================== + +Adding a new intrinsic function to LLVM is much easier than adding a new +instruction. Almost all extensions to LLVM should start as an intrinsic +function and then be turned into an instruction if warranted. + +#. ``llvm/docs/LangRef.html``: + + Document the intrinsic. Decide whether it is code generator specific and + what the restrictions are. Talk to other people about it so that you are + sure it's a good idea. + +#. ``llvm/include/llvm/IR/Intrinsics*.td``: + + Add an entry for your intrinsic. Describe its memory access characteristics + for optimization (this controls whether it will be DCE'd, CSE'd, etc). Note + that any intrinsic using the ``llvm_int_ty`` type for an argument will + be deemed by ``tblgen`` as overloaded and the corresponding suffix will + be required on the intrinsic's name. + +#. ``llvm/lib/Analysis/ConstantFolding.cpp``: + + If it is possible to constant fold your intrinsic, add support to it in the + ``canConstantFoldCallTo`` and ``ConstantFoldCall`` functions. + +#. ``llvm/test/Regression/*``: + + Add test cases for your test cases to the test suite + +Once the intrinsic has been added to the system, you must add code generator +support for it. Generally you must do the following steps: + +Add support to the .td file for the target(s) of your choice in +``lib/Target/*/*.td``. + + This is usually a matter of adding a pattern to the .td file that matches the + intrinsic, though it may obviously require adding the instructions you want to + generate as well. There are lots of examples in the PowerPC and X86 backend + to follow. + +Adding a new SelectionDAG node +============================== + +As with intrinsics, adding a new SelectionDAG node to LLVM is much easier than +adding a new instruction. New nodes are often added to help represent +instructions common to many targets. These nodes often map to an LLVM +instruction (add, sub) or intrinsic (byteswap, population count). In other +cases, new nodes have been added to allow many targets to perform a common task +(converting between floating point and integer representation) or capture more +complicated behavior in a single node (rotate). + +#. ``include/llvm/CodeGen/ISDOpcodes.h``: + + Add an enum value for the new SelectionDAG node. + +#. ``lib/CodeGen/SelectionDAG/SelectionDAG.cpp``: + + Add code to print the node to ``getOperationName``. If your new node can be + evaluated at compile time when given constant arguments (such as an add of a + constant with another constant), find the ``getNode`` method that takes the + appropriate number of arguments, and add a case for your node to the switch + statement that performs constant folding for nodes that take the same number + of arguments as your new node. + +#. ``lib/CodeGen/SelectionDAG/LegalizeDAG.cpp``: + + Add code to `legalize, promote, and expand + `_ the node as necessary. At a + minimum, you will need to add a case statement for your node in + ``LegalizeOp`` which calls LegalizeOp on the node's operands, and returns a + new node if any of the operands changed as a result of being legalized. It + is likely that not all targets supported by the SelectionDAG framework will + natively support the new node. In this case, you must also add code in your + node's case statement in ``LegalizeOp`` to Expand your node into simpler, + legal operations. The case for ``ISD::UREM`` for expanding a remainder into + a divide, multiply, and a subtract is a good example. + +#. ``lib/CodeGen/SelectionDAG/LegalizeDAG.cpp``: + + If targets may support the new node being added only at certain sizes, you + will also need to add code to your node's case statement in ``LegalizeOp`` + to Promote your node's operands to a larger size, and perform the correct + operation. You will also need to add code to ``PromoteOp`` to do this as + well. For a good example, see ``ISD::BSWAP``, which promotes its operand to + a wider size, performs the byteswap, and then shifts the correct bytes right + to emulate the narrower byteswap in the wider type. + +#. ``lib/CodeGen/SelectionDAG/LegalizeDAG.cpp``: + + Add a case for your node in ``ExpandOp`` to teach the legalizer how to + perform the action represented by the new node on a value that has been split + into high and low halves. This case will be used to support your node with a + 64 bit operand on a 32 bit target. + +#. ``lib/CodeGen/SelectionDAG/DAGCombiner.cpp``: + + If your node can be combined with itself, or other existing nodes in a + peephole-like fashion, add a visit function for it, and call that function + from. There are several good examples for simple combines you can do; + ``visitFABS`` and ``visitSRL`` are good starting places. + +#. ``lib/Target/PowerPC/PPCISelLowering.cpp``: + + Each target has an implementation of the ``TargetLowering`` class, usually in + its own file (although some targets include it in the same file as the + DAGToDAGISel). The default behavior for a target is to assume that your new + node is legal for all types that are legal for that target. If this target + does not natively support your node, then tell the target to either Promote + it (if it is supported at a larger type) or Expand it. This will cause the + code you wrote in ``LegalizeOp`` above to decompose your new node into other + legal nodes for this target. + +#. ``lib/Target/TargetSelectionDAG.td``: + + Most current targets supported by LLVM generate code using the DAGToDAG + method, where SelectionDAG nodes are pattern matched to target-specific + nodes, which represent individual instructions. In order for the targets to + match an instruction to your new node, you must add a def for that node to + the list in this file, with the appropriate type constraints. Look at + ``add``, ``bswap``, and ``fadd`` for examples. + +#. ``lib/Target/PowerPC/PPCInstrInfo.td``: + + Each target has a tablegen file that describes the target's instruction set. + For targets that use the DAGToDAG instruction selection framework, add a + pattern for your new node that uses one or more target nodes. Documentation + for this is a bit sparse right now, but there are several decent examples. + See the patterns for ``rotl`` in ``PPCInstrInfo.td``. + +#. TODO: document complex patterns. + +#. ``llvm/test/Regression/CodeGen/*``: + + Add test cases for your new node to the test suite. + ``llvm/test/Regression/CodeGen/X86/bswap.ll`` is a good example. + +Adding a new instruction +======================== + +.. warning:: + + Adding instructions changes the bitcode format, and it will take some effort + to maintain compatibility with the previous version. Only add an instruction + if it is absolutely necessary. + +#. ``llvm/include/llvm/Instruction.def``: + + add a number for your instruction and an enum name + +#. ``llvm/include/llvm/Instructions.h``: + + add a definition for the class that will represent your instruction + +#. ``llvm/include/llvm/Support/InstVisitor.h``: + + add a prototype for a visitor to your new instruction type + +#. ``llvm/lib/AsmParser/Lexer.l``: + + add a new token to parse your instruction from assembly text file + +#. ``llvm/lib/AsmParser/llvmAsmParser.y``: + + add the grammar on how your instruction can be read and what it will + construct as a result + +#. ``llvm/lib/Bitcode/Reader/Reader.cpp``: + + add a case for your instruction and how it will be parsed from bitcode + +#. ``llvm/lib/VMCore/Instruction.cpp``: + + add a case for how your instruction will be printed out to assembly + +#. ``llvm/lib/VMCore/Instructions.cpp``: + + implement the class you defined in ``llvm/include/llvm/Instructions.h`` + +#. Test your instruction + +#. ``llvm/lib/Target/*``: + + add support for your instruction to code generators, or add a lowering pass. + +#. ``llvm/test/Regression/*``: + + add your test cases to the test suite. + +Also, you need to implement (or modify) any analyses or passes that you want to +understand this new instruction. + +Adding a new type +================= + +.. warning:: + + Adding new types changes the bitcode format, and will break compatibility with + currently-existing LLVM installations. Only add new types if it is absolutely + necessary. + +Adding a fundamental type +------------------------- + +#. ``llvm/include/llvm/Type.h``: + + add enum for the new type; add static ``Type*`` for this type + +#. ``llvm/lib/VMCore/Type.cpp``: + + add mapping from ``TypeID`` => ``Type*``; initialize the static ``Type*`` + +#. ``llvm/lib/AsmReader/Lexer.l``: + + add ability to parse in the type from text assembly + +#. ``llvm/lib/AsmReader/llvmAsmParser.y``: + + add a token for that type + +Adding a derived type +--------------------- + +#. ``llvm/include/llvm/Type.h``: + + add enum for the new type; add a forward declaration of the type also + +#. ``llvm/include/llvm/DerivedTypes.h``: + + add new class to represent new class in the hierarchy; add forward + declaration to the TypeMap value type + +#. ``llvm/lib/VMCore/Type.cpp``: + + add support for derived type to: + + .. code-block:: c++ + + std::string getTypeDescription(const Type &Ty, + std::vector &TypeStack) + bool TypesEqual(const Type *Ty, const Type *Ty2, + std::map &EqTypes) + + add necessary member functions for type, and factory methods + +#. ``llvm/lib/AsmReader/Lexer.l``: + + add ability to parse in the type from text assembly + +#. ``llvm/lib/Bitcode/Writer/Writer.cpp``: + + modify ``void BitcodeWriter::outputType(const Type *T)`` to serialize your + type + +#. ``llvm/lib/Bitcode/Reader/Reader.cpp``: + + modify ``const Type *BitcodeReader::ParseType()`` to read your data type + +#. ``llvm/lib/VMCore/AsmWriter.cpp``: + + modify + + .. code-block:: c++ + + void calcTypeName(const Type *Ty, + std::vector &TypeStack, + std::map &TypeNames, + std::string &Result) + + to output the new derived type diff --git a/docs/Extensions.rst b/docs/Extensions.rst new file mode 100644 index 00000000..e308dbcd --- /dev/null +++ b/docs/Extensions.rst @@ -0,0 +1,145 @@ +=============== +LLVM Extensions +=============== + +.. contents:: + :local: + +.. toctree:: + :hidden: + +Introduction +============ + +This document describes extensions to tools and formats LLVM seeks compatibility +with. + +General Assembly Syntax +=========================== + +C99-style Hexadecimal Floating-point Constants +---------------------------------------------- + +LLVM's assemblers allow floating-point constants to be written in C99's +hexadecimal format instead of decimal if desired. + +.. code-block:: gas + + .section .data + .float 0x1c2.2ap3 + +Machine-specific Assembly Syntax +================================ + +X86/COFF-Dependent +------------------ + +Relocations +^^^^^^^^^^^ + +The following additional relocation type is supported: + +**@IMGREL** (AT&T syntax only) generates an image-relative relocation that +corresponds to the COFF relocation types ``IMAGE_REL_I386_DIR32NB`` (32-bit) or +``IMAGE_REL_AMD64_ADDR32NB`` (64-bit). + +.. code-block:: gas + + .text + fun: + mov foo@IMGREL(%ebx, %ecx, 4), %eax + + .section .pdata + .long fun@IMGREL + .long (fun@imgrel + 0x3F) + .long $unwind$fun@imgrel + + +``.linkonce`` Directive +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: + + ``.linkonce [ comdat type [ section identifier ] ]`` + +Supported COMDAT types: + +``discard`` + Discards duplicate sections with the same COMDAT symbol. This is the default + if no type is specified. + +``one_only`` + If the symbol is defined multiple times, the linker issues an error. + +``same_size`` + Duplicates are discarded, but the linker issues an error if any have + different sizes. + +``same_contents`` + Duplicates are discarded, but the linker issues an error if any duplicates + do not have exactly the same content. + +``associative`` + Links the section if a certain other COMDAT section is linked. This other + section is indicated by its section identifier following the comdat type. + The following restrictions apply to the associated section: + + 1. It must be the name of a section already defined. + 2. It must differ from the current section. + 3. It must be a COMDAT section. + 4. It cannot be another associative COMDAT section. + +``largest`` + Links the largest section from among the duplicates. + +``newest`` + Links the newest section from among the duplicates. + + +.. code-block:: gas + + .section .text$foo + .linkonce + ... + + .section .xdata$foo + .linkonce associative .text$foo + ... + +``.section`` Directive +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MC supports passing the information in ``.linkonce`` at the end of +``.section``. For example, these two codes are equivalent + +.. code-block:: gas + + .section secName, "dr", discard, "Symbol1" + .globl Symbol1 + Symbol1: + .long 1 + +.. code-block:: gas + + .section secName, "dr" + .linkonce discard + .globl Symbol1 + Symbol1: + .long 1 + +Note that in the combined form the COMDAT symbol is explict. This +extension exits to support multiple sections with the same name in +different comdats: + + +.. code-block:: gas + + .section secName, "dr", discard, "Symbol1" + .globl Symbol1 + Symbol1: + .long 1 + + .section secName, "dr", discard, "Symbol2" + .globl Symbol2 + Symbol2: + .long 1 diff --git a/docs/FAQ.rst b/docs/FAQ.rst new file mode 100644 index 00000000..e4ab2c18 --- /dev/null +++ b/docs/FAQ.rst @@ -0,0 +1,485 @@ +================================ +Frequently Asked Questions (FAQ) +================================ + +.. contents:: + :local: + + +License +======= + +Does the University of Illinois Open Source License really qualify as an "open source" license? +----------------------------------------------------------------------------------------------- +Yes, the license is `certified +`_ by the Open Source +Initiative (OSI). + + +Can I modify LLVM source code and redistribute the modified source? +------------------------------------------------------------------- +Yes. The modified source distribution must retain the copyright notice and +follow the three bulletted conditions listed in the `LLVM license +`_. + + +Can I modify the LLVM source code and redistribute binaries or other tools based on it, without redistributing the source? +-------------------------------------------------------------------------------------------------------------------------- +Yes. This is why we distribute LLVM under a less restrictive license than GPL, +as explained in the first question above. + + +Source Code +=========== + +In what language is LLVM written? +--------------------------------- +All of the LLVM tools and libraries are written in C++ with extensive use of +the STL. + + +How portable is the LLVM source code? +------------------------------------- +The LLVM source code should be portable to most modern Unix-like operating +systems. Most of the code is written in standard C++ with operating system +services abstracted to a support library. The tools required to build and +test LLVM have been ported to a plethora of platforms. + +Some porting problems may exist in the following areas: + +* The autoconf/makefile build system relies heavily on UNIX shell tools, + like the Bourne Shell and sed. Porting to systems without these tools + (MacOS 9, Plan 9) will require more effort. + +What API do I use to store a value to one of the virtual registers in LLVM IR's SSA representation? +--------------------------------------------------------------------------------------------------- + +In short: you can't. It's actually kind of a silly question once you grok +what's going on. Basically, in code like: + +.. code-block:: llvm + + %result = add i32 %foo, %bar + +, ``%result`` is just a name given to the ``Value`` of the ``add`` +instruction. In other words, ``%result`` *is* the add instruction. The +"assignment" doesn't explicitly "store" anything to any "virtual register"; +the "``=``" is more like the mathematical sense of equality. + +Longer explanation: In order to generate a textual representation of the +IR, some kind of name has to be given to each instruction so that other +instructions can textually reference it. However, the isomorphic in-memory +representation that you manipulate from C++ has no such restriction since +instructions can simply keep pointers to any other ``Value``'s that they +reference. In fact, the names of dummy numbered temporaries like ``%1`` are +not explicitly represented in the in-memory representation at all (see +``Value::getName()``). + +Build Problems +============== + +When I run configure, it finds the wrong C compiler. +---------------------------------------------------- +The ``configure`` script attempts to locate first ``gcc`` and then ``cc``, +unless it finds compiler paths set in ``CC`` and ``CXX`` for the C and C++ +compiler, respectively. + +If ``configure`` finds the wrong compiler, either adjust your ``PATH`` +environment variable or set ``CC`` and ``CXX`` explicitly. + + +The ``configure`` script finds the right C compiler, but it uses the LLVM tools from a previous build. What do I do? +--------------------------------------------------------------------------------------------------------------------- +The ``configure`` script uses the ``PATH`` to find executables, so if it's +grabbing the wrong linker/assembler/etc, there are two ways to fix it: + +#. Adjust your ``PATH`` environment variable so that the correct program + appears first in the ``PATH``. This may work, but may not be convenient + when you want them *first* in your path for other work. + +#. Run ``configure`` with an alternative ``PATH`` that is correct. In a + Bourne compatible shell, the syntax would be: + +.. code-block:: console + + % PATH=[the path without the bad program] ./configure ... + +This is still somewhat inconvenient, but it allows ``configure`` to do its +work without having to adjust your ``PATH`` permanently. + + +When creating a dynamic library, I get a strange GLIBC error. +------------------------------------------------------------- +Under some operating systems (i.e. Linux), libtool does not work correctly if +GCC was compiled with the ``--disable-shared option``. To work around this, +install your own version of GCC that has shared libraries enabled by default. + + +I've updated my source tree from Subversion, and now my build is trying to use a file/directory that doesn't exist. +------------------------------------------------------------------------------------------------------------------- +You need to re-run configure in your object directory. When new Makefiles +are added to the source tree, they have to be copied over to the object tree +in order to be used by the build. + + +I've modified a Makefile in my source tree, but my build tree keeps using the old version. What do I do? +--------------------------------------------------------------------------------------------------------- +If the Makefile already exists in your object tree, you can just run the +following command in the top level directory of your object tree: + +.. code-block:: console + + % ./config.status ; + +If the Makefile is new, you will have to modify the configure script to copy +it over. + + +I've upgraded to a new version of LLVM, and I get strange build errors. +----------------------------------------------------------------------- +Sometimes, changes to the LLVM source code alters how the build system works. +Changes in ``libtool``, ``autoconf``, or header file dependencies are +especially prone to this sort of problem. + +The best thing to try is to remove the old files and re-build. In most cases, +this takes care of the problem. To do this, just type ``make clean`` and then +``make`` in the directory that fails to build. + + +I've built LLVM and am testing it, but the tests freeze. +-------------------------------------------------------- +This is most likely occurring because you built a profile or release +(optimized) build of LLVM and have not specified the same information on the +``gmake`` command line. + +For example, if you built LLVM with the command: + +.. code-block:: console + + % gmake ENABLE_PROFILING=1 + +...then you must run the tests with the following commands: + +.. code-block:: console + + % cd llvm/test + % gmake ENABLE_PROFILING=1 + +Why do test results differ when I perform different types of builds? +-------------------------------------------------------------------- +The LLVM test suite is dependent upon several features of the LLVM tools and +libraries. + +First, the debugging assertions in code are not enabled in optimized or +profiling builds. Hence, tests that used to fail may pass. + +Second, some tests may rely upon debugging options or behavior that is only +available in the debug build. These tests will fail in an optimized or +profile build. + + +Compiling LLVM with GCC 3.3.2 fails, what should I do? +------------------------------------------------------ +This is `a bug in GCC `_, +and affects projects other than LLVM. Try upgrading or downgrading your GCC. + + +Compiling LLVM with GCC succeeds, but the resulting tools do not work, what can be wrong? +----------------------------------------------------------------------------------------- +Several versions of GCC have shown a weakness in miscompiling the LLVM +codebase. Please consult your compiler version (``gcc --version``) to find +out whether it is `broken `_. If so, your only +option is to upgrade GCC to a known good version. + + +After Subversion update, rebuilding gives the error "No rule to make target". +----------------------------------------------------------------------------- +If the error is of the form: + +.. code-block:: console + + gmake[2]: *** No rule to make target `/path/to/somefile', + needed by `/path/to/another/file.d'. + Stop. + +This may occur anytime files are moved within the Subversion repository or +removed entirely. In this case, the best solution is to erase all ``.d`` +files, which list dependencies for source files, and rebuild: + +.. code-block:: console + + % cd $LLVM_OBJ_DIR + % rm -f `find . -name \*\.d` + % gmake + +In other cases, it may be necessary to run ``make clean`` before rebuilding. + + +Source Languages +================ + +What source languages are supported? +------------------------------------ +LLVM currently has full support for C and C++ source languages. These are +available through both `Clang `_ and `DragonEgg +`_. + +The PyPy developers are working on integrating LLVM into the PyPy backend so +that PyPy language can translate to LLVM. + + +I'd like to write a self-hosting LLVM compiler. How should I interface with the LLVM middle-end optimizers and back-end code generators? +---------------------------------------------------------------------------------------------------------------------------------------- +Your compiler front-end will communicate with LLVM by creating a module in the +LLVM intermediate representation (IR) format. Assuming you want to write your +language's compiler in the language itself (rather than C++), there are 3 +major ways to tackle generating LLVM IR from a front-end: + +1. **Call into the LLVM libraries code using your language's FFI (foreign + function interface).** + + * *for:* best tracks changes to the LLVM IR, .ll syntax, and .bc format + + * *for:* enables running LLVM optimization passes without a emit/parse + overhead + + * *for:* adapts well to a JIT context + + * *against:* lots of ugly glue code to write + +2. **Emit LLVM assembly from your compiler's native language.** + + * *for:* very straightforward to get started + + * *against:* the .ll parser is slower than the bitcode reader when + interfacing to the middle end + + * *against:* it may be harder to track changes to the IR + +3. **Emit LLVM bitcode from your compiler's native language.** + + * *for:* can use the more-efficient bitcode reader when interfacing to the + middle end + + * *against:* you'll have to re-engineer the LLVM IR object model and bitcode + writer in your language + + * *against:* it may be harder to track changes to the IR + +If you go with the first option, the C bindings in include/llvm-c should help +a lot, since most languages have strong support for interfacing with C. The +most common hurdle with calling C from managed code is interfacing with the +garbage collector. The C interface was designed to require very little memory +management, and so is straightforward in this regard. + +What support is there for a higher level source language constructs for building a compiler? +-------------------------------------------------------------------------------------------- +Currently, there isn't much. LLVM supports an intermediate representation +which is useful for code representation but will not support the high level +(abstract syntax tree) representation needed by most compilers. There are no +facilities for lexical nor semantic analysis. + + +I don't understand the ``GetElementPtr`` instruction. Help! +----------------------------------------------------------- +See `The Often Misunderstood GEP Instruction `_. + + +Using the C and C++ Front Ends +============================== + +Can I compile C or C++ code to platform-independent LLVM bitcode? +----------------------------------------------------------------- +No. C and C++ are inherently platform-dependent languages. The most obvious +example of this is the preprocessor. A very common way that C code is made +portable is by using the preprocessor to include platform-specific code. In +practice, information about other platforms is lost after preprocessing, so +the result is inherently dependent on the platform that the preprocessing was +targeting. + +Another example is ``sizeof``. It's common for ``sizeof(long)`` to vary +between platforms. In most C front-ends, ``sizeof`` is expanded to a +constant immediately, thus hard-wiring a platform-specific detail. + +Also, since many platforms define their ABIs in terms of C, and since LLVM is +lower-level than C, front-ends currently must emit platform-specific IR in +order to have the result conform to the platform ABI. + + +Questions about code generated by the demo page +=============================================== + +What is this ``llvm.global_ctors`` and ``_GLOBAL__I_a...`` stuff that happens when I ``#include ``? +------------------------------------------------------------------------------------------------------------- +If you ``#include`` the ```` header into a C++ translation unit, +the file will probably use the ``std::cin``/``std::cout``/... global objects. +However, C++ does not guarantee an order of initialization between static +objects in different translation units, so if a static ctor/dtor in your .cpp +file used ``std::cout``, for example, the object would not necessarily be +automatically initialized before your use. + +To make ``std::cout`` and friends work correctly in these scenarios, the STL +that we use declares a static object that gets created in every translation +unit that includes ````. This object has a static constructor +and destructor that initializes and destroys the global iostream objects +before they could possibly be used in the file. The code that you see in the +``.ll`` file corresponds to the constructor and destructor registration code. + +If you would like to make it easier to *understand* the LLVM code generated +by the compiler in the demo page, consider using ``printf()`` instead of +``iostream``\s to print values. + + +Where did all of my code go?? +----------------------------- +If you are using the LLVM demo page, you may often wonder what happened to +all of the code that you typed in. Remember that the demo script is running +the code through the LLVM optimizers, so if your code doesn't actually do +anything useful, it might all be deleted. + +To prevent this, make sure that the code is actually needed. For example, if +you are computing some expression, return the value from the function instead +of leaving it in a local variable. If you really want to constrain the +optimizer, you can read from and assign to ``volatile`` global variables. + + +What is this "``undef``" thing that shows up in my code? +-------------------------------------------------------- +``undef`` is the LLVM way of representing a value that is not defined. You +can get these if you do not initialize a variable before you use it. For +example, the C function: + +.. code-block:: c + + int X() { int i; return i; } + +Is compiled to "``ret i32 undef``" because "``i``" never has a value specified +for it. + + +Why does instcombine + simplifycfg turn a call to a function with a mismatched calling convention into "unreachable"? Why not make the verifier reject it? +---------------------------------------------------------------------------------------------------------------------------------------------------------- +This is a common problem run into by authors of front-ends that are using +custom calling conventions: you need to make sure to set the right calling +convention on both the function and on each call to the function. For +example, this code: + +.. code-block:: llvm + + define fastcc void @foo() { + ret void + } + define void @bar() { + call void @foo() + ret void + } + +Is optimized to: + +.. code-block:: llvm + + define fastcc void @foo() { + ret void + } + define void @bar() { + unreachable + } + +... with "``opt -instcombine -simplifycfg``". This often bites people because +"all their code disappears". Setting the calling convention on the caller and +callee is required for indirect calls to work, so people often ask why not +make the verifier reject this sort of thing. + +The answer is that this code has undefined behavior, but it is not illegal. +If we made it illegal, then every transformation that could potentially create +this would have to ensure that it doesn't, and there is valid code that can +create this sort of construct (in dead code). The sorts of things that can +cause this to happen are fairly contrived, but we still need to accept them. +Here's an example: + +.. code-block:: llvm + + define fastcc void @foo() { + ret void + } + define internal void @bar(void()* %FP, i1 %cond) { + br i1 %cond, label %T, label %F + T: + call void %FP() + ret void + F: + call fastcc void %FP() + ret void + } + define void @test() { + %X = or i1 false, false + call void @bar(void()* @foo, i1 %X) + ret void + } + +In this example, "test" always passes ``@foo``/``false`` into ``bar``, which +ensures that it is dynamically called with the right calling conv (thus, the +code is perfectly well defined). If you run this through the inliner, you +get this (the explicit "or" is there so that the inliner doesn't dead code +eliminate a bunch of stuff): + +.. code-block:: llvm + + define fastcc void @foo() { + ret void + } + define void @test() { + %X = or i1 false, false + br i1 %X, label %T.i, label %F.i + T.i: + call void @foo() + br label %bar.exit + F.i: + call fastcc void @foo() + br label %bar.exit + bar.exit: + ret void + } + +Here you can see that the inlining pass made an undefined call to ``@foo`` +with the wrong calling convention. We really don't want to make the inliner +have to know about this sort of thing, so it needs to be valid code. In this +case, dead code elimination can trivially remove the undefined code. However, +if ``%X`` was an input argument to ``@test``, the inliner would produce this: + +.. code-block:: llvm + + define fastcc void @foo() { + ret void + } + + define void @test(i1 %X) { + br i1 %X, label %T.i, label %F.i + T.i: + call void @foo() + br label %bar.exit + F.i: + call fastcc void @foo() + br label %bar.exit + bar.exit: + ret void + } + +The interesting thing about this is that ``%X`` *must* be false for the +code to be well-defined, but no amount of dead code elimination will be able +to delete the broken call as unreachable. However, since +``instcombine``/``simplifycfg`` turns the undefined call into unreachable, we +end up with a branch on a condition that goes to unreachable: a branch to +unreachable can never happen, so "``-inline -instcombine -simplifycfg``" is +able to produce: + +.. code-block:: llvm + + define fastcc void @foo() { + ret void + } + define void @test(i1 %X) { + F.i: + call fastcc void @foo() + ret void + } diff --git a/docs/GarbageCollection.rst b/docs/GarbageCollection.rst new file mode 100644 index 00000000..73bc5eeb --- /dev/null +++ b/docs/GarbageCollection.rst @@ -0,0 +1,1015 @@ +===================================== +Accurate Garbage Collection with LLVM +===================================== + +.. contents:: + :local: + +Introduction +============ + +Garbage collection is a widely used technique that frees the programmer from +having to know the lifetimes of heap objects, making software easier to produce +and maintain. Many programming languages rely on garbage collection for +automatic memory management. There are two primary forms of garbage collection: +conservative and accurate. + +Conservative garbage collection often does not require any special support from +either the language or the compiler: it can handle non-type-safe programming +languages (such as C/C++) and does not require any special information from the +compiler. The `Boehm collector +`__ is an example of a +state-of-the-art conservative collector. + +Accurate garbage collection requires the ability to identify all pointers in the +program at run-time (which requires that the source-language be type-safe in +most cases). Identifying pointers at run-time requires compiler support to +locate all places that hold live pointer variables at run-time, including the +:ref:`processor stack and registers `. + +Conservative garbage collection is attractive because it does not require any +special compiler support, but it does have problems. In particular, because the +conservative garbage collector cannot *know* that a particular word in the +machine is a pointer, it cannot move live objects in the heap (preventing the +use of compacting and generational GC algorithms) and it can occasionally suffer +from memory leaks due to integer values that happen to point to objects in the +program. In addition, some aggressive compiler transformations can break +conservative garbage collectors (though these seem rare in practice). + +Accurate garbage collectors do not suffer from any of these problems, but they +can suffer from degraded scalar optimization of the program. In particular, +because the runtime must be able to identify and update all pointers active in +the program, some optimizations are less effective. In practice, however, the +locality and performance benefits of using aggressive garbage collection +techniques dominates any low-level losses. + +This document describes the mechanisms and interfaces provided by LLVM to +support accurate garbage collection. + +Goals and non-goals +------------------- + +LLVM's intermediate representation provides :ref:`garbage collection intrinsics +` that offer support for a broad class of collector models. For +instance, the intrinsics permit: + +* semi-space collectors + +* mark-sweep collectors + +* generational collectors + +* reference counting + +* incremental collectors + +* concurrent collectors + +* cooperative collectors + +We hope that the primitive support built into the LLVM IR is sufficient to +support a broad class of garbage collected languages including Scheme, ML, Java, +C#, Perl, Python, Lua, Ruby, other scripting languages, and more. + +However, LLVM does not itself provide a garbage collector --- this should be +part of your language's runtime library. LLVM provides a framework for compile +time :ref:`code generation plugins `. The role of these plugins is to +generate code and data structures which conforms to the *binary interface* +specified by the *runtime library*. This is similar to the relationship between +LLVM and DWARF debugging info, for example. The difference primarily lies in +the lack of an established standard in the domain of garbage collection --- thus +the plugins. + +The aspects of the binary interface with which LLVM's GC support is +concerned are: + +* Creation of GC-safe points within code where collection is allowed to execute + safely. + +* Computation of the stack map. For each safe point in the code, object + references within the stack frame must be identified so that the collector may + traverse and perhaps update them. + +* Write barriers when storing object references to the heap. These are commonly + used to optimize incremental scans in generational collectors. + +* Emission of read barriers when loading object references. These are useful + for interoperating with concurrent collectors. + +There are additional areas that LLVM does not directly address: + +* Registration of global roots with the runtime. + +* Registration of stack map entries with the runtime. + +* The functions used by the program to allocate memory, trigger a collection, + etc. + +* Computation or compilation of type maps, or registration of them with the + runtime. These are used to crawl the heap for object references. + +In general, LLVM's support for GC does not include features which can be +adequately addressed with other features of the IR and does not specify a +particular binary interface. On the plus side, this means that you should be +able to integrate LLVM with an existing runtime. On the other hand, it leaves a +lot of work for the developer of a novel language. However, it's easy to get +started quickly and scale up to a more sophisticated implementation as your +compiler matures. + +Getting started +=============== + +Using a GC with LLVM implies many things, for example: + +* Write a runtime library or find an existing one which implements a GC heap. + + #. Implement a memory allocator. + + #. Design a binary interface for the stack map, used to identify references + within a stack frame on the machine stack.\* + + #. Implement a stack crawler to discover functions on the call stack.\* + + #. Implement a registry for global roots. + + #. Design a binary interface for type maps, used to identify references + within heap objects. + + #. Implement a collection routine bringing together all of the above. + +* Emit compatible code from your compiler. + + * Initialization in the main function. + + * Use the ``gc "..."`` attribute to enable GC code generation (or + ``F.setGC("...")``). + + * Use ``@llvm.gcroot`` to mark stack roots. + + * Use ``@llvm.gcread`` and/or ``@llvm.gcwrite`` to manipulate GC references, + if necessary. + + * Allocate memory using the GC allocation routine provided by the runtime + library. + + * Generate type maps according to your runtime's binary interface. + +* Write a compiler plugin to interface LLVM with the runtime library.\* + + * Lower ``@llvm.gcread`` and ``@llvm.gcwrite`` to appropriate code + sequences.\* + + * Compile LLVM's stack map to the binary form expected by the runtime. + +* Load the plugin into the compiler. Use ``llc -load`` or link the plugin + statically with your language's compiler.\* + +* Link program executables with the runtime. + +To help with several of these tasks (those indicated with a \*), LLVM includes a +highly portable, built-in ShadowStack code generator. It is compiled into +``llc`` and works even with the interpreter and C backends. + +In your compiler +---------------- + +To turn the shadow stack on for your functions, first call: + +.. code-block:: c++ + + F.setGC("shadow-stack"); + +for each function your compiler emits. Since the shadow stack is built into +LLVM, you do not need to load a plugin. + +Your compiler must also use ``@llvm.gcroot`` as documented. Don't forget to +create a root for each intermediate value that is generated when evaluating an +expression. In ``h(f(), g())``, the result of ``f()`` could easily be collected +if evaluating ``g()`` triggers a collection. + +There's no need to use ``@llvm.gcread`` and ``@llvm.gcwrite`` over plain +``load`` and ``store`` for now. You will need them when switching to a more +advanced GC. + +In your runtime +--------------- + +The shadow stack doesn't imply a memory allocation algorithm. A semispace +collector or building atop ``malloc`` are great places to start, and can be +implemented with very little code. + +When it comes time to collect, however, your runtime needs to traverse the stack +roots, and for this it needs to integrate with the shadow stack. Luckily, doing +so is very simple. (This code is heavily commented to help you understand the +data structure, but there are only 20 lines of meaningful code.) + +.. code-block:: c++ + + /// @brief The map for a single function's stack frame. One of these is + /// compiled as constant data into the executable for each function. + /// + /// Storage of metadata values is elided if the %metadata parameter to + /// @llvm.gcroot is null. + struct FrameMap { + int32_t NumRoots; //< Number of roots in stack frame. + int32_t NumMeta; //< Number of metadata entries. May be < NumRoots. + const void *Meta[0]; //< Metadata for each root. + }; + + /// @brief A link in the dynamic shadow stack. One of these is embedded in + /// the stack frame of each function on the call stack. + struct StackEntry { + StackEntry *Next; //< Link to next stack entry (the caller's). + const FrameMap *Map; //< Pointer to constant FrameMap. + void *Roots[0]; //< Stack roots (in-place array). + }; + + /// @brief The head of the singly-linked list of StackEntries. Functions push + /// and pop onto this in their prologue and epilogue. + /// + /// Since there is only a global list, this technique is not threadsafe. + StackEntry *llvm_gc_root_chain; + + /// @brief Calls Visitor(root, meta) for each GC root on the stack. + /// root and meta are exactly the values passed to + /// @llvm.gcroot. + /// + /// Visitor could be a function to recursively mark live objects. Or it + /// might copy them to another heap or generation. + /// + /// @param Visitor A function to invoke for every GC root on the stack. + void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) { + for (StackEntry *R = llvm_gc_root_chain; R; R = R->Next) { + unsigned i = 0; + + // For roots [0, NumMeta), the metadata pointer is in the FrameMap. + for (unsigned e = R->Map->NumMeta; i != e; ++i) + Visitor(&R->Roots[i], R->Map->Meta[i]); + + // For roots [NumMeta, NumRoots), the metadata pointer is null. + for (unsigned e = R->Map->NumRoots; i != e; ++i) + Visitor(&R->Roots[i], NULL); + } + } + +About the shadow stack +---------------------- + +Unlike many GC algorithms which rely on a cooperative code generator to compile +stack maps, this algorithm carefully maintains a linked list of stack roots +[:ref:`Henderson2002 `]. This so-called "shadow stack" mirrors the +machine stack. Maintaining this data structure is slower than using a stack map +compiled into the executable as constant data, but has a significant portability +advantage because it requires no special support from the target code generator, +and does not require tricky platform-specific code to crawl the machine stack. + +The tradeoff for this simplicity and portability is: + +* High overhead per function call. + +* Not thread-safe. + +Still, it's an easy way to get started. After your compiler and runtime are up +and running, writing a :ref:`plugin ` will allow you to take advantage +of :ref:`more advanced GC features ` of LLVM in order to +improve performance. + +.. _gc_intrinsics: + +IR features +=========== + +This section describes the garbage collection facilities provided by the +:doc:`LLVM intermediate representation `. The exact behavior of these +IR features is specified by the binary interface implemented by a :ref:`code +generation plugin `, not by this document. + +These facilities are limited to those strictly necessary; they are not intended +to be a complete interface to any garbage collector. A program will need to +interface with the GC library using the facilities provided by that program. + +Specifying GC code generation: ``gc "..."`` +------------------------------------------- + +.. code-block:: llvm + + define ty @name(...) gc "name" { ... + +The ``gc`` function attribute is used to specify the desired GC style to the +compiler. Its programmatic equivalent is the ``setGC`` method of ``Function``. + +Setting ``gc "name"`` on a function triggers a search for a matching code +generation plugin "*name*"; it is that plugin which defines the exact nature of +the code generated to support GC. If none is found, the compiler will raise an +error. + +Specifying the GC style on a per-function basis allows LLVM to link together +programs that use different garbage collection algorithms (or none at all). + +.. _gcroot: + +Identifying GC roots on the stack: ``llvm.gcroot`` +-------------------------------------------------- + +.. code-block:: llvm + + void @llvm.gcroot(i8** %ptrloc, i8* %metadata) + +The ``llvm.gcroot`` intrinsic is used to inform LLVM that a stack variable +references an object on the heap and is to be tracked for garbage collection. +The exact impact on generated code is specified by a :ref:`compiler plugin +`. All calls to ``llvm.gcroot`` **must** reside inside the first basic +block. + +A compiler which uses mem2reg to raise imperative code using ``alloca`` into SSA +form need only add a call to ``@llvm.gcroot`` for those variables which a +pointers into the GC heap. + +It is also important to mark intermediate values with ``llvm.gcroot``. For +example, consider ``h(f(), g())``. Beware leaking the result of ``f()`` in the +case that ``g()`` triggers a collection. Note, that stack variables must be +initialized and marked with ``llvm.gcroot`` in function's prologue. + +The first argument **must** be a value referring to an alloca instruction or a +bitcast of an alloca. The second contains a pointer to metadata that should be +associated with the pointer, and **must** be a constant or global value +address. If your target collector uses tags, use a null pointer for metadata. + +The ``%metadata`` argument can be used to avoid requiring heap objects to have +'isa' pointers or tag bits. [Appel89_, Goldberg91_, Tolmach94_] If specified, +its value will be tracked along with the location of the pointer in the stack +frame. + +Consider the following fragment of Java code: + +.. code-block:: java + + { + Object X; // A null-initialized reference to an object + ... + } + +This block (which may be located in the middle of a function or in a loop nest), +could be compiled to this LLVM code: + +.. code-block:: llvm + + Entry: + ;; In the entry block for the function, allocate the + ;; stack space for X, which is an LLVM pointer. + %X = alloca %Object* + + ;; Tell LLVM that the stack space is a stack root. + ;; Java has type-tags on objects, so we pass null as metadata. + %tmp = bitcast %Object** %X to i8** + call void @llvm.gcroot(i8** %tmp, i8* null) + ... + + ;; "CodeBlock" is the block corresponding to the start + ;; of the scope above. + CodeBlock: + ;; Java null-initializes pointers. + store %Object* null, %Object** %X + + ... + + ;; As the pointer goes out of scope, store a null value into + ;; it, to indicate that the value is no longer live. + store %Object* null, %Object** %X + ... + +Reading and writing references in the heap +------------------------------------------ + +Some collectors need to be informed when the mutator (the program that needs +garbage collection) either reads a pointer from or writes a pointer to a field +of a heap object. The code fragments inserted at these points are called *read +barriers* and *write barriers*, respectively. The amount of code that needs to +be executed is usually quite small and not on the critical path of any +computation, so the overall performance impact of the barrier is tolerable. + +Barriers often require access to the *object pointer* rather than the *derived +pointer* (which is a pointer to the field within the object). Accordingly, +these intrinsics take both pointers as separate arguments for completeness. In +this snippet, ``%object`` is the object pointer, and ``%derived`` is the derived +pointer: + +.. code-block:: llvm + + ;; An array type. + %class.Array = type { %class.Object, i32, [0 x %class.Object*] } + ... + + ;; Load the object pointer from a gcroot. + %object = load %class.Array** %object_addr + + ;; Compute the derived pointer. + %derived = getelementptr %object, i32 0, i32 2, i32 %n + +LLVM does not enforce this relationship between the object and derived pointer +(although a :ref:`plugin ` might). However, it would be an unusual +collector that violated it. + +The use of these intrinsics is naturally optional if the target GC does require +the corresponding barrier. Such a GC plugin will replace the intrinsic calls +with the corresponding ``load`` or ``store`` instruction if they are used. + +Write barrier: ``llvm.gcwrite`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + void @llvm.gcwrite(i8* %value, i8* %object, i8** %derived) + +For write barriers, LLVM provides the ``llvm.gcwrite`` intrinsic function. It +has exactly the same semantics as a non-volatile ``store`` to the derived +pointer (the third argument). The exact code generated is specified by a +compiler :ref:`plugin `. + +Many important algorithms require write barriers, including generational and +concurrent collectors. Additionally, write barriers could be used to implement +reference counting. + +Read barrier: ``llvm.gcread`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + i8* @llvm.gcread(i8* %object, i8** %derived) + +For read barriers, LLVM provides the ``llvm.gcread`` intrinsic function. It has +exactly the same semantics as a non-volatile ``load`` from the derived pointer +(the second argument). The exact code generated is specified by a +:ref:`compiler plugin `. + +Read barriers are needed by fewer algorithms than write barriers, and may have a +greater performance impact since pointer reads are more frequent than writes. + +.. _plugin: + +Implementing a collector plugin +=============================== + +User code specifies which GC code generation to use with the ``gc`` function +attribute or, equivalently, with the ``setGC`` method of ``Function``. + +To implement a GC plugin, it is necessary to subclass ``llvm::GCStrategy``, +which can be accomplished in a few lines of boilerplate code. LLVM's +infrastructure provides access to several important algorithms. For an +uncontroversial collector, all that remains may be to compile LLVM's computed +stack map to assembly code (using the binary representation expected by the +runtime library). This can be accomplished in about 100 lines of code. + +This is not the appropriate place to implement a garbage collected heap or a +garbage collector itself. That code should exist in the language's runtime +library. The compiler plugin is responsible for generating code which conforms +to the binary interface defined by library, most essentially the :ref:`stack map +`. + +To subclass ``llvm::GCStrategy`` and register it with the compiler: + +.. code-block:: c++ + + // lib/MyGC/MyGC.cpp - Example LLVM GC plugin + + #include "llvm/CodeGen/GCStrategy.h" + #include "llvm/CodeGen/GCMetadata.h" + #include "llvm/Support/Compiler.h" + + using namespace llvm; + + namespace { + class LLVM_LIBRARY_VISIBILITY MyGC : public GCStrategy { + public: + MyGC() {} + }; + + GCRegistry::Add + X("mygc", "My bespoke garbage collector."); + } + +This boilerplate collector does nothing. More specifically: + +* ``llvm.gcread`` calls are replaced with the corresponding ``load`` + instruction. + +* ``llvm.gcwrite`` calls are replaced with the corresponding ``store`` + instruction. + +* No safe points are added to the code. + +* The stack map is not compiled into the executable. + +Using the LLVM makefiles (like the `sample project +`__), this code +can be compiled as a plugin using a simple makefile: + +.. code-block:: make + + # lib/MyGC/Makefile + + LEVEL := ../.. + LIBRARYNAME = MyGC + LOADABLE_MODULE = 1 + + include $(LEVEL)/Makefile.common + +Once the plugin is compiled, code using it may be compiled using ``llc +-load=MyGC.so`` (though MyGC.so may have some other platform-specific +extension): + +:: + + $ cat sample.ll + define void @f() gc "mygc" { + entry: + ret void + } + $ llvm-as < sample.ll | llc -load=MyGC.so + +It is also possible to statically link the collector plugin into tools, such as +a language-specific compiler front-end. + +.. _collector-algos: + +Overview of available features +------------------------------ + +``GCStrategy`` provides a range of features through which a plugin may do useful +work. Some of these are callbacks, some are algorithms that can be enabled, +disabled, or customized. This matrix summarizes the supported (and planned) +features and correlates them with the collection techniques which typically +require them. + +.. |v| unicode:: 0x2714 + :trim: + +.. |x| unicode:: 0x2718 + :trim: + ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| Algorithm | Done | Shadow | refcount | mark- | copying | incremental | threaded | concurrent | +| | | stack | | sweep | | | | | ++============+======+========+==========+=======+=========+=============+==========+============+ +| stack map | |v| | | | |x| | |x| | |x| | |x| | |x| | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| initialize | |v| | |x| | |x| | |x| | |x| | |x| | |x| | |x| | +| roots | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| derived | NO | | | | | | **N**\* | **N**\* | +| pointers | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| **custom | |v| | | | | | | | | +| lowering** | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *gcroot* | |v| | |x| | |x| | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *gcwrite* | |v| | | |x| | | | |x| | | |x| | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *gcread* | |v| | | | | | | | |x| | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| **safe | | | | | | | | | +| points** | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *in | |v| | | | |x| | |x| | |x| | |x| | |x| | +| calls* | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *before | |v| | | | | | | |x| | |x| | +| calls* | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *for | NO | | | | | | **N** | **N** | +| loops* | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *before | |v| | | | | | | |x| | |x| | +| escape* | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| emit code | NO | | | | | | **N** | **N** | +| at safe | | | | | | | | | +| points | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| **output** | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *assembly* | |v| | | | |x| | |x| | |x| | |x| | |x| | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *JIT* | NO | | | **?** | **?** | **?** | **?** | **?** | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| *obj* | NO | | | **?** | **?** | **?** | **?** | **?** | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| live | NO | | | **?** | **?** | **?** | **?** | **?** | +| analysis | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| register | NO | | | **?** | **?** | **?** | **?** | **?** | +| map | | | | | | | | | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| \* Derived pointers only pose a hasard to copying collections. | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ +| **?** denotes a feature which could be utilized if available. | ++------------+------+--------+----------+-------+---------+-------------+----------+------------+ + +To be clear, the collection techniques above are defined as: + +Shadow Stack + The mutator carefully maintains a linked list of stack roots. + +Reference Counting + The mutator maintains a reference count for each object and frees an object + when its count falls to zero. + +Mark-Sweep + When the heap is exhausted, the collector marks reachable objects starting + from the roots, then deallocates unreachable objects in a sweep phase. + +Copying + As reachability analysis proceeds, the collector copies objects from one heap + area to another, compacting them in the process. Copying collectors enable + highly efficient "bump pointer" allocation and can improve locality of + reference. + +Incremental + (Including generational collectors.) Incremental collectors generally have all + the properties of a copying collector (regardless of whether the mature heap + is compacting), but bring the added complexity of requiring write barriers. + +Threaded + Denotes a multithreaded mutator; the collector must still stop the mutator + ("stop the world") before beginning reachability analysis. Stopping a + multithreaded mutator is a complicated problem. It generally requires highly + platform specific code in the runtime, and the production of carefully + designed machine code at safe points. + +Concurrent + In this technique, the mutator and the collector run concurrently, with the + goal of eliminating pause times. In a *cooperative* collector, the mutator + further aids with collection should a pause occur, allowing collection to take + advantage of multiprocessor hosts. The "stop the world" problem of threaded + collectors is generally still present to a limited extent. Sophisticated + marking algorithms are necessary. Read barriers may be necessary. + +As the matrix indicates, LLVM's garbage collection infrastructure is already +suitable for a wide variety of collectors, but does not currently extend to +multithreaded programs. This will be added in the future as there is +interest. + +.. _stack-map: + +Computing stack maps +-------------------- + +LLVM automatically computes a stack map. One of the most important features +of a ``GCStrategy`` is to compile this information into the executable in +the binary representation expected by the runtime library. + +The stack map consists of the location and identity of each GC root in the +each function in the module. For each root: + +* ``RootNum``: The index of the root. + +* ``StackOffset``: The offset of the object relative to the frame pointer. + +* ``RootMetadata``: The value passed as the ``%metadata`` parameter to the + ``@llvm.gcroot`` intrinsic. + +Also, for the function as a whole: + +* ``getFrameSize()``: The overall size of the function's initial stack frame, + not accounting for any dynamic allocation. + +* ``roots_size()``: The count of roots in the function. + +To access the stack map, use ``GCFunctionMetadata::roots_begin()`` and +-``end()`` from the :ref:`GCMetadataPrinter `: + +.. code-block:: c++ + + for (iterator I = begin(), E = end(); I != E; ++I) { + GCFunctionInfo *FI = *I; + unsigned FrameSize = FI->getFrameSize(); + size_t RootCount = FI->roots_size(); + + for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(), + RE = FI->roots_end(); + RI != RE; ++RI) { + int RootNum = RI->Num; + int RootStackOffset = RI->StackOffset; + Constant *RootMetadata = RI->Metadata; + } + } + +If the ``llvm.gcroot`` intrinsic is eliminated before code generation by a +custom lowering pass, LLVM will compute an empty stack map. This may be useful +for collector plugins which implement reference counting or a shadow stack. + +.. _init-roots: + +Initializing roots to null: ``InitRoots`` +----------------------------------------- + +.. code-block:: c++ + + MyGC::MyGC() { + InitRoots = true; + } + +When set, LLVM will automatically initialize each root to ``null`` upon entry to +the function. This prevents the GC's sweep phase from visiting uninitialized +pointers, which will almost certainly cause it to crash. This initialization +occurs before custom lowering, so the two may be used together. + +Since LLVM does not yet compute liveness information, there is no means of +distinguishing an uninitialized stack root from an initialized one. Therefore, +this feature should be used by all GC plugins. It is enabled by default. + +Custom lowering of intrinsics: ``CustomRoots``, ``CustomReadBarriers``, and ``CustomWriteBarriers`` +--------------------------------------------------------------------------------------------------- + +For GCs which use barriers or unusual treatment of stack roots, these flags +allow the collector to perform arbitrary transformations of the LLVM IR: + +.. code-block:: c++ + + class MyGC : public GCStrategy { + public: + MyGC() { + CustomRoots = true; + CustomReadBarriers = true; + CustomWriteBarriers = true; + } + + virtual bool initializeCustomLowering(Module &M); + virtual bool performCustomLowering(Function &F); + }; + +If any of these flags are set, then LLVM suppresses its default lowering for the +corresponding intrinsics and instead calls ``performCustomLowering``. + +LLVM's default action for each intrinsic is as follows: + +* ``llvm.gcroot``: Leave it alone. The code generator must see it or the stack + map will not be computed. + +* ``llvm.gcread``: Substitute a ``load`` instruction. + +* ``llvm.gcwrite``: Substitute a ``store`` instruction. + +If ``CustomReadBarriers`` or ``CustomWriteBarriers`` are specified, then +``performCustomLowering`` **must** eliminate the corresponding barriers. + +``performCustomLowering`` must comply with the same restrictions as +:ref:`FunctionPass::runOnFunction ` +Likewise, ``initializeCustomLowering`` has the same semantics as +:ref:`Pass::doInitialization(Module&) +` + +The following can be used as a template: + +.. code-block:: c++ + + #include "llvm/IR/Module.h" + #include "llvm/IR/IntrinsicInst.h" + + bool MyGC::initializeCustomLowering(Module &M) { + return false; + } + + bool MyGC::performCustomLowering(Function &F) { + bool MadeChange = false; + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ) + if (IntrinsicInst *CI = dyn_cast(II++)) + if (Function *F = CI->getCalledFunction()) + switch (F->getIntrinsicID()) { + case Intrinsic::gcwrite: + // Handle llvm.gcwrite. + CI->eraseFromParent(); + MadeChange = true; + break; + case Intrinsic::gcread: + // Handle llvm.gcread. + CI->eraseFromParent(); + MadeChange = true; + break; + case Intrinsic::gcroot: + // Handle llvm.gcroot. + CI->eraseFromParent(); + MadeChange = true; + break; + } + + return MadeChange; + } + +.. _safe-points: + +Generating safe points: ``NeededSafePoints`` +-------------------------------------------- + +LLVM can compute four kinds of safe points: + +.. code-block:: c++ + + namespace GC { + /// PointKind - The type of a collector-safe point. + /// + enum PointKind { + Loop, //< Instr is a loop (backwards branch). + Return, //< Instr is a return instruction. + PreCall, //< Instr is a call instruction. + PostCall //< Instr is the return address of a call. + }; + } + +A collector can request any combination of the four by setting the +``NeededSafePoints`` mask: + +.. code-block:: c++ + + MyGC::MyGC() { + NeededSafePoints = 1 << GC::Loop + | 1 << GC::Return + | 1 << GC::PreCall + | 1 << GC::PostCall; + } + +It can then use the following routines to access safe points. + +.. code-block:: c++ + + for (iterator I = begin(), E = end(); I != E; ++I) { + GCFunctionInfo *MD = *I; + size_t PointCount = MD->size(); + + for (GCFunctionInfo::iterator PI = MD->begin(), + PE = MD->end(); PI != PE; ++PI) { + GC::PointKind PointKind = PI->Kind; + unsigned PointNum = PI->Num; + } + } + +Almost every collector requires ``PostCall`` safe points, since these correspond +to the moments when the function is suspended during a call to a subroutine. + +Threaded programs generally require ``Loop`` safe points to guarantee that the +application will reach a safe point within a bounded amount of time, even if it +is executing a long-running loop which contains no function calls. + +Threaded collectors may also require ``Return`` and ``PreCall`` safe points to +implement "stop the world" techniques using self-modifying code, where it is +important that the program not exit the function without reaching a safe point +(because only the topmost function has been patched). + +.. _assembly: + +Emitting assembly code: ``GCMetadataPrinter`` +--------------------------------------------- + +LLVM allows a plugin to print arbitrary assembly code before and after the rest +of a module's assembly code. At the end of the module, the GC can compile the +LLVM stack map into assembly code. (At the beginning, this information is not +yet computed.) + +Since AsmWriter and CodeGen are separate components of LLVM, a separate abstract +base class and registry is provided for printing assembly code, the +``GCMetadaPrinter`` and ``GCMetadataPrinterRegistry``. The AsmWriter will look +for such a subclass if the ``GCStrategy`` sets ``UsesMetadata``: + +.. code-block:: c++ + + MyGC::MyGC() { + UsesMetadata = true; + } + +This separation allows JIT-only clients to be smaller. + +Note that LLVM does not currently have analogous APIs to support code generation +in the JIT, nor using the object writers. + +.. code-block:: c++ + + // lib/MyGC/MyGCPrinter.cpp - Example LLVM GC printer + + #include "llvm/CodeGen/GCMetadataPrinter.h" + #include "llvm/Support/Compiler.h" + + using namespace llvm; + + namespace { + class LLVM_LIBRARY_VISIBILITY MyGCPrinter : public GCMetadataPrinter { + public: + virtual void beginAssembly(AsmPrinter &AP); + + virtual void finishAssembly(AsmPrinter &AP); + }; + + GCMetadataPrinterRegistry::Add + X("mygc", "My bespoke garbage collector."); + } + +The collector should use ``AsmPrinter`` to print portable assembly code. The +collector itself contains the stack map for the entire module, and may access +the ``GCFunctionInfo`` using its own ``begin()`` and ``end()`` methods. Here's +a realistic example: + +.. code-block:: c++ + + #include "llvm/CodeGen/AsmPrinter.h" + #include "llvm/IR/Function.h" + #include "llvm/IR/DataLayout.h" + #include "llvm/Target/TargetAsmInfo.h" + #include "llvm/Target/TargetMachine.h" + + void MyGCPrinter::beginAssembly(AsmPrinter &AP) { + // Nothing to do. + } + + void MyGCPrinter::finishAssembly(AsmPrinter &AP) { + MCStreamer &OS = AP.OutStreamer; + unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(); + + // Put this in the data section. + OS.SwitchSection(AP.getObjFileLowering().getDataSection()); + + // For each function... + for (iterator FI = begin(), FE = end(); FI != FE; ++FI) { + GCFunctionInfo &MD = **FI; + + // A compact GC layout. Emit this data structure: + // + // struct { + // int32_t PointCount; + // void *SafePointAddress[PointCount]; + // int32_t StackFrameSize; // in words + // int32_t StackArity; + // int32_t LiveCount; + // int32_t LiveOffsets[LiveCount]; + // } __gcmap_; + + // Align to address width. + AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); + + // Emit PointCount. + OS.AddComment("safe point count"); + AP.EmitInt32(MD.size()); + + // And each safe point... + for (GCFunctionInfo::iterator PI = MD.begin(), + PE = MD.end(); PI != PE; ++PI) { + // Emit the address of the safe point. + OS.AddComment("safe point address"); + MCSymbol *Label = PI->Label; + AP.EmitLabelPlusOffset(Label/*Hi*/, 0/*Offset*/, 4/*Size*/); + } + + // Stack information never change in safe points! Only print info from the + // first call-site. + GCFunctionInfo::iterator PI = MD.begin(); + + // Emit the stack frame size. + OS.AddComment("stack frame size (in words)"); + AP.EmitInt32(MD.getFrameSize() / IntPtrSize); + + // Emit stack arity, i.e. the number of stacked arguments. + unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6; + unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs ? + MD.getFunction().arg_size() - RegisteredArgs : 0; + OS.AddComment("stack arity"); + AP.EmitInt32(StackArity); + + // Emit the number of live roots in the function. + OS.AddComment("live root count"); + AP.EmitInt32(MD.live_size(PI)); + + // And for each live root... + for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI), + LE = MD.live_end(PI); + LI != LE; ++LI) { + // Emit live root's offset within the stack frame. + OS.AddComment("stack index (offset / wordsize)"); + AP.EmitInt32(LI->StackOffset); + } + } + } + +References +========== + +.. _appel89: + +[Appel89] Runtime Tags Aren't Necessary. Andrew W. Appel. Lisp and Symbolic +Computation 19(7):703-705, July 1989. + +.. _goldberg91: + +[Goldberg91] Tag-free garbage collection for strongly typed programming +languages. Benjamin Goldberg. ACM SIGPLAN PLDI'91. + +.. _tolmach94: + +[Tolmach94] Tag-free garbage collection using explicit type parameters. Andrew +Tolmach. Proceedings of the 1994 ACM conference on LISP and functional +programming. + +.. _henderson02: + +[Henderson2002] `Accurate Garbage Collection in an Uncooperative Environment +`__ diff --git a/docs/GetElementPtr.rst b/docs/GetElementPtr.rst new file mode 100644 index 00000000..306a2a87 --- /dev/null +++ b/docs/GetElementPtr.rst @@ -0,0 +1,536 @@ +======================================= +The Often Misunderstood GEP Instruction +======================================= + +.. contents:: + :local: + +Introduction +============ + +This document seeks to dispel the mystery and confusion surrounding LLVM's +`GetElementPtr `_ (GEP) instruction. Questions +about the wily GEP instruction are probably the most frequently occurring +questions once a developer gets down to coding with LLVM. Here we lay out the +sources of confusion and show that the GEP instruction is really quite simple. + +Address Computation +=================== + +When people are first confronted with the GEP instruction, they tend to relate +it to known concepts from other programming paradigms, most notably C array +indexing and field selection. GEP closely resembles C array indexing and field +selection, however it is a little different and this leads to the following +questions. + +What is the first index of the GEP instruction? +----------------------------------------------- + +Quick answer: The index stepping through the first operand. + +The confusion with the first index usually arises from thinking about the +GetElementPtr instruction as if it was a C index operator. They aren't the +same. For example, when we write, in "C": + +.. code-block:: c++ + + AType *Foo; + ... + X = &Foo->F; + +it is natural to think that there is only one index, the selection of the field +``F``. However, in this example, ``Foo`` is a pointer. That pointer +must be indexed explicitly in LLVM. C, on the other hand, indices through it +transparently. To arrive at the same address location as the C code, you would +provide the GEP instruction with two index operands. The first operand indexes +through the pointer; the second operand indexes the field ``F`` of the +structure, just as if you wrote: + +.. code-block:: c++ + + X = &Foo[0].F; + +Sometimes this question gets rephrased as: + +.. _GEP index through first pointer: + + *Why is it okay to index through the first pointer, but subsequent pointers + won't be dereferenced?* + +The answer is simply because memory does not have to be accessed to perform the +computation. The first operand to the GEP instruction must be a value of a +pointer type. The value of the pointer is provided directly to the GEP +instruction as an operand without any need for accessing memory. It must, +therefore be indexed and requires an index operand. Consider this example: + +.. code-block:: c++ + + struct munger_struct { + int f1; + int f2; + }; + void munge(struct munger_struct *P) { + P[0].f1 = P[1].f1 + P[2].f2; + } + ... + munger_struct Array[3]; + ... + munge(Array); + +In this "C" example, the front end compiler (llvm-gcc) will generate three GEP +instructions for the three indices through "P" in the assignment statement. The +function argument ``P`` will be the first operand of each of these GEP +instructions. The second operand indexes through that pointer. The third +operand will be the field offset into the ``struct munger_struct`` type, for +either the ``f1`` or ``f2`` field. So, in LLVM assembly the ``munge`` function +looks like: + +.. code-block:: llvm + + void %munge(%struct.munger_struct* %P) { + entry: + %tmp = getelementptr %struct.munger_struct* %P, i32 1, i32 0 + %tmp = load i32* %tmp + %tmp6 = getelementptr %struct.munger_struct* %P, i32 2, i32 1 + %tmp7 = load i32* %tmp6 + %tmp8 = add i32 %tmp7, %tmp + %tmp9 = getelementptr %struct.munger_struct* %P, i32 0, i32 0 + store i32 %tmp8, i32* %tmp9 + ret void + } + +In each case the first operand is the pointer through which the GEP instruction +starts. The same is true whether the first operand is an argument, allocated +memory, or a global variable. + +To make this clear, let's consider a more obtuse example: + +.. code-block:: llvm + + %MyVar = uninitialized global i32 + ... + %idx1 = getelementptr i32* %MyVar, i64 0 + %idx2 = getelementptr i32* %MyVar, i64 1 + %idx3 = getelementptr i32* %MyVar, i64 2 + +These GEP instructions are simply making address computations from the base +address of ``MyVar``. They compute, as follows (using C syntax): + +.. code-block:: c++ + + idx1 = (char*) &MyVar + 0 + idx2 = (char*) &MyVar + 4 + idx3 = (char*) &MyVar + 8 + +Since the type ``i32`` is known to be four bytes long, the indices 0, 1 and 2 +translate into memory offsets of 0, 4, and 8, respectively. No memory is +accessed to make these computations because the address of ``%MyVar`` is passed +directly to the GEP instructions. + +The obtuse part of this example is in the cases of ``%idx2`` and ``%idx3``. They +result in the computation of addresses that point to memory past the end of the +``%MyVar`` global, which is only one ``i32`` long, not three ``i32``\s long. +While this is legal in LLVM, it is inadvisable because any load or store with +the pointer that results from these GEP instructions would produce undefined +results. + +Why is the extra 0 index required? +---------------------------------- + +Quick answer: there are no superfluous indices. + +This question arises most often when the GEP instruction is applied to a global +variable which is always a pointer type. For example, consider this: + +.. code-block:: llvm + + %MyStruct = uninitialized global { float*, i32 } + ... + %idx = getelementptr { float*, i32 }* %MyStruct, i64 0, i32 1 + +The GEP above yields an ``i32*`` by indexing the ``i32`` typed field of the +structure ``%MyStruct``. When people first look at it, they wonder why the ``i64 +0`` index is needed. However, a closer inspection of how globals and GEPs work +reveals the need. Becoming aware of the following facts will dispel the +confusion: + +#. The type of ``%MyStruct`` is *not* ``{ float*, i32 }`` but rather ``{ float*, + i32 }*``. That is, ``%MyStruct`` is a pointer to a structure containing a + pointer to a ``float`` and an ``i32``. + +#. Point #1 is evidenced by noticing the type of the first operand of the GEP + instruction (``%MyStruct``) which is ``{ float*, i32 }*``. + +#. The first index, ``i64 0`` is required to step over the global variable + ``%MyStruct``. Since the first argument to the GEP instruction must always + be a value of pointer type, the first index steps through that pointer. A + value of 0 means 0 elements offset from that pointer. + +#. The second index, ``i32 1`` selects the second field of the structure (the + ``i32``). + +What is dereferenced by GEP? +---------------------------- + +Quick answer: nothing. + +The GetElementPtr instruction dereferences nothing. That is, it doesn't access +memory in any way. That's what the Load and Store instructions are for. GEP is +only involved in the computation of addresses. For example, consider this: + +.. code-block:: llvm + + %MyVar = uninitialized global { [40 x i32 ]* } + ... + %idx = getelementptr { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17 + +In this example, we have a global variable, ``%MyVar`` that is a pointer to a +structure containing a pointer to an array of 40 ints. The GEP instruction seems +to be accessing the 18th integer of the structure's array of ints. However, this +is actually an illegal GEP instruction. It won't compile. The reason is that the +pointer in the structure *must* be dereferenced in order to index into the +array of 40 ints. Since the GEP instruction never accesses memory, it is +illegal. + +In order to access the 18th integer in the array, you would need to do the +following: + +.. code-block:: llvm + + %idx = getelementptr { [40 x i32]* }* %, i64 0, i32 0 + %arr = load [40 x i32]** %idx + %idx = getelementptr [40 x i32]* %arr, i64 0, i64 17 + +In this case, we have to load the pointer in the structure with a load +instruction before we can index into the array. If the example was changed to: + +.. code-block:: llvm + + %MyVar = uninitialized global { [40 x i32 ] } + ... + %idx = getelementptr { [40 x i32] }*, i64 0, i32 0, i64 17 + +then everything works fine. In this case, the structure does not contain a +pointer and the GEP instruction can index through the global variable, into the +first field of the structure and access the 18th ``i32`` in the array there. + +Why don't GEP x,0,0,1 and GEP x,1 alias? +---------------------------------------- + +Quick Answer: They compute different address locations. + +If you look at the first indices in these GEP instructions you find that they +are different (0 and 1), therefore the address computation diverges with that +index. Consider this example: + +.. code-block:: llvm + + %MyVar = global { [10 x i32 ] } + %idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 0, i32 0, i64 1 + %idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1 + +In this example, ``idx1`` computes the address of the second integer in the +array that is in the structure in ``%MyVar``, that is ``MyVar+4``. The type of +``idx1`` is ``i32*``. However, ``idx2`` computes the address of *the next* +structure after ``%MyVar``. The type of ``idx2`` is ``{ [10 x i32] }*`` and its +value is equivalent to ``MyVar + 40`` because it indexes past the ten 4-byte +integers in ``MyVar``. Obviously, in such a situation, the pointers don't +alias. + +Why do GEP x,1,0,0 and GEP x,1 alias? +------------------------------------- + +Quick Answer: They compute the same address location. + +These two GEP instructions will compute the same address because indexing +through the 0th element does not change the address. However, it does change the +type. Consider this example: + +.. code-block:: llvm + + %MyVar = global { [10 x i32 ] } + %idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 1, i32 0, i64 0 + %idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1 + +In this example, the value of ``%idx1`` is ``%MyVar+40`` and its type is +``i32*``. The value of ``%idx2`` is also ``MyVar+40`` but its type is ``{ [10 x +i32] }*``. + +Can GEP index into vector elements? +----------------------------------- + +This hasn't always been forcefully disallowed, though it's not recommended. It +leads to awkward special cases in the optimizers, and fundamental inconsistency +in the IR. In the future, it will probably be outright disallowed. + +What effect do address spaces have on GEPs? +------------------------------------------- + +None, except that the address space qualifier on the first operand pointer type +always matches the address space qualifier on the result type. + +How is GEP different from ``ptrtoint``, arithmetic, and ``inttoptr``? +--------------------------------------------------------------------- + +It's very similar; there are only subtle differences. + +With ptrtoint, you have to pick an integer type. One approach is to pick i64; +this is safe on everything LLVM supports (LLVM internally assumes pointers are +never wider than 64 bits in many places), and the optimizer will actually narrow +the i64 arithmetic down to the actual pointer size on targets which don't +support 64-bit arithmetic in most cases. However, there are some cases where it +doesn't do this. With GEP you can avoid this problem. + +Also, GEP carries additional pointer aliasing rules. It's invalid to take a GEP +from one object, address into a different separately allocated object, and +dereference it. IR producers (front-ends) must follow this rule, and consumers +(optimizers, specifically alias analysis) benefit from being able to rely on +it. See the `Rules`_ section for more information. + +And, GEP is more concise in common cases. + +However, for the underlying integer computation implied, there is no +difference. + + +I'm writing a backend for a target which needs custom lowering for GEP. How do I do this? +----------------------------------------------------------------------------------------- + +You don't. The integer computation implied by a GEP is target-independent. +Typically what you'll need to do is make your backend pattern-match expressions +trees involving ADD, MUL, etc., which are what GEP is lowered into. This has the +advantage of letting your code work correctly in more cases. + +GEP does use target-dependent parameters for the size and layout of data types, +which targets can customize. + +If you require support for addressing units which are not 8 bits, you'll need to +fix a lot of code in the backend, with GEP lowering being only a small piece of +the overall picture. + +How does VLA addressing work with GEPs? +--------------------------------------- + +GEPs don't natively support VLAs. LLVM's type system is entirely static, and GEP +address computations are guided by an LLVM type. + +VLA indices can be implemented as linearized indices. For example, an expression +like ``X[a][b][c]``, must be effectively lowered into a form like +``X[a*m+b*n+c]``, so that it appears to the GEP as a single-dimensional array +reference. + +This means if you want to write an analysis which understands array indices and +you want to support VLAs, your code will have to be prepared to reverse-engineer +the linearization. One way to solve this problem is to use the ScalarEvolution +library, which always presents VLA and non-VLA indexing in the same manner. + +.. _Rules: + +Rules +===== + +What happens if an array index is out of bounds? +------------------------------------------------ + +There are two senses in which an array index can be out of bounds. + +First, there's the array type which comes from the (static) type of the first +operand to the GEP. Indices greater than the number of elements in the +corresponding static array type are valid. There is no problem with out of +bounds indices in this sense. Indexing into an array only depends on the size of +the array element, not the number of elements. + +A common example of how this is used is arrays where the size is not known. +It's common to use array types with zero length to represent these. The fact +that the static type says there are zero elements is irrelevant; it's perfectly +valid to compute arbitrary element indices, as the computation only depends on +the size of the array element, not the number of elements. Note that zero-sized +arrays are not a special case here. + +This sense is unconnected with ``inbounds`` keyword. The ``inbounds`` keyword is +designed to describe low-level pointer arithmetic overflow conditions, rather +than high-level array indexing rules. + +Analysis passes which wish to understand array indexing should not assume that +the static array type bounds are respected. + +The second sense of being out of bounds is computing an address that's beyond +the actual underlying allocated object. + +With the ``inbounds`` keyword, the result value of the GEP is undefined if the +address is outside the actual underlying allocated object and not the address +one-past-the-end. + +Without the ``inbounds`` keyword, there are no restrictions on computing +out-of-bounds addresses. Obviously, performing a load or a store requires an +address of allocated and sufficiently aligned memory. But the GEP itself is only +concerned with computing addresses. + +Can array indices be negative? +------------------------------ + +Yes. This is basically a special case of array indices being out of bounds. + +Can I compare two values computed with GEPs? +-------------------------------------------- + +Yes. If both addresses are within the same allocated object, or +one-past-the-end, you'll get the comparison result you expect. If either is +outside of it, integer arithmetic wrapping may occur, so the comparison may not +be meaningful. + +Can I do GEP with a different pointer type than the type of the underlying object? +---------------------------------------------------------------------------------- + +Yes. There are no restrictions on bitcasting a pointer value to an arbitrary +pointer type. The types in a GEP serve only to define the parameters for the +underlying integer computation. They need not correspond with the actual type of +the underlying object. + +Furthermore, loads and stores don't have to use the same types as the type of +the underlying object. Types in this context serve only to specify memory size +and alignment. Beyond that there are merely a hint to the optimizer indicating +how the value will likely be used. + +Can I cast an object's address to integer and add it to null? +------------------------------------------------------------- + +You can compute an address that way, but if you use GEP to do the add, you can't +use that pointer to actually access the object, unless the object is managed +outside of LLVM. + +The underlying integer computation is sufficiently defined; null has a defined +value --- zero --- and you can add whatever value you want to it. + +However, it's invalid to access (load from or store to) an LLVM-aware object +with such a pointer. This includes ``GlobalVariables``, ``Allocas``, and objects +pointed to by noalias pointers. + +If you really need this functionality, you can do the arithmetic with explicit +integer instructions, and use inttoptr to convert the result to an address. Most +of GEP's special aliasing rules do not apply to pointers computed from ptrtoint, +arithmetic, and inttoptr sequences. + +Can I compute the distance between two objects, and add that value to one address to compute the other address? +--------------------------------------------------------------------------------------------------------------- + +As with arithmetic on null, you can use GEP to compute an address that way, but +you can't use that pointer to actually access the object if you do, unless the +object is managed outside of LLVM. + +Also as above, ptrtoint and inttoptr provide an alternative way to do this which +do not have this restriction. + +Can I do type-based alias analysis on LLVM IR? +---------------------------------------------- + +You can't do type-based alias analysis using LLVM's built-in type system, +because LLVM has no restrictions on mixing types in addressing, loads or stores. + +LLVM's type-based alias analysis pass uses metadata to describe a different type +system (such as the C type system), and performs type-based aliasing on top of +that. Further details are in the `language reference `_. + +What happens if a GEP computation overflows? +-------------------------------------------- + +If the GEP lacks the ``inbounds`` keyword, the value is the result from +evaluating the implied two's complement integer computation. However, since +there's no guarantee of where an object will be allocated in the address space, +such values have limited meaning. + +If the GEP has the ``inbounds`` keyword, the result value is undefined (a "trap +value") if the GEP overflows (i.e. wraps around the end of the address space). + +As such, there are some ramifications of this for inbounds GEPs: scales implied +by array/vector/pointer indices are always known to be "nsw" since they are +signed values that are scaled by the element size. These values are also +allowed to be negative (e.g. "``gep i32 *%P, i32 -1``") but the pointer itself +is logically treated as an unsigned value. This means that GEPs have an +asymmetric relation between the pointer base (which is treated as unsigned) and +the offset applied to it (which is treated as signed). The result of the +additions within the offset calculation cannot have signed overflow, but when +applied to the base pointer, there can be signed overflow. + +How can I tell if my front-end is following the rules? +------------------------------------------------------ + +There is currently no checker for the getelementptr rules. Currently, the only +way to do this is to manually check each place in your front-end where +GetElementPtr operators are created. + +It's not possible to write a checker which could find all rule violations +statically. It would be possible to write a checker which works by instrumenting +the code with dynamic checks though. Alternatively, it would be possible to +write a static checker which catches a subset of possible problems. However, no +such checker exists today. + +Rationale +========= + +Why is GEP designed this way? +----------------------------- + +The design of GEP has the following goals, in rough unofficial order of +priority: + +* Support C, C-like languages, and languages which can be conceptually lowered + into C (this covers a lot). + +* Support optimizations such as those that are common in C compilers. In + particular, GEP is a cornerstone of LLVM's `pointer aliasing + model `_. + +* Provide a consistent method for computing addresses so that address + computations don't need to be a part of load and store instructions in the IR. + +* Support non-C-like languages, to the extent that it doesn't interfere with + other goals. + +* Minimize target-specific information in the IR. + +Why do struct member indices always use ``i32``? +------------------------------------------------ + +The specific type i32 is probably just a historical artifact, however it's wide +enough for all practical purposes, so there's been no need to change it. It +doesn't necessarily imply i32 address arithmetic; it's just an identifier which +identifies a field in a struct. Requiring that all struct indices be the same +reduces the range of possibilities for cases where two GEPs are effectively the +same but have distinct operand types. + +What's an uglygep? +------------------ + +Some LLVM optimizers operate on GEPs by internally lowering them into more +primitive integer expressions, which allows them to be combined with other +integer expressions and/or split into multiple separate integer expressions. If +they've made non-trivial changes, translating back into LLVM IR can involve +reverse-engineering the structure of the addressing in order to fit it into the +static type of the original first operand. It isn't always possibly to fully +reconstruct this structure; sometimes the underlying addressing doesn't +correspond with the static type at all. In such cases the optimizer instead will +emit a GEP with the base pointer casted to a simple address-unit pointer, using +the name "uglygep". This isn't pretty, but it's just as valid, and it's +sufficient to preserve the pointer aliasing guarantees that GEP provides. + +Summary +======= + +In summary, here's some things to always remember about the GetElementPtr +instruction: + + +#. The GEP instruction never accesses memory, it only provides pointer + computations. + +#. The first operand to the GEP instruction is always a pointer and it must be + indexed. + +#. There are no superfluous indices for the GEP instruction. + +#. Trailing zero indices are superfluous for pointer aliasing, but not for the + types of the pointers. + +#. Leading zero indices are not superfluous for pointer aliasing nor the types + of the pointers. diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst new file mode 100644 index 00000000..2a6b6379 --- /dev/null +++ b/docs/GettingStarted.rst @@ -0,0 +1,1383 @@ +==================================== +Getting Started with the LLVM System +==================================== + +.. contents:: + :local: + +Overview +======== + +Welcome to LLVM! In order to get started, you first need to know some basic +information. + +First, LLVM comes in three pieces. The first piece is the LLVM suite. This +contains all of the tools, libraries, and header files needed to use LLVM. It +contains an assembler, disassembler, bitcode analyzer and bitcode optimizer. It +also contains basic regression tests that can be used to test the LLVM tools and +the Clang front end. + +The second piece is the `Clang `_ front end. This +component compiles C, C++, Objective C, and Objective C++ code into LLVM +bitcode. Once compiled into LLVM bitcode, a program can be manipulated with the +LLVM tools from the LLVM suite. + +There is a third, optional piece called Test Suite. It is a suite of programs +with a testing harness that can be used to further test LLVM's functionality +and performance. + +Getting Started Quickly (A Summary) +=================================== + +The LLVM Getting Started documentation may be out of date. So, the `Clang +Getting Started `_ page might also be a +good place to start. + +Here's the short story for getting up and running quickly with LLVM: + +#. Read the documentation. +#. Read the documentation. +#. Remember that you were warned twice about reading the documentation. +#. Checkout LLVM: + + * ``cd where-you-want-llvm-to-live`` + * ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm`` + +#. Checkout Clang: + + * ``cd where-you-want-llvm-to-live`` + * ``cd llvm/tools`` + * ``svn co http://llvm.org/svn/llvm-project/cfe/trunk clang`` + +#. Checkout Compiler-RT: + + * ``cd where-you-want-llvm-to-live`` + * ``cd llvm/projects`` + * ``svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt`` + +#. Get the Test Suite Source Code **[Optional]** + + * ``cd where-you-want-llvm-to-live`` + * ``cd llvm/projects`` + * ``svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite`` + +#. Configure and build LLVM and Clang: + + * ``cd where-you-want-to-build-llvm`` + * ``mkdir build`` (for building without polluting the source dir) + * ``cd build`` + * ``../llvm/configure [options]`` + Some common options: + + * ``--prefix=directory`` --- Specify for *directory* the full pathname of + where you want the LLVM tools and libraries to be installed (default + ``/usr/local``). + + * ``--enable-optimized`` --- Compile with optimizations enabled (default + is NO). + + * ``--enable-assertions`` --- Compile with assertion checks enabled + (default is YES). + + * ``make [-j]`` --- The ``-j`` specifies the number of jobs (commands) to run + simultaneously. This builds both LLVM and Clang for Debug+Asserts mode. + The ``--enable-optimized`` configure option is used to specify a Release + build. + + * ``make check-all`` --- This run the regression tests to ensure everything + is in working order. + + * ``make update`` --- This command is used to update all the svn repositories + at once, rather then having to ``cd`` into the individual repositories and + running ``svn update``. + + * It is also possible to use CMake instead of the makefiles. With CMake it is + possible to generate project files for several IDEs: Xcode, Eclipse CDT4, + CodeBlocks, Qt-Creator (use the CodeBlocks generator), KDevelop3. + + * If you get an "internal compiler error (ICE)" or test failures, see + `below`. + +Consult the `Getting Started with LLVM`_ section for detailed information on +configuring and compiling LLVM. See `Setting Up Your Environment`_ for tips +that simplify working with the Clang front end and LLVM tools. Go to `Program +Layout`_ to learn about the layout of the source code tree. + +Requirements +============ + +Before you begin to use the LLVM system, review the requirements given below. +This may save you some trouble by knowing ahead of time what hardware and +software you will need. + +Hardware +-------- + +LLVM is known to work on the following platforms: + ++-----------------+----------------------+-------------------------+ +|OS | Arch | Compilers | ++=================+======================+=========================+ +|AuroraUX | x86\ :sup:`1` | GCC | ++-----------------+----------------------+-------------------------+ +|Linux | x86\ :sup:`1` | GCC | ++-----------------+----------------------+-------------------------+ +|Linux | amd64 | GCC | ++-----------------+----------------------+-------------------------+ +|Linux | ARM\ :sup:`13` | GCC | ++-----------------+----------------------+-------------------------+ +|Solaris | V9 (Ultrasparc) | GCC | ++-----------------+----------------------+-------------------------+ +|FreeBSD | x86\ :sup:`1` | GCC | ++-----------------+----------------------+-------------------------+ +|FreeBSD | amd64 | GCC | ++-----------------+----------------------+-------------------------+ +|MacOS X\ :sup:`2`| PowerPC | GCC | ++-----------------+----------------------+-------------------------+ +|MacOS X\ :sup:`9`| x86 | GCC | ++-----------------+----------------------+-------------------------+ +|Cygwin/Win32 | x86\ :sup:`1, 8, 11` | GCC 3.4.X, binutils 2.20| ++-----------------+----------------------+-------------------------+ + +LLVM has partial support for the following platforms: + ++-------------------+----------------------+-------------------------------------------+ +|OS | Arch | Compilers | ++===================+======================+===========================================+ +| Windows | x86\ :sup:`1` | Visual Studio 2000 or higher\ :sup:`4,5` | ++-------------------+----------------------+-------------------------------------------+ +| AIX\ :sup:`3,4` | PowerPC | GCC | ++-------------------+----------------------+-------------------------------------------+ +| Linux\ :sup:`3,5` | PowerPC | GCC | ++-------------------+----------------------+-------------------------------------------+ +| Linux\ :sup:`7` | Alpha | GCC | ++-------------------+----------------------+-------------------------------------------+ +| Linux\ :sup:`7` | Itanium (IA-64) | GCC | ++-------------------+----------------------+-------------------------------------------+ +| HP-UX\ :sup:`7` | Itanium (IA-64) | HP aCC | ++-------------------+----------------------+-------------------------------------------+ +| Windows x64 | x86-64 | mingw-w64's GCC-4.5.x\ :sup:`12` | ++-------------------+----------------------+-------------------------------------------+ + +.. note:: + + #. Code generation supported for Pentium processors and up + #. Code generation supported for 32-bit ABI only + #. No native code generation + #. Build is not complete: one or more tools do not link or function + #. The GCC-based C/C++ frontend does not build + #. The port is done using the MSYS shell. + #. Native code generation exists but is not complete. + #. Binutils 2.20 or later is required to build the assembler generated by LLVM properly. + #. Xcode 2.5 and gcc 4.0.1 (Apple Build 5370) will trip internal LLVM assert + messages when compiled for Release at optimization levels greater than 0 + (i.e., ``-O1`` and higher). Add ``OPTIMIZE_OPTION="-O0"`` to the build + command line if compiling for LLVM Release or bootstrapping the LLVM + toolchain. + #. For MSYS/MinGW on Windows, be sure to install the MSYS version of the perl + package, and be sure it appears in your path before any Windows-based + versions such as Strawberry Perl and ActivePerl, as these have + Windows-specifics that will cause the build to fail. + #. To use LLVM modules on Win32-based system, you may configure LLVM + with ``--enable-shared``. + #. To compile SPU backend, you need to add ``LDFLAGS=-Wl,--stack,16777216`` to + configure. + #. MCJIT not working well pre-v7, old JIT engine not supported any more. + +Note that you will need about 1-3 GB of space for a full LLVM build in Debug +mode, depending on the system (it is so large because of all the debugging +information and the fact that the libraries are statically linked into multiple +tools). If you do not need many of the tools and you are space-conscious, you +can pass ``ONLY_TOOLS="tools you need"`` to make. The Release build requires +considerably less space. + +The LLVM suite *may* compile on other platforms, but it is not guaranteed to do +so. If compilation is successful, the LLVM utilities should be able to +assemble, disassemble, analyze, and optimize LLVM bitcode. Code generation +should work as well, although the generated native code may not work on your +platform. + +Software +-------- + +Compiling LLVM requires that you have several software packages installed. The +table below lists those required packages. The Package column is the usual name +for the software package that LLVM depends on. The Version column provides +"known to work" versions of the package. The Notes column describes how LLVM +uses the package and provides other details. + ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| Package | Version | Notes | ++==============================================================+=================+=============================================+ +| `GNU Make `_ | 3.79, 3.79.1 | Makefile/build processor | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `GCC `_ | 3.4.2 | C/C++ compiler\ :sup:`1` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `TeXinfo `_ | 4.5 | For building the CFE | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `SVN `_ | >=1.3 | Subversion access to LLVM\ :sup:`2` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `python `_ | >=2.5 | Automated test suite\ :sup:`3` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `GNU M4 `_ | 1.4 | Macro processor for configuration\ :sup:`4` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `GNU Autoconf `_ | 2.60 | Configuration script builder\ :sup:`4` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `GNU Automake `_ | 1.9.6 | aclocal macro generator\ :sup:`4` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `libtool `_ | 1.5.22 | Shared library manager\ :sup:`4` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `zlib `_ | >=1.2.3.4 | Compression library\ :sup:`5` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ + +.. note:: + + #. Only the C and C++ languages are needed so there's no need to build the + other languages for LLVM's purposes. See `below` for specific version + info. + #. You only need Subversion if you intend to build from the latest LLVM + sources. If you're working from a release distribution, you don't need + Subversion. + #. Only needed if you want to run the automated test suite in the + ``llvm/test`` directory. + #. If you want to make changes to the configure scripts, you will need GNU + autoconf (2.60), and consequently, GNU M4 (version 1.4 or higher). You + will also need automake (1.9.6). We only use aclocal from that package. + #. Optional, adds compression/uncompression capabilities to selected LLVM + tools. + +Additionally, your compilation host is expected to have the usual plethora of +Unix utilities. Specifically: + +* **ar** --- archive library builder +* **bzip2** --- bzip2 command for distribution generation +* **bunzip2** --- bunzip2 command for distribution checking +* **chmod** --- change permissions on a file +* **cat** --- output concatenation utility +* **cp** --- copy files +* **date** --- print the current date/time +* **echo** --- print to standard output +* **egrep** --- extended regular expression search utility +* **find** --- find files/dirs in a file system +* **grep** --- regular expression search utility +* **gzip** --- gzip command for distribution generation +* **gunzip** --- gunzip command for distribution checking +* **install** --- install directories/files +* **mkdir** --- create a directory +* **mv** --- move (rename) files +* **ranlib** --- symbol table builder for archive libraries +* **rm** --- remove (delete) files and directories +* **sed** --- stream editor for transforming output +* **sh** --- Bourne shell for make build scripts +* **tar** --- tape archive for distribution generation +* **test** --- test things in file system +* **unzip** --- unzip command for distribution checking +* **zip** --- zip command for distribution generation + +.. _below: +.. _check here: + +Broken versions of GCC and other tools +-------------------------------------- + +LLVM is very demanding of the host C++ compiler, and as such tends to expose +bugs in the compiler. In particular, several versions of GCC crash when trying +to compile LLVM. We routinely use GCC 4.2 (and higher) or Clang. Other +versions of GCC will probably work as well. GCC versions listed here are known +to not work. If you are using one of these versions, please try to upgrade your +GCC to something more recent. If you run into a problem with a version of GCC +not listed here, please `let us know `_. Please use +the "``gcc -v``" command to find out which version of GCC you are using. + +**GCC versions prior to 3.0**: GCC 2.96.x and before had several problems in the +STL that effectively prevent it from compiling LLVM. + +**GCC 3.2.2 and 3.2.3**: These versions of GCC fails to compile LLVM with a +bogus template error. This was fixed in later GCCs. + +**GCC 3.3.2**: This version of GCC suffered from a `serious bug +`_ which causes it to crash in the +"``convert_from_eh_region_ranges_1``" GCC function. + +**Cygwin GCC 3.3.3**: The version of GCC 3.3.3 commonly shipped with Cygwin does +not work. + +**SuSE GCC 3.3.3**: The version of GCC 3.3.3 shipped with SuSE 9.1 (and possibly +others) does not compile LLVM correctly (it appears that exception handling is +broken in some cases). Please download the FSF 3.3.3 or upgrade to a newer +version of GCC. + +**GCC 3.4.0 on linux/x86 (32-bit)**: GCC miscompiles portions of the code +generator, causing an infinite loop in the llvm-gcc build when built with +optimizations enabled (i.e. a release build). + +**GCC 3.4.2 on linux/x86 (32-bit)**: GCC miscompiles portions of the code +generator at -O3, as with 3.4.0. However gcc 3.4.2 (unlike 3.4.0) correctly +compiles LLVM at -O2. A work around is to build release LLVM builds with +"``make ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O2 ...``" + +**GCC 3.4.x on X86-64/amd64**: GCC `miscompiles portions of LLVM +`__. + +**GCC 3.4.4 (CodeSourcery ARM 2005q3-2)**: this compiler miscompiles LLVM when +building with optimizations enabled. It appears to work with "``make +ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O1``" or build a debug build. + +**IA-64 GCC 4.0.0**: The IA-64 version of GCC 4.0.0 is known to miscompile LLVM. + +**Apple Xcode 2.3**: GCC crashes when compiling LLVM at -O3 (which is the +default with ENABLE_OPTIMIZED=1. To work around this, build with +"``ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O2``". + +**GCC 4.1.1**: GCC fails to build LLVM with template concept check errors +compiling some files. At the time of this writing, GCC mainline (4.2) did not +share the problem. + +**GCC 4.1.1 on X86-64/amd64**: GCC `miscompiles portions of LLVM +`__ when compiling llvm itself into 64-bit code. LLVM +will appear to mostly work but will be buggy, e.g. failing portions of its +testsuite. + +**GCC 4.1.2 on OpenSUSE**: Seg faults during libstdc++ build and on x86_64 +platforms compiling md5.c gets a mangled constant. + +**GCC 4.1.2 (20061115 (prerelease) (Debian 4.1.1-21)) on Debian**: Appears to +miscompile parts of LLVM 2.4. One symptom is ValueSymbolTable complaining about +symbols remaining in the table on destruction. + +**GCC 4.1.2 20071124 (Red Hat 4.1.2-42)**: Suffers from the same symptoms as the +previous one. It appears to work with ENABLE_OPTIMIZED=0 (the default). + +**Cygwin GCC 4.3.2 20080827 (beta) 2**: Users `reported +`_ various problems related with link errors when using +this GCC version. + +**Debian GCC 4.3.2 on X86**: Crashes building some files in LLVM 2.6. + +**GCC 4.3.3 (Debian 4.3.3-10) on ARM**: Miscompiles parts of LLVM 2.6 when +optimizations are turned on. The symptom is an infinite loop in +``FoldingSetImpl::RemoveNode`` while running the code generator. + +**SUSE 11 GCC 4.3.4**: Miscompiles LLVM, causing crashes in ValueHandle logic. + +**GCC 4.3.5 and GCC 4.4.5 on ARM**: These can miscompile ``value >> 1`` even at +``-O0``. A test failure in ``test/Assembler/alignstack.ll`` is one symptom of +the problem. + +**GCC 4.6.3 on ARM**: Miscompiles ``llvm-readobj`` at ``-O3``. A test failure +in ``test/Object/readobj-shared-object.test`` is one symptom of the problem. + +**GNU ld 2.16.X**. Some 2.16.X versions of the ld linker will produce very long +warning messages complaining that some "``.gnu.linkonce.t.*``" symbol was +defined in a discarded section. You can safely ignore these messages as they are +erroneous and the linkage is correct. These messages disappear using ld 2.17. + +**GNU binutils 2.17**: Binutils 2.17 contains `a bug +`__ which causes huge link +times (minutes instead of seconds) when building LLVM. We recommend upgrading +to a newer version (2.17.50.0.4 or later). + +**GNU Binutils 2.19.1 Gold**: This version of Gold contained `a bug +`__ which causes +intermittent failures when building LLVM with position independent code. The +symptom is an error about cyclic dependencies. We recommend upgrading to a +newer version of Gold. + +**Clang 3.0 with libstdc++ 4.7.x**: a few Linux distributions (Ubuntu 12.10, +Fedora 17) have both Clang 3.0 and libstdc++ 4.7 in their repositories. Clang +3.0 does not implement a few builtins that are used in this library. We +recommend using the system GCC to compile LLVM and Clang in this case. + +**Clang 3.0 on Mageia 2**. There's a packaging issue: Clang can not find at +least some (``cxxabi.h``) libstdc++ headers. + +.. _Getting Started with LLVM: + +Getting Started with LLVM +========================= + +The remainder of this guide is meant to get you up and running with LLVM and to +give you some basic information about the LLVM environment. + +The later sections of this guide describe the `general layout`_ of the LLVM +source tree, a `simple example`_ using the LLVM tool chain, and `links`_ to find +more information about LLVM or to get help via e-mail. + +Terminology and Notation +------------------------ + +Throughout this manual, the following names are used to denote paths specific to +the local system and working environment. *These are not environment variables +you need to set but just strings used in the rest of this document below*. In +any of the examples below, simply replace each of these names with the +appropriate pathname on your local system. All these paths are absolute: + +``SRC_ROOT`` + + This is the top level directory of the LLVM source tree. + +``OBJ_ROOT`` + + This is the top level directory of the LLVM object tree (i.e. the tree where + object files and compiled programs will be placed. It can be the same as + SRC_ROOT). + +.. _Setting Up Your Environment: + +Setting Up Your Environment +--------------------------- + +In order to compile and use LLVM, you may need to set some environment +variables. + +``LLVM_LIB_SEARCH_PATH=/path/to/your/bitcode/libs`` + + [Optional] This environment variable helps LLVM linking tools find the + locations of your bitcode libraries. It is provided only as a convenience + since you can specify the paths using the -L options of the tools and the + C/C++ front-end will automatically use the bitcode files installed in its + ``lib`` directory. + +Unpacking the LLVM Archives +--------------------------- + +If you have the LLVM distribution, you will need to unpack it before you can +begin to compile it. LLVM is distributed as a set of two files: the LLVM suite +and the LLVM GCC front end compiled for your platform. There is an additional +test suite that is optional. Each file is a TAR archive that is compressed with +the gzip program. + +The files are as follows, with *x.y* marking the version number: + +``llvm-x.y.tar.gz`` + + Source release for the LLVM libraries and tools. + +``llvm-test-x.y.tar.gz`` + + Source release for the LLVM test-suite. + +.. _checkout: + +Checkout LLVM from Subversion +----------------------------- + +If you have access to our Subversion repository, you can get a fresh copy of the +entire source code. All you need to do is check it out from Subversion as +follows: + +* ``cd where-you-want-llvm-to-live`` +* Read-Only: ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm`` +* Read-Write:``svn co https://user@llvm.org/svn/llvm-project/llvm/trunk llvm`` + +This will create an '``llvm``' directory in the current directory and fully +populate it with the LLVM source code, Makefiles, test directories, and local +copies of documentation files. + +If you want to get a specific release (as opposed to the most recent revision), +you can checkout it from the '``tags``' directory (instead of '``trunk``'). The +following releases are located in the following subdirectories of the '``tags``' +directory: + +* Release 3.3: **RELEASE_33/final** +* Release 3.2: **RELEASE_32/final** +* Release 3.1: **RELEASE_31/final** +* Release 3.0: **RELEASE_30/final** +* Release 2.9: **RELEASE_29/final** +* Release 2.8: **RELEASE_28** +* Release 2.7: **RELEASE_27** +* Release 2.6: **RELEASE_26** +* Release 2.5: **RELEASE_25** +* Release 2.4: **RELEASE_24** +* Release 2.3: **RELEASE_23** +* Release 2.2: **RELEASE_22** +* Release 2.1: **RELEASE_21** +* Release 2.0: **RELEASE_20** +* Release 1.9: **RELEASE_19** +* Release 1.8: **RELEASE_18** +* Release 1.7: **RELEASE_17** +* Release 1.6: **RELEASE_16** +* Release 1.5: **RELEASE_15** +* Release 1.4: **RELEASE_14** +* Release 1.3: **RELEASE_13** +* Release 1.2: **RELEASE_12** +* Release 1.1: **RELEASE_11** +* Release 1.0: **RELEASE_1** + +If you would like to get the LLVM test suite (a separate package as of 1.4), you +get it from the Subversion repository: + +.. code-block:: console + + % cd llvm/projects + % svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite + +By placing it in the ``llvm/projects``, it will be automatically configured by +the LLVM configure script as well as automatically updated when you run ``svn +update``. + +Git Mirror +---------- + +Git mirrors are available for a number of LLVM subprojects. These mirrors sync +automatically with each Subversion commit and contain all necessary git-svn +marks (so, you can recreate git-svn metadata locally). Note that right now +mirrors reflect only ``trunk`` for each project. You can do the read-only Git +clone of LLVM via: + +.. code-block:: console + + % git clone http://llvm.org/git/llvm.git + +If you want to check out clang too, run: + +.. code-block:: console + + % cd llvm/tools + % git clone http://llvm.org/git/clang.git + +If you want to check out compiler-rt too, run: + +.. code-block:: console + + % cd llvm/projects + % git clone http://llvm.org/git/compiler-rt.git + +If you want to check out the Test Suite Source Code (optional), run: + +.. code-block:: console + + % cd llvm/projects + % git clone http://llvm.org/git/test-suite.git + +Since the upstream repository is in Subversion, you should use ``git +pull --rebase`` instead of ``git pull`` to avoid generating a non-linear history +in your clone. To configure ``git pull`` to pass ``--rebase`` by default on the +master branch, run the following command: + +.. code-block:: console + + % git config branch.master.rebase true + +Sending patches with Git +^^^^^^^^^^^^^^^^^^^^^^^^ + +Please read `Developer Policy `_, too. + +Assume ``master`` points the upstream and ``mybranch`` points your working +branch, and ``mybranch`` is rebased onto ``master``. At first you may check +sanity of whitespaces: + +.. code-block:: console + + % git diff --check master..mybranch + +The easiest way to generate a patch is as below: + +.. code-block:: console + + % git diff master..mybranch > /path/to/mybranch.diff + +It is a little different from svn-generated diff. git-diff-generated diff has +prefixes like ``a/`` and ``b/``. Don't worry, most developers might know it +could be accepted with ``patch -p1 -N``. + +But you may generate patchset with git-format-patch. It generates by-each-commit +patchset. To generate patch files to attach to your article: + +.. code-block:: console + + % git format-patch --no-attach master..mybranch -o /path/to/your/patchset + +If you would like to send patches directly, you may use git-send-email or +git-imap-send. Here is an example to generate the patchset in Gmail's [Drafts]. + +.. code-block:: console + + % git format-patch --attach master..mybranch --stdout | git imap-send + +Then, your .git/config should have [imap] sections. + +.. code-block:: ini + + [imap] + host = imaps://imap.gmail.com + user = your.gmail.account@gmail.com + pass = himitsu! + port = 993 + sslverify = false + ; in English + folder = "[Gmail]/Drafts" + ; example for Japanese, "Modified UTF-7" encoded. + folder = "[Gmail]/&Tgtm+DBN-" + ; example for Traditional Chinese + folder = "[Gmail]/&g0l6Pw-" + +For developers to work with git-svn +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To set up clone from which you can submit code using ``git-svn``, run: + +.. code-block:: console + + % git clone http://llvm.org/git/llvm.git + % cd llvm + % git svn init https://llvm.org/svn/llvm-project/llvm/trunk --username= + % git config svn-remote.svn.fetch :refs/remotes/origin/master + % git svn rebase -l # -l avoids fetching ahead of the git mirror. + + # If you have clang too: + % cd tools + % git clone http://llvm.org/git/clang.git + % cd clang + % git svn init https://llvm.org/svn/llvm-project/cfe/trunk --username= + % git config svn-remote.svn.fetch :refs/remotes/origin/master + % git svn rebase -l + +Likewise for compiler-rt and test-suite. + +To update this clone without generating git-svn tags that conflict with the +upstream Git repo, run: + +.. code-block:: console + + % git fetch && (cd tools/clang && git fetch) # Get matching revisions of both trees. + % git checkout master + % git svn rebase -l + % (cd tools/clang && + git checkout master && + git svn rebase -l) + +Likewise for compiler-rt and test-suite. + +This leaves your working directories on their master branches, so you'll need to +``checkout`` each working branch individually and ``rebase`` it on top of its +parent branch. + +For those who wish to be able to update an llvm repo/revert patches easily using +git-svn, please look in the directory for the scripts ``git-svnup`` and +``git-svnrevert``. + +To perform the aforementioned update steps go into your source directory and +just type ``git-svnup`` or ``git svnup`` and everything will just work. + +If one wishes to revert a commit with git-svn, but do not want the git hash to +escape into the commit message, one can use the script ``git-svnrevert`` or +``git svnrevert`` which will take in the git hash for the commit you want to +revert, look up the appropriate svn revision, and output a message where all +references to the git hash have been replaced with the svn revision. + +To commit back changes via git-svn, use ``git svn dcommit``: + +.. code-block:: console + + % git svn dcommit + +Note that git-svn will create one SVN commit for each Git commit you have pending, +so squash and edit each commit before executing ``dcommit`` to make sure they all +conform to the coding standards and the developers' policy. + +On success, ``dcommit`` will rebase against the HEAD of SVN, so to avoid conflict, +please make sure your current branch is up-to-date (via fetch/rebase) before +proceeding. + +The git-svn metadata can get out of sync after you mess around with branches and +``dcommit``. When that happens, ``git svn dcommit`` stops working, complaining +about files with uncommitted changes. The fix is to rebuild the metadata: + +.. code-block:: console + + % rm -rf .git/svn + % git svn rebase -l + +Please, refer to the Git-SVN manual (``man git-svn``) for more information. + +Local LLVM Configuration +------------------------ + +Once checked out from the Subversion repository, the LLVM suite source code must +be configured via the ``configure`` script. This script sets variables in the +various ``*.in`` files, most notably ``llvm/Makefile.config`` and +``llvm/include/Config/config.h``. It also populates *OBJ_ROOT* with the +Makefiles needed to begin building LLVM. + +The following environment variables are used by the ``configure`` script to +configure the build system: + ++------------+-----------------------------------------------------------+ +| Variable | Purpose | ++============+===========================================================+ +| CC | Tells ``configure`` which C compiler to use. By default, | +| | ``configure`` will check ``PATH`` for ``clang`` and GCC C | +| | compilers (in this order). Use this variable to override | +| | ``configure``\'s default behavior. | ++------------+-----------------------------------------------------------+ +| CXX | Tells ``configure`` which C++ compiler to use. By | +| | default, ``configure`` will check ``PATH`` for | +| | ``clang++`` and GCC C++ compilers (in this order). Use | +| | this variable to override ``configure``'s default | +| | behavior. | ++------------+-----------------------------------------------------------+ + +The following options can be used to set or enable LLVM specific options: + +``--enable-optimized`` + + Enables optimized compilation (debugging symbols are removed and GCC + optimization flags are enabled). Note that this is the default setting if you + are using the LLVM distribution. The default behavior of an Subversion + checkout is to use an unoptimized build (also known as a debug build). + +``--enable-debug-runtime`` + + Enables debug symbols in the runtime libraries. The default is to strip debug + symbols from the runtime libraries. + +``--enable-jit`` + + Compile the Just In Time (JIT) compiler functionality. This is not available + on all platforms. The default is dependent on platform, so it is best to + explicitly enable it if you want it. + +``--enable-targets=target-option`` + + Controls which targets will be built and linked into llc. The default value + for ``target_options`` is "all" which builds and links all available targets. + The value "host-only" can be specified to build only a native compiler (no + cross-compiler targets available). The "native" target is selected as the + target of the build host. You can also specify a comma separated list of + target names that you want available in llc. The target names use all lower + case. The current set of targets is: + + ``arm, cpp, hexagon, mips, mipsel, msp430, powerpc, ptx, sparc, spu, + systemz, x86, x86_64, xcore``. + +``--enable-doxygen`` + + Look for the doxygen program and enable construction of doxygen based + documentation from the source code. This is disabled by default because + generating the documentation can take a long time and producess 100s of + megabytes of output. + +``--with-udis86`` + + LLVM can use external disassembler library for various purposes (now it's used + only for examining code produced by JIT). This option will enable usage of + `udis86 `_ x86 (both 32 and 64 bits) + disassembler library. + +To configure LLVM, follow these steps: + +#. Change directory into the object root directory: + + .. code-block:: console + + % cd OBJ_ROOT + +#. Run the ``configure`` script located in the LLVM source tree: + + .. code-block:: console + + % SRC_ROOT/configure --prefix=/install/path [other options] + +Compiling the LLVM Suite Source Code +------------------------------------ + +Once you have configured LLVM, you can build it. There are three types of +builds: + +Debug Builds + + These builds are the default when one is using an Subversion checkout and + types ``gmake`` (unless the ``--enable-optimized`` option was used during + configuration). The build system will compile the tools and libraries with + debugging information. To get a Debug Build using the LLVM distribution the + ``--disable-optimized`` option must be passed to ``configure``. + +Release (Optimized) Builds + + These builds are enabled with the ``--enable-optimized`` option to + ``configure`` or by specifying ``ENABLE_OPTIMIZED=1`` on the ``gmake`` command + line. For these builds, the build system will compile the tools and libraries + with GCC optimizations enabled and strip debugging information from the + libraries and executables it generates. Note that Release Builds are default + when using an LLVM distribution. + +Profile Builds + + These builds are for use with profiling. They compile profiling information + into the code for use with programs like ``gprof``. Profile builds must be + started by specifying ``ENABLE_PROFILING=1`` on the ``gmake`` command line. + +Once you have LLVM configured, you can build it by entering the *OBJ_ROOT* +directory and issuing the following command: + +.. code-block:: console + + % gmake + +If the build fails, please `check here`_ to see if you are using a version of +GCC that is known not to compile LLVM. + +If you have multiple processors in your machine, you may wish to use some of the +parallel build options provided by GNU Make. For example, you could use the +command: + +.. code-block:: console + + % gmake -j2 + +There are several special targets which are useful when working with the LLVM +source code: + +``gmake clean`` + + Removes all files generated by the build. This includes object files, + generated C/C++ files, libraries, and executables. + +``gmake dist-clean`` + + Removes everything that ``gmake clean`` does, but also removes files generated + by ``configure``. It attempts to return the source tree to the original state + in which it was shipped. + +``gmake install`` + + Installs LLVM header files, libraries, tools, and documentation in a hierarchy + under ``$PREFIX``, specified with ``./configure --prefix=[dir]``, which + defaults to ``/usr/local``. + +``gmake -C runtime install-bytecode`` + + Assuming you built LLVM into $OBJDIR, when this command is run, it will + install bitcode libraries into the GCC front end's bitcode library directory. + If you need to update your bitcode libraries, this is the target to use once + you've built them. + +Please see the `Makefile Guide `_ for further details on +these ``make`` targets and descriptions of other targets available. + +It is also possible to override default values from ``configure`` by declaring +variables on the command line. The following are some examples: + +``gmake ENABLE_OPTIMIZED=1`` + + Perform a Release (Optimized) build. + +``gmake ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1`` + + Perform a Release (Optimized) build without assertions enabled. + +``gmake ENABLE_OPTIMIZED=0`` + + Perform a Debug build. + +``gmake ENABLE_PROFILING=1`` + + Perform a Profiling build. + +``gmake VERBOSE=1`` + + Print what ``gmake`` is doing on standard output. + +``gmake TOOL_VERBOSE=1`` + + Ask each tool invoked by the makefiles to print out what it is doing on + the standard output. This also implies ``VERBOSE=1``. + +Every directory in the LLVM object tree includes a ``Makefile`` to build it and +any subdirectories that it contains. Entering any directory inside the LLVM +object tree and typing ``gmake`` should rebuild anything in or below that +directory that is out of date. + +This does not apply to building the documentation. +LLVM's (non-Doxygen) documentation is produced with the +`Sphinx `_ documentation generation system. +There are some HTML documents that have not yet been converted to the new +system (which uses the easy-to-read and easy-to-write +`reStructuredText `_ plaintext markup +language). +The generated documentation is built in the ``SRC_ROOT/docs`` directory using +a special makefile. +For instructions on how to install Sphinx, see +`Sphinx Introduction for LLVM Developers +`_. +After following the instructions there for installing Sphinx, build the LLVM +HTML documentation by doing the following: + +.. code-block:: console + + $ cd SRC_ROOT/docs + $ make -f Makefile.sphinx + +This creates a ``_build/html`` sub-directory with all of the HTML files, not +just the generated ones. +This directory corresponds to ``llvm.org/docs``. +For example, ``_build/html/SphinxQuickstartTemplate.html`` corresponds to +``llvm.org/docs/SphinxQuickstartTemplate.html``. +The :doc:`SphinxQuickstartTemplate` is useful when creating a new document. + +Cross-Compiling LLVM +-------------------- + +It is possible to cross-compile LLVM itself. That is, you can create LLVM +executables and libraries to be hosted on a platform different from the platform +where they are built (a Canadian Cross build). To configure a cross-compile, +supply the configure script with ``--build`` and ``--host`` options that are +different. The values of these options must be legal target triples that your +GCC compiler supports. + +The result of such a build is executables that are not runnable on on the build +host (--build option) but can be executed on the compile host (--host option). + +Check :doc:`HowToCrossCompileLLVM` and `Clang docs on how to cross-compile in general +`_ for more information +about cross-compiling. + +The Location of LLVM Object Files +--------------------------------- + +The LLVM build system is capable of sharing a single LLVM source tree among +several LLVM builds. Hence, it is possible to build LLVM for several different +platforms or configurations using the same source tree. + +This is accomplished in the typical autoconf manner: + +* Change directory to where the LLVM object files should live: + + .. code-block:: console + + % cd OBJ_ROOT + +* Run the ``configure`` script found in the LLVM source directory: + + .. code-block:: console + + % SRC_ROOT/configure + +The LLVM build will place files underneath *OBJ_ROOT* in directories named after +the build type: + +Debug Builds with assertions enabled (the default) + + Tools + + ``OBJ_ROOT/Debug+Asserts/bin`` + + Libraries + + ``OBJ_ROOT/Debug+Asserts/lib`` + +Release Builds + + Tools + + ``OBJ_ROOT/Release/bin`` + + Libraries + + ``OBJ_ROOT/Release/lib`` + +Profile Builds + + Tools + + ``OBJ_ROOT/Profile/bin`` + + Libraries + + ``OBJ_ROOT/Profile/lib`` + +Optional Configuration Items +---------------------------- + +If you're running on a Linux system that supports the `binfmt_misc +`_ +module, and you have root access on the system, you can set your system up to +execute LLVM bitcode files directly. To do this, use commands like this (the +first command may not be required if you are already using the module): + +.. code-block:: console + + % mount -t binfmt_misc none /proc/sys/fs/binfmt_misc + % echo ':llvm:M::BC::/path/to/lli:' > /proc/sys/fs/binfmt_misc/register + % chmod u+x hello.bc (if needed) + % ./hello.bc + +This allows you to execute LLVM bitcode files directly. On Debian, you can also +use this command instead of the 'echo' command above: + +.. code-block:: console + + % sudo update-binfmts --install llvm /path/to/lli --magic 'BC' + +.. _Program Layout: +.. _general layout: + +Program Layout +============== + +One useful source of information about the LLVM source base is the LLVM `doxygen +`_ documentation available at +``_. The following is a brief introduction to code +layout: + +``llvm/examples`` +----------------- + +This directory contains some simple examples of how to use the LLVM IR and JIT. + +``llvm/include`` +---------------- + +This directory contains public header files exported from the LLVM library. The +three main subdirectories of this directory are: + +``llvm/include/llvm`` + + This directory contains all of the LLVM specific header files. This directory + also has subdirectories for different portions of LLVM: ``Analysis``, + ``CodeGen``, ``Target``, ``Transforms``, etc... + +``llvm/include/llvm/Support`` + + This directory contains generic support libraries that are provided with LLVM + but not necessarily specific to LLVM. For example, some C++ STL utilities and + a Command Line option processing library store their header files here. + +``llvm/include/llvm/Config`` + + This directory contains header files configured by the ``configure`` script. + They wrap "standard" UNIX and C header files. Source code can include these + header files which automatically take care of the conditional #includes that + the ``configure`` script generates. + +``llvm/lib`` +------------ + +This directory contains most of the source files of the LLVM system. In LLVM, +almost all code exists in libraries, making it very easy to share code among the +different `tools`_. + +``llvm/lib/VMCore/`` + + This directory holds the core LLVM source files that implement core classes + like Instruction and BasicBlock. + +``llvm/lib/AsmParser/`` + + This directory holds the source code for the LLVM assembly language parser + library. + +``llvm/lib/Bitcode/`` + + This directory holds code for reading and write LLVM bitcode. + +``llvm/lib/Analysis/`` + + This directory contains a variety of different program analyses, such as + Dominator Information, Call Graphs, Induction Variables, Interval + Identification, Natural Loop Identification, etc. + +``llvm/lib/Transforms/`` + + This directory contains the source code for the LLVM to LLVM program + transformations, such as Aggressive Dead Code Elimination, Sparse Conditional + Constant Propagation, Inlining, Loop Invariant Code Motion, Dead Global + Elimination, and many others. + +``llvm/lib/Target/`` + + This directory contains files that describe various target architectures for + code generation. For example, the ``llvm/lib/Target/X86`` directory holds the + X86 machine description while ``llvm/lib/Target/ARM`` implements the ARM + backend. + +``llvm/lib/CodeGen/`` + + This directory contains the major parts of the code generator: Instruction + Selector, Instruction Scheduling, and Register Allocation. + +``llvm/lib/MC/`` + + (FIXME: T.B.D.) + +``llvm/lib/Debugger/`` + + This directory contains the source level debugger library that makes it + possible to instrument LLVM programs so that a debugger could identify source + code locations at which the program is executing. + +``llvm/lib/ExecutionEngine/`` + + This directory contains libraries for executing LLVM bitcode directly at + runtime in both interpreted and JIT compiled fashions. + +``llvm/lib/Support/`` + + This directory contains the source code that corresponds to the header files + located in ``llvm/include/ADT/`` and ``llvm/include/Support/``. + +``llvm/projects`` +----------------- + +This directory contains projects that are not strictly part of LLVM but are +shipped with LLVM. This is also the directory where you should create your own +LLVM-based projects. See ``llvm/projects/sample`` for an example of how to set +up your own project. + +``llvm/runtime`` +---------------- + +This directory contains libraries which are compiled into LLVM bitcode and used +when linking programs with the Clang front end. Most of these libraries are +skeleton versions of real libraries; for example, libc is a stripped down +version of glibc. + +Unlike the rest of the LLVM suite, this directory needs the LLVM GCC front end +to compile. + +``llvm/test`` +------------- + +This directory contains feature and regression tests and other basic sanity +checks on the LLVM infrastructure. These are intended to run quickly and cover a +lot of territory without being exhaustive. + +``test-suite`` +-------------- + +This is not a directory in the normal llvm module; it is a separate Subversion +module that must be checked out (usually to ``projects/test-suite``). This +module contains a comprehensive correctness, performance, and benchmarking test +suite for LLVM. It is a separate Subversion module because not every LLVM user +is interested in downloading or building such a comprehensive test suite. For +further details on this test suite, please see the :doc:`Testing Guide +` document. + +.. _tools: + +``llvm/tools`` +-------------- + +The **tools** directory contains the executables built out of the libraries +above, which form the main part of the user interface. You can always get help +for a tool by typing ``tool_name -help``. The following is a brief introduction +to the most important tools. More detailed information is in +the `Command Guide `_. + +``bugpoint`` + + ``bugpoint`` is used to debug optimization passes or code generation backends + by narrowing down the given test case to the minimum number of passes and/or + instructions that still cause a problem, whether it is a crash or + miscompilation. See ``_ for more information on using + ``bugpoint``. + +``llvm-ar`` + + The archiver produces an archive containing the given LLVM bitcode files, + optionally with an index for faster lookup. + +``llvm-as`` + + The assembler transforms the human readable LLVM assembly to LLVM bitcode. + +``llvm-dis`` + + The disassembler transforms the LLVM bitcode to human readable LLVM assembly. + +``llvm-link`` + + ``llvm-link``, not surprisingly, links multiple LLVM modules into a single + program. + +``lli`` + + ``lli`` is the LLVM interpreter, which can directly execute LLVM bitcode + (although very slowly...). For architectures that support it (currently x86, + Sparc, and PowerPC), by default, ``lli`` will function as a Just-In-Time + compiler (if the functionality was compiled in), and will execute the code + *much* faster than the interpreter. + +``llc`` + + ``llc`` is the LLVM backend compiler, which translates LLVM bitcode to a + native code assembly file or to C code (with the ``-march=c`` option). + +``opt`` + + ``opt`` reads LLVM bitcode, applies a series of LLVM to LLVM transformations + (which are specified on the command line), and then outputs the resultant + bitcode. The '``opt -help``' command is a good way to get a list of the + program transformations available in LLVM. + + ``opt`` can also be used to run a specific analysis on an input LLVM bitcode + file and print out the results. It is primarily useful for debugging + analyses, or familiarizing yourself with what an analysis does. + +``llvm/utils`` +-------------- + +This directory contains utilities for working with LLVM source code, and some of +the utilities are actually required as part of the build process because they +are code generators for parts of LLVM infrastructure. + + +``codegen-diff`` + + ``codegen-diff`` is a script that finds differences between code that LLC + generates and code that LLI generates. This is a useful tool if you are + debugging one of them, assuming that the other generates correct output. For + the full user manual, run ```perldoc codegen-diff'``. + +``emacs/`` + + The ``emacs`` directory contains syntax-highlighting files which will work + with Emacs and XEmacs editors, providing syntax highlighting support for LLVM + assembly files and TableGen description files. For information on how to use + the syntax files, consult the ``README`` file in that directory. + +``getsrcs.sh`` + + The ``getsrcs.sh`` script finds and outputs all non-generated source files, + which is useful if one wishes to do a lot of development across directories + and does not want to individually find each file. One way to use it is to run, + for example: ``xemacs `utils/getsources.sh``` from the top of your LLVM source + tree. + +``llvmgrep`` + + This little tool performs an ``egrep -H -n`` on each source file in LLVM and + passes to it a regular expression provided on ``llvmgrep``'s command + line. This is a very efficient way of searching the source base for a + particular regular expression. + +``makellvm`` + + The ``makellvm`` script compiles all files in the current directory and then + compiles and links the tool that is the first argument. For example, assuming + you are in the directory ``llvm/lib/Target/Sparc``, if ``makellvm`` is in your + path, simply running ``makellvm llc`` will make a build of the current + directory, switch to directory ``llvm/tools/llc`` and build it, causing a + re-linking of LLC. + +``TableGen/`` + + The ``TableGen`` directory contains the tool used to generate register + descriptions, instruction set descriptions, and even assemblers from common + TableGen description files. + +``vim/`` + + The ``vim`` directory contains syntax-highlighting files which will work with + the VIM editor, providing syntax highlighting support for LLVM assembly files + and TableGen description files. For information on how to use the syntax + files, consult the ``README`` file in that directory. + +.. _simple example: + +An Example Using the LLVM Tool Chain +==================================== + +This section gives an example of using LLVM with the Clang front end. + +Example with clang +------------------ + +#. First, create a simple C file, name it 'hello.c': + + .. code-block:: c + + #include + + int main() { + printf("hello world\n"); + return 0; + } + +#. Next, compile the C file into a native executable: + + .. code-block:: console + + % clang hello.c -o hello + + .. note:: + + Clang works just like GCC by default. The standard -S and -c arguments + work as usual (producing a native .s or .o file, respectively). + +#. Next, compile the C file into an LLVM bitcode file: + + .. code-block:: console + + % clang -O3 -emit-llvm hello.c -c -o hello.bc + + The -emit-llvm option can be used with the -S or -c options to emit an LLVM + ``.ll`` or ``.bc`` file (respectively) for the code. This allows you to use + the `standard LLVM tools `_ on the bitcode file. + +#. Run the program in both forms. To run the program, use: + + .. code-block:: console + + % ./hello + + and + + .. code-block:: console + + % lli hello.bc + + The second examples shows how to invoke the LLVM JIT, :doc:`lli + `. + +#. Use the ``llvm-dis`` utility to take a look at the LLVM assembly code: + + .. code-block:: console + + % llvm-dis < hello.bc | less + +#. Compile the program to native assembly using the LLC code generator: + + .. code-block:: console + + % llc hello.bc -o hello.s + +#. Assemble the native assembly language file into a program: + + .. code-block:: console + + % /opt/SUNWspro/bin/cc -xarch=v9 hello.s -o hello.native # On Solaris + + % gcc hello.s -o hello.native # On others + +#. Execute the native code program: + + .. code-block:: console + + % ./hello.native + + Note that using clang to compile directly to native code (i.e. when the + ``-emit-llvm`` option is not present) does steps 6/7/8 for you. + +Common Problems +=============== + +If you are having problems building or using LLVM, or if you have any other +general questions about LLVM, please consult the `Frequently Asked +Questions `_ page. + +.. _links: + +Links +===== + +This document is just an **introduction** on how to use LLVM to do some simple +things... there are many more interesting and complicated things that you can do +that aren't documented here (but we'll gladly accept a patch if you want to +write something up!). For more information about LLVM, check out: + +* `LLVM Homepage `_ +* `LLVM Doxygen Tree `_ +* `Starting a Project that Uses LLVM `_ diff --git a/docs/GettingStartedVS.rst b/docs/GettingStartedVS.rst new file mode 100644 index 00000000..c46dc831 --- /dev/null +++ b/docs/GettingStartedVS.rst @@ -0,0 +1,235 @@ +================================================================== +Getting Started with the LLVM System using Microsoft Visual Studio +================================================================== + +.. contents:: + :local: + + +Overview +======== +Welcome to LLVM on Windows! This document only covers LLVM on Windows using +Visual Studio, not mingw or cygwin. In order to get started, you first need to +know some basic information. + +There are many different projects that compose LLVM. The first is the LLVM +suite. This contains all of the tools, libraries, and header files needed to +use LLVM. It contains an assembler, disassembler, +bitcode analyzer and bitcode optimizer. It also contains a test suite that can +be used to test the LLVM tools. + +Another useful project on Windows is `Clang `_. +Clang is a C family ([Objective]C/C++) compiler. Clang mostly works on +Windows, but does not currently understand all of the Microsoft extensions +to C and C++. Because of this, clang cannot parse the C++ standard library +included with Visual Studio, nor parts of the Windows Platform SDK. However, +most standard C programs do compile. Clang can be used to emit bitcode, +directly emit object files or even linked executables using Visual Studio's +``link.exe``. + +The large LLVM test suite cannot be run on the Visual Studio port at this +time. + +Most of the tools build and work. ``bugpoint`` does build, but does +not work. + +Additional information about the LLVM directory structure and tool chain +can be found on the main `Getting Started `_ page. + + +Requirements +============ +Before you begin to use the LLVM system, review the requirements given +below. This may save you some trouble by knowing ahead of time what hardware +and software you will need. + +Hardware +-------- +Any system that can adequately run Visual Studio 2010 is fine. The LLVM +source tree and object files, libraries and executables will consume +approximately 3GB. + +Software +-------- +You will need Visual Studio 2010 or higher. Earlier versions of Visual +Studio have bugs, are not completely compatible, or do not support the C++ +standard well enough. + +You will also need the `CMake `_ build system since it +generates the project files you will use to build with. + +If you would like to run the LLVM tests you will need `Python +`_. Versions 2.4-2.7 are known to work. You will need +`GnuWin32 `_ tools, too. + +Do not install the LLVM directory tree into a path containing spaces (e.g. +``C:\Documents and Settings\...``) as the configure step will fail. + + +Getting Started +=============== +Here's the short story for getting up and running quickly with LLVM: + +1. Read the documentation. +2. Seriously, read the documentation. +3. Remember that you were warned twice about reading the documentation. +4. Get the Source Code + + * With the distributed files: + + 1. ``cd `` + 2. ``gunzip --stdout llvm-VERSION.tar.gz | tar -xvf -`` + (*or use WinZip*) + 3. ``cd llvm`` + + * With anonymous Subversion access: + + 1. ``cd `` + 2. ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm`` + 3. ``cd llvm`` + +5. Use `CMake `_ to generate up-to-date project files: + + * Once CMake is installed then the simplest way is to just start the + CMake GUI, select the directory where you have LLVM extracted to, and + the default options should all be fine. One option you may really + want to change, regardless of anything else, might be the + ``CMAKE_INSTALL_PREFIX`` setting to select a directory to INSTALL to + once compiling is complete, although installation is not mandatory for + using LLVM. Another important option is ``LLVM_TARGETS_TO_BUILD``, + which controls the LLVM target architectures that are included on the + build. + * See the `LLVM CMake guide `_ for detailed information about + how to configure the LLVM build. + +6. Start Visual Studio + + * In the directory you created the project files will have an ``llvm.sln`` + file, just double-click on that to open Visual Studio. + +7. Build the LLVM Suite: + + * The projects may still be built individually, but to build them all do + not just select all of them in batch build (as some are meant as + configuration projects), but rather select and build just the + ``ALL_BUILD`` project to build everything, or the ``INSTALL`` project, + which first builds the ``ALL_BUILD`` project, then installs the LLVM + headers, libs, and other useful things to the directory set by the + ``CMAKE_INSTALL_PREFIX`` setting when you first configured CMake. + * The Fibonacci project is a sample program that uses the JIT. Modify the + project's debugging properties to provide a numeric command line argument + or run it from the command line. The program will print the + corresponding fibonacci value. + +8. Test LLVM on Visual Studio: + + * If ``%PATH%`` does not contain GnuWin32, you may specify + ``LLVM_LIT_TOOLS_DIR`` on CMake for the path to GnuWin32. + * You can run LLVM tests by merely building the project "check". The test + results will be shown in the VS output window. + +.. FIXME: Is it up-to-date? + +9. Test LLVM: + + * The LLVM tests can be run by changing directory to the llvm source + directory and running: + + .. code-block:: bat + + C:\..\llvm> python ..\build\bin\llvm-lit --param build_config=Win32 --param build_mode=Debug --param llvm_site_config=../build/test/lit.site.cfg test + + This example assumes that Python is in your PATH variable, you + have built a Win32 Debug version of llvm with a standard out of + line build. You should not see any unexpected failures, but will + see many unsupported tests and expected failures. + + A specific test or test directory can be run with: + + .. code-block:: bat + + C:\..\llvm> python ..\build\bin\llvm-lit --param build_config=Win32 --param build_mode=Debug --param llvm_site_config=../build/test/lit.site.cfg test/path/to/test + + +An Example Using the LLVM Tool Chain +==================================== + +1. First, create a simple C file, name it '``hello.c``': + + .. code-block:: c + + #include + int main() { + printf("hello world\n"); + return 0; + } + +2. Next, compile the C file into an LLVM bitcode file: + + .. code-block:: bat + + C:\..> clang -c hello.c -emit-llvm -o hello.bc + + This will create the result file ``hello.bc`` which is the LLVM bitcode + that corresponds the compiled program and the library facilities that + it required. You can execute this file directly using ``lli`` tool, + compile it to native assembly with the ``llc``, optimize or analyze it + further with the ``opt`` tool, etc. + + Alternatively you can directly output an executable with clang with: + + .. code-block:: bat + + C:\..> clang hello.c -o hello.exe + + The ``-o hello.exe`` is required because clang currently outputs ``a.out`` + when neither ``-o`` nor ``-c`` are given. + +3. Run the program using the just-in-time compiler: + + .. code-block:: bat + + C:\..> lli hello.bc + +4. Use the ``llvm-dis`` utility to take a look at the LLVM assembly code: + + .. code-block:: bat + + C:\..> llvm-dis < hello.bc | more + +5. Compile the program to object code using the LLC code generator: + + .. code-block:: bat + + C:\..> llc -filetype=obj hello.bc + +6. Link to binary using Microsoft link: + + .. code-block:: bat + + C:\..> link hello.obj -defaultlib:libcmt + +7. Execute the native code program: + + .. code-block:: bat + + C:\..> hello.exe + + +Common Problems +=============== +If you are having problems building or using LLVM, or if you have any other +general questions about LLVM, please consult the `Frequently Asked Questions +`_ page. + + +Links +===== +This document is just an **introduction** to how to use LLVM to do some simple +things... there are many more interesting and complicated things that you can +do that aren't documented here (but we'll gladly accept a patch if you want to +write something up!). For more information about LLVM, check out: + +* `LLVM homepage `_ +* `LLVM doxygen tree `_ + diff --git a/docs/GoldPlugin.rst b/docs/GoldPlugin.rst new file mode 100644 index 00000000..28b202ad --- /dev/null +++ b/docs/GoldPlugin.rst @@ -0,0 +1,172 @@ +==================== +The LLVM gold plugin +==================== + +Introduction +============ + +Building with link time optimization requires cooperation from +the system linker. LTO support on Linux systems requires that you use the +`gold linker`_ which supports LTO via plugins. This is the same mechanism +used by the `GCC LTO`_ project. + +The LLVM gold plugin implements the gold plugin interface on top of +:ref:`libLTO`. The same plugin can also be used by other tools such as +``ar`` and ``nm``. + +.. _`gold linker`: http://sourceware.org/binutils +.. _`GCC LTO`: http://gcc.gnu.org/wiki/LinkTimeOptimization +.. _`gold plugin interface`: http://gcc.gnu.org/wiki/whopr/driver + +.. _lto-how-to-build: + +How to build it +=============== + +You need to have gold with plugin support and build the LLVMgold plugin. +Check whether you have gold running ``/usr/bin/ld -v``. It will report "GNU +gold" or else "GNU ld" if not. If you have gold, check for plugin support +by running ``/usr/bin/ld -plugin``. If it complains "missing argument" then +you have plugin support. If not, such as an "unknown option" error then you +will either need to build gold or install a version with plugin support. + +* Download, configure and build gold with plugin support: + + .. code-block:: bash + + $ git clone --depth 1 git://sourceware.org/git/binutils-gdb.git binutils + $ mkdir build + $ cd build + $ ../binutils/configure --enable-gold --enable-plugins --disable-werror + $ make all-gold + + That should leave you with ``build/gold/ld-new`` which supports + the ``-plugin`` option. Running ``make`` will additionally build + ``build/binutils/ar`` and ``nm-new`` binaries supporting plugins. + +* Build the LLVMgold plugin: Configure LLVM with + ``--with-binutils-include=/path/to/binutils/include`` and run + ``make``. + +Usage +===== + +The linker takes a ``-plugin`` option that points to the path of +the plugin ``.so`` file. To find out what link command ``gcc`` +would run in a given situation, run ``gcc -v [...]`` and +look for the line where it runs ``collect2``. Replace that with +``ld-new -plugin /path/to/LLVMgold.so`` to test it out. Once you're +ready to switch to using gold, backup your existing ``/usr/bin/ld`` +then replace it with ``ld-new``. + +You should produce bitcode files from ``clang`` with the option +``-flto``. This flag will also cause ``clang`` to look for the gold plugin in +the ``lib`` directory under its prefix and pass the ``-plugin`` option to +``ld``. It will not look for an alternate linker, which is why you need +gold to be the installed system linker in your path. + +``ar`` and ``nm`` also accept the ``-plugin`` option and it's possible to +to install ``LLVMgold.so`` to ``/usr/lib/bfd-plugins`` for a seamless setup. +If you built your own gold, be sure to install the ``ar`` and ``nm-new`` you +built to ``/usr/bin``. + + +Example of link time optimization +--------------------------------- + +The following example shows a worked example of the gold plugin mixing LLVM +bitcode and native code. + +.. code-block:: c + + --- a.c --- + #include + + extern void foo1(void); + extern void foo4(void); + + void foo2(void) { + printf("Foo2\n"); + } + + void foo3(void) { + foo4(); + } + + int main(void) { + foo1(); + } + + --- b.c --- + #include + + extern void foo2(void); + + void foo1(void) { + foo2(); + } + + void foo4(void) { + printf("Foo4"); + } + +.. code-block:: bash + + --- command lines --- + $ clang -flto a.c -c -o a.o # <-- a.o is LLVM bitcode file + $ ar q a.a a.o # <-- a.a is an archive with LLVM bitcode + $ clang b.c -c -o b.o # <-- b.o is native object file + $ clang -flto a.a b.o -o main # <-- link with LLVMgold plugin + +Gold informs the plugin that foo3 is never referenced outside the IR, +leading LLVM to delete that function. However, unlike in the :ref:`libLTO +example ` gold does not currently eliminate foo4. + +Quickstart for using LTO with autotooled projects +================================================= + +Once your system ``ld``, ``ar``, and ``nm`` all support LLVM bitcode, +everything is in place for an easy to use LTO build of autotooled projects: + +* Follow the instructions :ref:`on how to build LLVMgold.so + `. + +* Install the newly built binutils to ``$PREFIX`` + +* Copy ``Release/lib/LLVMgold.so`` to ``$PREFIX/lib/bfd-plugins/`` + +* Set environment variables (``$PREFIX`` is where you installed clang and + binutils): + + .. code-block:: bash + + export CC="$PREFIX/bin/clang -flto" + export CXX="$PREFIX/bin/clang++ -flto" + export AR="$PREFIX/bin/ar" + export NM="$PREFIX/bin/nm" + export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a + +* Or you can just set your path: + + .. code-block:: bash + + export PATH="$PREFIX/bin:$PATH" + export CC="clang -flto" + export CXX="clang++ -flto" + export RANLIB=/bin/true +* Configure and build the project as usual: + + .. code-block:: bash + + % ./configure && make && make check + +The environment variable settings may work for non-autotooled projects too, +but you may need to set the ``LD`` environment variable as well. + +Licensing +========= + +Gold is licensed under the GPLv3. LLVMgold uses the interface file +``plugin-api.h`` from gold which means that the resulting ``LLVMgold.so`` +binary is also GPLv3. This can still be used to link non-GPLv3 programs +just as much as gold could without the plugin. diff --git a/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt b/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt new file mode 100644 index 00000000..f0861811 --- /dev/null +++ b/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt @@ -0,0 +1,74 @@ +Date: Sat, 18 Nov 2000 09:19:35 -0600 (CST) +From: Vikram Adve +To: Chris Lattner +Subject: a few thoughts + +I've been mulling over the virtual machine problem and I had some +thoughts about some things for us to think about discuss: + +1. We need to be clear on our goals for the VM. Do we want to emphasize + portability and safety like the Java VM? Or shall we focus on the + architecture interface first (i.e., consider the code generation and + processor issues), since the architecture interface question is also + important for portable Java-type VMs? + + This is important because the audiences for these two goals are very + different. Architects and many compiler people care much more about + the second question. The Java compiler and OS community care much more + about the first one. + + Also, while the architecture interface question is important for + Java-type VMs, the design constraints are very different. + + +2. Design issues to consider (an initial list that we should continue + to modify). Note that I'm not trying to suggest actual solutions here, + but just various directions we can pursue: + + a. A single-assignment VM, which we've both already been thinking about. + + b. A strongly-typed VM. One question is do we need the types to be + explicitly declared or should they be inferred by the dynamic compiler? + + c. How do we get more high-level information into the VM while keeping + to a low-level VM design? + + o Explicit array references as operands? An alternative is + to have just an array type, and let the index computations be + separate 3-operand instructions. + + o Explicit instructions to handle aliasing, e.g.s: + -- an instruction to say "I speculate that these two values are not + aliased, but check at runtime", like speculative execution in + EPIC? + -- or an instruction to check whether two values are aliased and + execute different code depending on the answer, somewhat like + predicated code in EPIC + + o (This one is a difficult but powerful idea.) + A "thread-id" field on every instruction that allows the static + compiler to generate a set of parallel threads, and then have + the runtime compiler and hardware do what they please with it. + This has very powerful uses, but thread-id on every instruction + is expensive in terms of instruction size and code size. + We would need to compactly encode it somehow. + + Also, this will require some reading on at least two other + projects: + -- Multiscalar architecture from Wisconsin + -- Simultaneous multithreading architecture from Washington + + o Or forget all this and stick to a traditional instruction set? + + +BTW, on an unrelated note, after the meeting yesterday, I did remember +that you had suggested doing instruction scheduling on SSA form instead +of a dependence DAG earlier in the semester. When we talked about +it yesterday, I didn't remember where the idea had come from but I +remembered later. Just giving credit where its due... + +Perhaps you can save the above as a file under RCS so you and I can +continue to expand on this. + +--Vikram + diff --git a/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt b/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt new file mode 100644 index 00000000..81ca5391 --- /dev/null +++ b/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt @@ -0,0 +1,199 @@ +Date: Sun, 19 Nov 2000 16:23:57 -0600 (CST) +From: Chris Lattner +To: Vikram Adve +Subject: Re: a few thoughts + +Okay... here are a few of my thoughts on this (it's good to know that we +think so alike!): + +> 1. We need to be clear on our goals for the VM. Do we want to emphasize +> portability and safety like the Java VM? Or shall we focus on the +> architecture interface first (i.e., consider the code generation and +> processor issues), since the architecture interface question is also +> important for portable Java-type VMs? + +I forsee the architecture looking kinda like this: (which is completely +subject to change) + +1. The VM code is NOT guaranteed safe in a java sense. Doing so makes it + basically impossible to support C like languages. Besides that, + certifying a register based language as safe at run time would be a + pretty expensive operation to have to do. Additionally, we would like + to be able to statically eliminate many bounds checks in Java + programs... for example. + + 2. Instead, we can do the following (eventually): + * Java bytecode is used as our "safe" representation (to avoid + reinventing something that we don't add much value to). When the + user chooses to execute Java bytecodes directly (ie, not + precompiled) the runtime compiler can do some very simple + transformations (JIT style) to convert it into valid input for our + VM. Performance is not wonderful, but it works right. + * The file is scheduled to be compiled (rigorously) at a later + time. This could be done by some background process or by a second + processor in the system during idle time or something... + * To keep things "safe" ie to enforce a sandbox on Java/foreign code, + we could sign the generated VM code with a host specific private + key. Then before the code is executed/loaded, we can check to see if + the trusted compiler generated the code. This would be much quicker + than having to validate consistency (especially if bounds checks have + been removed, for example) + +> This is important because the audiences for these two goals are very +> different. Architects and many compiler people care much more about +> the second question. The Java compiler and OS community care much more +> about the first one. + +3. By focusing on a more low level virtual machine, we have much more room + for value add. The nice safe "sandbox" VM can be provided as a layer + on top of it. It also lets us focus on the more interesting compilers + related projects. + +> 2. Design issues to consider (an initial list that we should continue +> to modify). Note that I'm not trying to suggest actual solutions here, +> but just various directions we can pursue: + +Understood. :) + +> a. A single-assignment VM, which we've both already been thinking +> about. + +Yup, I think that this makes a lot of sense. I am still intrigued, +however, by the prospect of a minimally allocated VM representation... I +think that it could have definite advantages for certain applications +(think very small machines, like PDAs). I don't, however, think that our +initial implementations should focus on this. :) + +Here are some other auxiliary goals that I think we should consider: + +1. Primary goal: Support a high performance dynamic compilation + system. This means that we have an "ideal" division of labor between + the runtime and static compilers. Of course, the other goals of the + system somewhat reduce the importance of this point (f.e. portability + reduces performance, but hopefully not much) +2. Portability to different processors. Since we are most familiar with + x86 and solaris, I think that these two are excellent candidates when + we get that far... +3. Support for all languages & styles of programming (general purpose + VM). This is the point that disallows java style bytecodes, where all + array refs are checked for bounds, etc... +4. Support linking between different language families. For example, call + C functions directly from Java without using the nasty/slow/gross JNI + layer. This involves several subpoints: + A. Support for languages that require garbage collectors and integration + with languages that don't. As a base point, we could insist on + always using a conservative GC, but implement free as a noop, f.e. + +> b. A strongly-typed VM. One question is do we need the types to be +> explicitly declared or should they be inferred by the dynamic +> compiler? + + B. This is kind of similar to another idea that I have: make OOP + constructs (virtual function tables, class heirarchies, etc) explicit + in the VM representation. I believe that the number of additional + constructs would be fairly low, but would give us lots of important + information... something else that would/could be important is to + have exceptions as first class types so that they would be handled in + a uniform way for the entire VM... so that C functions can call Java + functions for example... + +> c. How do we get more high-level information into the VM while keeping +> to a low-level VM design? +> o Explicit array references as operands? An alternative is +> to have just an array type, and let the index computations be +> separate 3-operand instructions. + + C. In the model I was thinking of (subject to change of course), we + would just have an array type (distinct from the pointer + types). This would allow us to have arbitrarily complex index + expressions, while still distinguishing "load" from "Array load", + for example. Perhaps also, switch jump tables would be first class + types as well? This would allow better reasoning about the program. + +5. Support dynamic loading of code from various sources. Already + mentioned above was the example of loading java bytecodes, but we want + to support dynamic loading of VM code as well. This makes the job of + the runtime compiler much more interesting: it can do interprocedural + optimizations that the static compiler can't do, because it doesn't + have all of the required information (for example, inlining from + shared libraries, etc...) + +6. Define a set of generally useful annotations to add to the VM + representation. For example, a function can be analysed to see if it + has any sideeffects when run... also, the MOD/REF sets could be + calculated, etc... we would have to determine what is reasonable. This + would generally be used to make IP optimizations cheaper for the + runtime compiler... + +> o Explicit instructions to handle aliasing, e.g.s: +> -- an instruction to say "I speculate that these two values are not +> aliased, but check at runtime", like speculative execution in +> EPIC? +> -- or an instruction to check whether two values are aliased and +> execute different code depending on the answer, somewhat like +> predicated code in EPIC + +These are also very good points... if this can be determined at compile +time. I think that an epic style of representation (not the instruction +packing, just the information presented) could be a very interesting model +to use... more later... + +> o (This one is a difficult but powerful idea.) +> A "thread-id" field on every instruction that allows the static +> compiler to generate a set of parallel threads, and then have +> the runtime compiler and hardware do what they please with it. +> This has very powerful uses, but thread-id on every instruction +> is expensive in terms of instruction size and code size. +> We would need to compactly encode it somehow. + +Yes yes yes! :) I think it would be *VERY* useful to include this kind +of information (which EPIC architectures *implicitly* encode. The trend +that we are seeing supports this greatly: + +1. Commodity processors are getting massive SIMD support: + * Intel/Amd MMX/MMX2 + * AMD's 3Dnow! + * Intel's SSE/SSE2 + * Sun's VIS +2. SMP is becoming much more common, especially in the server space. +3. Multiple processors on a die are right around the corner. + +If nothing else, not designing this in would severely limit our future +expansion of the project... + +> Also, this will require some reading on at least two other +> projects: +> -- Multiscalar architecture from Wisconsin +> -- Simultaneous multithreading architecture from Washington +> +> o Or forget all this and stick to a traditional instruction set? + +Heh... :) Well, from a pure research point of view, it is almost more +attactive to go with the most extreme/different ISA possible. On one axis +you get safety and conservatism, and on the other you get degree of +influence that the results have. Of course the problem with pure research +is that often times there is no concrete product of the research... :) + +> BTW, on an unrelated note, after the meeting yesterday, I did remember +> that you had suggested doing instruction scheduling on SSA form instead +> of a dependence DAG earlier in the semester. When we talked about +> it yesterday, I didn't remember where the idea had come from but I +> remembered later. Just giving credit where its due... + +:) Thanks. + +> Perhaps you can save the above as a file under RCS so you and I can +> continue to expand on this. + +I think it makes sense to do so when we get our ideas more formalized and +bounce it back and forth a couple of times... then I'll do a more formal +writeup of our goals and ideas. Obviously our first implementation will +not want to do all of the stuff that I pointed out above... be we will +want to design the project so that we do not artificially limit ourselves +at sometime in the future... + +Anyways, let me know what you think about these ideas... and if they sound +reasonable... + +-Chris + diff --git a/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt b/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt new file mode 100644 index 00000000..8c452924 --- /dev/null +++ b/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt @@ -0,0 +1,30 @@ +From: Chris Lattner [mailto:sabre@nondot.org] +Sent: Wednesday, December 06, 2000 6:41 PM +To: Vikram S. Adve +Subject: Additional idea with respect to encoding + +Here's another idea with respect to keeping the common case instruction +size down (less than 32 bits ideally): + +Instead of encoding an instruction to operate on two register numbers, +have it operate on two negative offsets based on the current register +number. Therefore, instead of using: + +r57 = add r55, r56 (r57 is the implicit dest register, of course) + +We could use: + +r57 = add -2, -1 + +My guess is that most SSA references are to recent values (especially if +they correspond to expressions like (x+y*z+p*q/ ...), so the negative +numbers would tend to stay small, even at the end of the procedure (where +the implicit register destination number could be quite large). Of course +the negative sign is reduntant, so you would be storing small integers +almost all of the time, and 5-6 bits worth of register number would be +plenty for most cases... + +What do you think? + +-Chris + diff --git a/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt b/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt new file mode 100644 index 00000000..01b644b3 --- /dev/null +++ b/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt @@ -0,0 +1,83 @@ +SUMMARY +------- + +We met to discuss the LLVM instruction format and bytecode representation: + +ISSUES RESOLVED +--------------- + +1. We decided that we shall use a flat namespace to represent our + variables in SSA form, as opposed to having a two dimensional namespace + of the original variable and the SSA instance subscript. + +ARGUMENT AGAINST: + * A two dimensional namespace would be valuable when doing alias + analysis because the extra information can help limit the scope of + analysis. + +ARGUMENT FOR: + * Including this information would require that all users of the LLVM + bytecode would have to parse and handle it. This would slow down the + common case and inflate the instruction representation with another + infinite variable space. + +REASONING: + * It was decided that because original variable sources could be + reconstructed from SSA form in linear time, that it would be an + unjustified expense for the common case to include the extra + information for one optimization. Alias analysis itself is typically + greater than linear in asymptotic complexity, so this extra analaysis + would not affect the runtime of the optimization in a significant + way. Additionally, this would be an unlikely optimization to do at + runtime. + + +IDEAS TO CONSIDER +----------------- + +1. Including dominator information in the LLVM bytecode + representation. This is one example of an analysis result that may be + packaged with the bytecodes themselves. As a conceptual implementation + idea, we could include an immediate dominator number for each basic block + in the LLVM bytecode program. Basic blocks could be numbered according + to the order of occurrence in the bytecode representation. + +2. Including loop header and body information. This would facilitate + detection of intervals and natural loops. + +UNRESOLVED ISSUES +----------------- + +1. Will oSUIF provide enough of an infrastructure to support the research + that we will be doing? We know that it has less than stellar + performance, but hope that this will be of little importance for our + static compiler. This could affect us if we decided to do some IP + research. Also we do not yet understand the level of exception support + currently implemented. + +2. Should we consider the requirements of a direct hardware implementation + of the LLVM when we design it? If so, several design issues should + have their priorities shifted. The other option is to focus on a + software layer interpreting the LLVM in all cases. + +3. Should we use some form of packetized format to improve forward + compatibility? For example, we could design the system to encode a + packet type and length field before analysis information, to allow a + runtime to skip information that it didn't understand in a bytecode + stream. The obvious benefit would be for compatibility, the drawback + is that it would tend to splinter that 'standard' LLVM definition. + +4. Should we use fixed length instructions or variable length + instructions? Fetching variable length instructions is expensive (for + either hardware or software based LLVM runtimes), but we have several + 'infinite' spaces that instructions operate in (SSA register numbers, + type spaces, or packet length [if packets were implemented]). Several + options were mentioned including: + A. Using 16 or 32 bit numbers, which would be 'big enough' + B. A scheme similar to how UTF-8 works, to encode infinite numbers + while keeping small number small. + C. Use something similar to Huffman encoding, so that the most common + numbers are the smallest. + +-Chris + diff --git a/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt b/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt new file mode 100644 index 00000000..111706a3 --- /dev/null +++ b/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt @@ -0,0 +1,39 @@ +Date: Wed, 31 Jan 2001 12:04:33 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: another thought + +I have a budding idea about making LLVM a little more ambitious: a +customizable runtime system that can be used to implement language-specific +virtual machines for many different languages. E.g., a C vm, a C++ vm, a +Java vm, a Lisp vm, .. + +The idea would be that LLVM would provide a standard set of runtime features +(some low-level like standard assembly instructions with code generation and +static and runtime optimization; some higher-level like type-safety and +perhaps a garbage collection library). Each language vm would select the +runtime features needed for that language, extending or customizing them as +needed. Most of the machine-dependent code-generation and optimization +features as well as low-level machine-independent optimizations (like PRE) +could be provided by LLVM and should be sufficient for any language, +simplifying the language compiler. (This would also help interoperability +between languages.) Also, some or most of the higher-level +machine-independent features like type-safety and access safety should be +reusable by different languages, with minor extensions. The language +compiler could then focus on language-specific analyses and optimizations. + +The risk is that this sounds like a universal IR -- something that the +compiler community has tried and failed to develop for decades, and is +universally skeptical about. No matter what we say, we won't be able to +convince anyone that we have a universal IR that will work. We need to +think about whether LLVM is different or if has something novel that might +convince people. E.g., the idea of providing a package of separable +features that different languages select from. Also, using SSA with or +without type-safety as the intermediate representation. + +One interesting starting point would be to discuss how a JVM would be +implemented on top of LLVM a bit more. That might give us clues on how to +structure LLVM to support one or more language VMs. + +--Vikram + diff --git a/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt b/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt new file mode 100644 index 00000000..c09cf1f0 --- /dev/null +++ b/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt @@ -0,0 +1,67 @@ +Date: Tue, 6 Feb 2001 20:27:37 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: Type notation debate... + +This is the way that I am currently planning on implementing types: + +Primitive Types: +type ::= void|bool|sbyte|ubyte|short|ushort|int|uint|long|ulong + +Method: +typelist ::= typelisth | /*empty*/ +typelisth ::= type | typelisth ',' type +type ::= type (typelist) + +Arrays (without and with size): +type ::= '[' type ']' | '[' INT ',' type ']' + +Pointer: +type ::= type '*' + +Structure: +type ::= '{' typelist '}' + +Packed: +type ::= '<' INT ',' type '>' + +Simple examples: + +[[ %4, int ]] - array of (array of 4 (int)) +[ { int, int } ] - Array of structure +[ < %4, int > ] - Array of 128 bit SIMD packets +int (int, [[int, %4]]) - Method taking a 2d array and int, returning int + + +Okay before you comment, please look at: + +http://www.research.att.com/~bs/devXinterview.html + +Search for "In another interview, you defined the C declarator syntax as +an experiment that failed. However, this syntactic construct has been +around for 27 years and perhaps more; why do you consider it problematic +(except for its cumbersome syntax)?" and read that response for me. :) + +Now with this syntax, his example would be represented as: + +[ %10, bool (int, int) * ] * + +vs + +bool (*(*)[10])(int, int) + +in C. + +Basically, my argument for this type construction system is that it is +VERY simple to use and understand (although it IS different than C, it is +very simple and straightforward, which C is NOT). In fact, I would assert +that most programmers TODAY do not understand pointers to member +functions, and have to look up an example when they have to write them. + +In my opinion, it is critically important to have clear and concise type +specifications, because types are going to be all over the programs. + +Let me know your thoughts on this. :) + +-Chris + diff --git a/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt b/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt new file mode 100644 index 00000000..8bfefbf6 --- /dev/null +++ b/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt @@ -0,0 +1,75 @@ +Date: Thu, 8 Feb 2001 08:42:04 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: RE: Type notation debate... + +Chris, + +> Okay before you comment, please look at: +> +> http://www.research.att.com/~bs/devXinterview.html + +I read this argument. Even before that, I was already in agreement with you +and him that the C declarator syntax is difficult and confusing. + +But in fact, if you read the entire answer carefully, he came to the same +conclusion I do: that you have to go with familiar syntax over logical +syntax because familiarity is such a strong force: + + "However, familiarity is a strong force. To compare, in English, we +live +more or less happily with the absurd rules for "to be" (am, are, is, been, +was, were, ...) and all attempts to simplify are treated with contempt or +(preferably) humor. It be a curious world and it always beed." + +> Basically, my argument for this type construction system is that it is +> VERY simple to use and understand (although it IS different than C, it is +> very simple and straightforward, which C is NOT). In fact, I would assert +> that most programmers TODAY do not understand pointers to member +> functions, and have to look up an example when they have to write them. + +Again, I don't disagree with this at all. But to some extent this +particular problem is inherently difficult. Your syntax for the above +example may be easier for you to read because this is the way you have been +thinking about it. Honestly, I don't find it much easier than the C syntax. +In either case, I would have to look up an example to write pointers to +member functions. + +But pointers to member functions are nowhere near as common as arrays. And +the old array syntax: + type [ int, int, ...] +is just much more familiar and clear to people than anything new you +introduce, no matter how logical it is. Introducing a new syntax that may +make function pointers easier but makes arrays much more difficult seems +very risky to me. + +> In my opinion, it is critically important to have clear and concise type +> specifications, because types are going to be all over the programs. + +I absolutely agree. But the question is, what is more clear and concise? +The syntax programmers are used to out of years of experience or a new +syntax that they have never seen that has a more logical structure. I think +the answer is the former. Sometimes, you have to give up a better idea +because you can't overcome sociological barriers to it. Qwerty keyboards +and Windows are two classic examples of bad technology that are difficult to +root out. + +P.S. Also, while I agree that most your syntax is more logical, there is +one part that isn't: + +Arrays (without and with size): +type ::= '[' type ']' | '[' INT ',' type ']'. + +The arrays with size lists the dimensions and the type in a single list. +That is just too confusing: + [10, 40, int] +This seems to be a 3-D array where the third dimension is something strange. +It is too confusing to have a list of 3 things, some of which are dimensions +and one is a type. Either of the following would be better: + + array [10, 40] of int +or + int [10, 40] + +--Vikram + diff --git a/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt b/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt new file mode 100644 index 00000000..6e978415 --- /dev/null +++ b/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt @@ -0,0 +1,53 @@ +Date: Thu, 8 Feb 2001 14:31:05 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Type notation debate... + +> Arrays (without and with size): +> type ::= '[' type ']' | '[' INT ',' type ']'. +> +> The arrays with size lists the dimensions and the type in a single list. +> That is just too confusing: + +> [10, 40, int] +> This seems to be a 3-D array where the third dimension is something strange. +> It is too confusing to have a list of 3 things, some of which are dimensions +> and one is a type. + +The above grammar indicates that there is only one integer parameter, ie +the upper bound. The lower bound is always implied to be zero, for +several reasons: + +* As a low level VM, we want to expose addressing computations + explicitly. Since the lower bound must always be known in a high level + language statically, the language front end can do the translation + automatically. +* This fits more closely with what Java needs, ie what we need in the + short term. Java arrays are always zero based. + +If a two element list is too confusing, I would recommend an alternate +syntax of: + +type ::= '[' type ']' | '[' INT 'x' type ']'. + +For example: + [12 x int] + [12x int] + [ 12 x [ 4x int ]] + +Which is syntactically nicer, and more explicit. + +> Either of the following would be better: +> array [10, 40] of int + +I considered this approach for arrays in general (ie array of int/ array +of 12 int), but found that it made declarations WAY too long. Remember +that because of the nature of llvm, you get a lot of types strewn all over +the program, and using the 'typedef' like facility is not a wonderful +option, because then types aren't explicit anymore. + +I find this email interesting, because you contradict the previous email +you sent, where you recommend that we stick to C syntax.... + +-Chris + diff --git a/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt b/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt new file mode 100644 index 00000000..83973244 --- /dev/null +++ b/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt @@ -0,0 +1,89 @@ +> But in fact, if you read the entire answer carefully, he came to the same +> conclusion I do: that you have to go with familiar syntax over logical +> syntax because familiarity is such a strong force: +> "However, familiarity is a strong force. To compare, in English, we +live +> more or less happily with the absurd rules for "to be" (am, are, is, been, +> was, were, ...) and all attempts to simplify are treated with contempt or +> (preferably) humor. It be a curious world and it always beed." + +Although you have to remember that his situation was considerably +different than ours. He was in a position where he was designing a high +level language that had to be COMPATIBLE with C. Our language is such +that a new person would have to learn the new, different, syntax +anyways. Making them learn about the type system does not seem like much +of a stretch from learning the opcodes and how SSA form works, and how +everything ties together... + +> > Basically, my argument for this type construction system is that it is +> > VERY simple to use and understand (although it IS different than C, it is +> > very simple and straightforward, which C is NOT). In fact, I would assert +> > that most programmers TODAY do not understand pointers to member +> > functions, and have to look up an example when they have to write them. + +> Again, I don't disagree with this at all. But to some extent this +> particular problem is inherently difficult. Your syntax for the above +> example may be easier for you to read because this is the way you have been +> thinking about it. Honestly, I don't find it much easier than the C syntax. +> In either case, I would have to look up an example to write pointers to +> member functions. + +I would argue that because the lexical structure of the language is self +consistent, any person who spent a significant amount of time programming +in LLVM directly would understand how to do it without looking it up in a +manual. The reason this does not work for C is because you rarely have to +declare these pointers, and the syntax is inconsistent with the method +declaration and calling syntax. + +> But pointers to member functions are nowhere near as common as arrays. + +Very true. If you're implementing an object oriented language, however, +remember that you have to do all the pointer to member function stuff +yourself.... so every time you invoke a virtual method one is involved +(instead of having C++ hide it for you behind "syntactic sugar"). + +> And the old array syntax: +> type [ int, int, ...] +> is just much more familiar and clear to people than anything new you +> introduce, no matter how logical it is. + +Erm... excuse me but how is this the "old array syntax"? If you are +arguing for consistency with C, you should be asking for 'type int []', +which is significantly different than the above (beside the above +introduces a new operator and duplicates information +needlessly). Basically what I am suggesting is exactly the above without +the fluff. So instead of: + + type [ int, int, ...] + +you use: + + type [ int ] + +> Introducing a new syntax that may +> make function pointers easier but makes arrays much more difficult seems +> very risky to me. + +This is not about function pointers. This is about consistency in the +type system, and consistency with the rest of the language. The point +above does not make arrays any more difficult to use, and makes the +structure of types much more obvious than the "c way". + +> > In my opinion, it is critically important to have clear and concise type +> > specifications, because types are going to be all over the programs. +> +> I absolutely agree. But the question is, what is more clear and concise? +> The syntax programmers are used to out of years of experience or a new +> syntax that they have never seen that has a more logical structure. I think +> the answer is the former. Sometimes, you have to give up a better idea +> because you can't overcome sociological barriers to it. Qwerty keyboards +> and Windows are two classic examples of bad technology that are difficult to +> root out. + +Very true, but you seem to be advocating a completely different Type +system than C has, in addition to it not offering the advantages of clear +structure that the system I recommended does... so you seem to not have a +problem with changing this, just with what I change it to. :) + +-Chris + diff --git a/docs/HistoricalNotes/2001-02-09-AdveComments.txt b/docs/HistoricalNotes/2001-02-09-AdveComments.txt new file mode 100644 index 00000000..5503233c --- /dev/null +++ b/docs/HistoricalNotes/2001-02-09-AdveComments.txt @@ -0,0 +1,120 @@ +Ok, here are my comments and suggestions about the LLVM instruction set. +We should discuss some now, but can discuss many of them later, when we +revisit synchronization, type inference, and other issues. +(We have discussed some of the comments already.) + + +o We should consider eliminating the type annotation in cases where it is + essentially obvious from the instruction type, e.g., in br, it is obvious + that the first arg. should be a bool and the other args should be labels: + + br bool , label , label + + I think your point was that making all types explicit improves clarity + and readability. I agree to some extent, but it also comes at the cost + of verbosity. And when the types are obvious from people's experience + (e.g., in the br instruction), it doesn't seem to help as much. + + +o On reflection, I really like your idea of having the two different switch + types (even though they encode implementation techniques rather than + semantics). It should simplify building the CFG and my guess is it could + enable some significant optimizations, though we should think about which. + + +o In the lookup-indirect form of the switch, is there a reason not to make + the val-type uint? Most HLL switch statements (including Java and C++) + require that anyway. And it would also make the val-type uniform + in the two forms of the switch. + + I did see the switch-on-bool examples and, while cute, we can just use + the branch instructions in that particular case. + + +o I agree with your comment that we don't need 'neg'. + + +o There's a trade-off with the cast instruction: + + it avoids having to define all the upcasts and downcasts that are + valid for the operands of each instruction (you probably have thought + of other benefits also) + - it could make the bytecode significantly larger because there could + be a lot of cast operations + + +o Making the second arg. to 'shl' a ubyte seems good enough to me. + 255 positions seems adequate for several generations of machines + and is more compact than uint. + + +o I still have some major concerns about including malloc and free in the + language (either as builtin functions or instructions). LLVM must be + able to represent code from many different languages. Languages such as + C, C++ Java and Fortran 90 would not be able to use our malloc anyway + because each of them will want to provide a library implementation of it. + + This gets even worse when code from different languages is linked + into a single executable (which is fairly common in large apps). + Having a single malloc would just not suffice, and instead would simply + complicate the picture further because it adds an extra variant in + addition to the one each language provides. + + Instead, providing a default library version of malloc and free + (and perhaps a malloc_gc with garbage collection instead of free) + would make a good implementation available to anyone who wants it. + + I don't recall all your arguments in favor so let's discuss this again, + and soon. + + +o 'alloca' on the other hand sounds like a good idea, and the + implementation seems fairly language-independent so it doesn't have the + problems with malloc listed above. + + +o About indirect call: + Your option #2 sounded good to me. I'm not sure I understand your + concern about an explicit 'icall' instruction? + + +o A pair of important synchronization instr'ns to think about: + load-linked + store-conditional + + +o Other classes of instructions that are valuable for pipeline performance: + conditional-move + predicated instructions + + +o I believe tail calls are relatively easy to identify; do you know why + .NET has a tailcall instruction? + + +o I agree that we need a static data space. Otherwise, emulating global + data gets unnecessarily complex. + + +o About explicit parallelism: + + We once talked about adding a symbolic thread-id field to each + instruction. (It could be optional so single-threaded codes are + not penalized.) This could map well to multi-threaded architectures + while providing easy ILP for single-threaded onces. But it is probably + too radical an idea to include in a base version of LLVM. Instead, it + could a great topic for a separate study. + + What is the semantics of the IA64 stop bit? + + + + +o And finally, another thought about the syntax for arrays :-) + + Although this syntax: + array of + is verbose, it will be used only in the human-readable assembly code so + size should not matter. I think we should consider it because I find it + to be the clearest syntax. It could even make arrays of function + pointers somewhat readable. + diff --git a/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt b/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt new file mode 100644 index 00000000..da502636 --- /dev/null +++ b/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt @@ -0,0 +1,245 @@ +From: Chris Lattner +To: "Vikram S. Adve" +Subject: Re: LLVM Feedback + +I've included your feedback in the /home/vadve/lattner/llvm/docs directory +so that it will live in CVS eventually with the rest of LLVM. I've +significantly updated the documentation to reflect the changes you +suggested, as specified below: + +> We should consider eliminating the type annotation in cases where it is +> essentially obvious from the instruction type: +> br bool , label , label +> I think your point was that making all types explicit improves clarity +> and readability. I agree to some extent, but it also comes at the +> cost of verbosity. And when the types are obvious from people's +> experience (e.g., in the br instruction), it doesn't seem to help as +> much. + +Very true. We should discuss this more, but my reasoning is more of a +consistency argument. There are VERY few instructions that can have all +of the types eliminated, and doing so when available unnecessarily makes +the language more difficult to handle. Especially when you see 'int +%this' and 'bool %that' all over the place, I think it would be +disorienting to see: + + br %predicate, %iftrue, %iffalse + +for branches. Even just typing that once gives me the creeps. ;) Like I +said, we should probably discuss this further in person... + +> On reflection, I really like your idea of having the two different +> switch types (even though they encode implementation techniques rather +> than semantics). It should simplify building the CFG and my guess is it +> could enable some significant optimizations, though we should think +> about which. + +Great. I added a note to the switch section commenting on how the VM +should just use the instruction type as a hint, and that the +implementation may choose altermate representations (such as predicated +branches). + +> In the lookup-indirect form of the switch, is there a reason not to +> make the val-type uint? + +No. This was something I was debating for a while, and didn't really feel +strongly about either way. It is common to switch on other types in HLL's +(for example signed int's are particularly common), but in this case, all +that will be added is an additional 'cast' instruction. I removed that +from the spec. + +> I agree with your comment that we don't need 'neg' + +Removed. + +> There's a trade-off with the cast instruction: +> + it avoids having to define all the upcasts and downcasts that are +> valid for the operands of each instruction (you probably have +> thought of other benefits also) +> - it could make the bytecode significantly larger because there could +> be a lot of cast operations + + + You NEED casts to represent things like: + void foo(float); + ... + int x; + ... + foo(x); + in a language like C. Even in a Java like language, you need upcasts + and some way to implement dynamic downcasts. + + Not all forms of instructions take every type (for example you can't + shift by a floating point number of bits), thus SOME programs will need + implicit casts. + +To be efficient and to avoid your '-' point above, we just have to be +careful to specify that the instructions shall operate on all common +types, therefore casting should be relatively uncommon. For example all +of the arithmetic operations work on almost all data types. + +> Making the second arg. to 'shl' a ubyte seems good enough to me. +> 255 positions seems adequate for several generations of machines + +Okay, that comment is removed. + +> and is more compact than uint. + +No, it isn't. Remember that the bytecode encoding saves value slots into +the bytecode instructions themselves, not constant values. This is +another case where we may introduce more cast instructions (but we will +also reduce the number of opcode variants that must be supported by a +virtual machine). Because most shifts are by constant values, I don't +think that we'll have to cast many shifts. :) + +> I still have some major concerns about including malloc and free in the +> language (either as builtin functions or instructions). + +Agreed. How about this proposal: + +malloc/free are either built in functions or actual opcodes. They provide +all of the type safety that the document would indicate, blah blah +blah. :) + +Now, because of all of the excellent points that you raised, an +implementation may want to override the default malloc/free behavior of +the program. To do this, they simply implement a "malloc" and +"free" function. The virtual machine will then be defined to use the user +defined malloc/free function (which return/take void*'s, not type'd +pointers like the builtin function would) if one is available, otherwise +fall back on a system malloc/free. + +Does this sound like a good compromise? It would give us all of the +typesafety/elegance in the language while still allowing the user to do +all the cool stuff they want to... + +> 'alloca' on the other hand sounds like a good idea, and the +> implementation seems fairly language-independent so it doesn't have the +> problems with malloc listed above. + +Okay, once we get the above stuff figured out, I'll put it all in the +spec. + +> About indirect call: +> Your option #2 sounded good to me. I'm not sure I understand your +> concern about an explicit 'icall' instruction? + +I worry too much. :) The other alternative has been removed. 'icall' is +now up in the instruction list next to 'call'. + +> I believe tail calls are relatively easy to identify; do you know why +> .NET has a tailcall instruction? + +Although I am just guessing, I believe it probably has to do with the fact +that they want languages like Haskell and lisp to be efficiently runnable +on their VM. Of course this means that the VM MUST implement tail calls +'correctly', or else life will suck. :) I would put this into a future +feature bin, because it could be pretty handy... + +> A pair of important synchronization instr'ns to think about: +> load-linked +> store-conditional + +What is 'load-linked'? I think that (at least for now) I should add these +to the 'possible extensions' section, because they are not immediately +needed... + +> Other classes of instructions that are valuable for pipeline +> performance: +> conditional-move +> predicated instructions + +Conditional move is effectly a special case of a predicated +instruction... and I think that all predicated instructions can possibly +be implemented later in LLVM. It would significantly change things, and +it doesn't seem to be very necessary right now. It would seem to +complicate flow control analysis a LOT in the virtual machine. I would +tend to prefer that a predicated architecture like IA64 convert from a +"basic block" representation to a predicated rep as part of it's dynamic +complication phase. Also, if a basic block contains ONLY a move, then +that can be trivally translated into a conditional move... + +> I agree that we need a static data space. Otherwise, emulating global +> data gets unnecessarily complex. + +Definitely. Also a later item though. :) + +> We once talked about adding a symbolic thread-id field to each +> .. +> Instead, it could a great topic for a separate study. + +Agreed. :) + +> What is the semantics of the IA64 stop bit? + +Basically, the IA64 writes instructions like this: +mov ... +add ... +sub ... +op xxx +op xxx +;; +mov ... +add ... +sub ... +op xxx +op xxx +;; + +Where the ;; delimits a group of instruction with no dependencies between +them, which can all be executed concurrently (to the limits of the +available functional units). The ;; gets translated into a bit set in one +of the opcodes. + +The advantages of this representation is that you don't have to do some +kind of 'thread id scheduling' pass by having to specify ahead of time how +many threads to use, and the representation doesn't have a per instruction +overhead... + +> And finally, another thought about the syntax for arrays :-) +> Although this syntax: +> array of +> is verbose, it will be used only in the human-readable assembly code so +> size should not matter. I think we should consider it because I find it +> to be the clearest syntax. It could even make arrays of function +> pointers somewhat readable. + +My only comment will be to give you an example of why this is a bad +idea. :) + +Here is an example of using the switch statement (with my recommended +syntax): + +switch uint %val, label %otherwise, + [%3 x {uint, label}] [ { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } ] + +Here it is with the syntax you are proposing: + +switch uint %val, label %otherwise, + array %3 of {uint, label} + array of {uint, label} + { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } + +Which is ambiguous and very verbose. It would be possible to specify +constants with [] brackets as in my syntax, which would look like this: + +switch uint %val, label %otherwise, + array %3 of {uint, label} [ { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } ] + +But then the syntax is inconsistent between type definition and constant +definition (why do []'s enclose the constants but not the types??). + +Anyways, I'm sure that there is much debate still to be had over +this... :) + +-Chris + +http://www.nondot.org/~sabre/os/ +http://www.nondot.org/MagicStats/ +http://korbit.sourceforge.net/ + + diff --git a/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt b/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt new file mode 100644 index 00000000..2c7534d9 --- /dev/null +++ b/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt @@ -0,0 +1,39 @@ +Date: Tue, 13 Feb 2001 13:29:52 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: LLVM Concerns... + + +I've updated the documentation to include load store and allocation +instructions (please take a look and let me know if I'm on the right +track): + +file:/home/vadve/lattner/llvm/docs/LangRef.html#memoryops + +I have a couple of concerns I would like to bring up: + +1. Reference types + Right now, I've spec'd out the language to have a pointer type, which + works fine for lots of stuff... except that Java really has + references: constrained pointers that cannot be manipulated: added and + subtracted, moved, etc... Do we want to have a type like this? It + could be very nice for analysis (pointer always points to the start of + an object, etc...) and more closely matches Java semantics. The + pointer type would be kept for C++ like semantics. Through analysis, + C++ pointers could be promoted to references in the LLVM + representation. + +2. Our "implicit" memory references in assembly language: + After thinking about it, this model has two problems: + A. If you do pointer analysis and realize that two stores are + independent and can share the same memory source object, there is + no way to represent this in either the bytecode or assembly. + B. When parsing assembly/bytecode, we effectively have to do a full + SSA generation/PHI node insertion pass to build the dependencies + when we don't want the "pinned" representation. This is not + cool. + I'm tempted to make memory references explicit in both the assembly and + bytecode to get around this... what do you think? + +-Chris + diff --git a/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt b/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt new file mode 100644 index 00000000..50534337 --- /dev/null +++ b/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt @@ -0,0 +1,47 @@ +Date: Tue, 13 Feb 2001 18:25:42 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: RE: LLVM Concerns... + +> 1. Reference types +> Right now, I've spec'd out the language to have a pointer type, which +> works fine for lots of stuff... except that Java really has +> references: constrained pointers that cannot be manipulated: added and +> subtracted, moved, etc... Do we want to have a type like this? It +> could be very nice for analysis (pointer always points to the start of +> an object, etc...) and more closely matches Java semantics. The +> pointer type would be kept for C++ like semantics. Through analysis, +> C++ pointers could be promoted to references in the LLVM +> representation. + + +You're right, having references would be useful. Even for C++ the *static* +compiler could generate references instead of pointers with fairly +straightforward analysis. Let's include a reference type for now. But I'm +also really concerned that LLVM is becoming big and complex and (perhaps) +too high-level. After we get some initial performance results, we may have +a clearer idea of what our goals should be and we should revisit this +question then. + +> 2. Our "implicit" memory references in assembly language: +> After thinking about it, this model has two problems: +> A. If you do pointer analysis and realize that two stores are +> independent and can share the same memory source object, + +not sure what you meant by "share the same memory source object" + +> there is +> no way to represent this in either the bytecode or assembly. +> B. When parsing assembly/bytecode, we effectively have to do a full +> SSA generation/PHI node insertion pass to build the dependencies +> when we don't want the "pinned" representation. This is not +> cool. + +I understand the concern. But again, let's focus on the performance first +and then look at the language design issues. E.g., it would be good to know +how big the bytecode files are before expanding them further. I am pretty +keen to explore the implications of LLVM for mobile devices. Both bytecode +size and power consumption are important to consider there. + +--Vikram + diff --git a/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt b/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt new file mode 100644 index 00000000..5f7843ab --- /dev/null +++ b/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt @@ -0,0 +1,49 @@ +By Chris: + +LLVM has been designed with two primary goals in mind. First we strive to +enable the best possible division of labor between static and dynamic +compilers, and second, we need a flexible and powerful interface +between these two complementary stages of compilation. We feel that +providing a solution to these two goals will yield an excellent solution +to the performance problem faced by modern architectures and programming +languages. + +A key insight into current compiler and runtime systems is that a +compiler may fall in anywhere in a "continuum of compilation" to do its +job. On one side, scripting languages statically compile nothing and +dynamically compile (or equivalently, interpret) everything. On the far +other side, traditional static compilers process everything statically and +nothing dynamically. These approaches have typically been seen as a +tradeoff between performance and portability. On a deeper level, however, +there are two reasons that optimal system performance may be obtained by a +system somewhere in between these two extremes: Dynamic application +behavior and social constraints. + +From a technical perspective, pure static compilation cannot ever give +optimal performance in all cases, because applications have varying dynamic +behavior that the static compiler cannot take into consideration. Even +compilers that support profile guided optimization generate poor code in +the real world, because using such optimization tunes that application +to one particular usage pattern, whereas real programs (as opposed to +benchmarks) often have several different usage patterns. + +On a social level, static compilation is a very shortsighted solution to +the performance problem. Instruction set architectures (ISAs) continuously +evolve, and each implementation of an ISA (a processor) must choose a set +of tradeoffs that make sense in the market context that it is designed for. +With every new processor introduced, the vendor faces two fundamental +problems: First, there is a lag time between when a processor is introduced +to when compilers generate quality code for the architecture. Secondly, +even when compilers catch up to the new architecture there is often a large +body of legacy code that was compiled for previous generations and will +not or can not be upgraded. Thus a large percentage of code running on a +processor may be compiled quite sub-optimally for the current +characteristics of the dynamic execution environment. + +For these reasons, LLVM has been designed from the beginning as a long-term +solution to these problems. Its design allows the large body of platform +independent, static, program optimizations currently in compilers to be +reused unchanged in their current form. It also provides important static +type information to enable powerful dynamic and link time optimizations +to be performed quickly and efficiently. This combination enables an +increase in effective system performance for real world environments. diff --git a/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt b/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt new file mode 100644 index 00000000..b546301d --- /dev/null +++ b/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt @@ -0,0 +1,202 @@ +Meeting notes: Implementation idea: Exception Handling in C++/Java + +The 5/18/01 meeting discussed ideas for implementing exceptions in LLVM. +We decided that the best solution requires a set of library calls provided by +the VM, as well as an extension to the LLVM function invocation syntax. + +The LLVM function invocation instruction previously looks like this (ignoring +types): + + call func(arg1, arg2, arg3) + +The extension discussed today adds an optional "with" clause that +associates a label with the call site. The new syntax looks like this: + + call func(arg1, arg2, arg3) with funcCleanup + +This funcHandler always stays tightly associated with the call site (being +encoded directly into the call opcode itself), and should be used whenever +there is cleanup work that needs to be done for the current function if +an exception is thrown by func (or if we are in a try block). + +To support this, the VM/Runtime provide the following simple library +functions (all syntax in this document is very abstract): + +typedef struct { something } %frame; + The VM must export a "frame type", that is an opaque structure used to + implement different types of stack walking that may be used by various + language runtime libraries. We imagine that it would be typical to + represent a frame with a PC and frame pointer pair, although that is not + required. + +%frame getStackCurrentFrame(); + Get a frame object for the current function. Note that if the current + function was inlined into its caller, the "current" frame will belong to + the "caller". + +bool isFirstFrame(%frame f); + Returns true if the specified frame is the top level (first activated) frame + for this thread. For the main thread, this corresponds to the main() + function, for a spawned thread, it corresponds to the thread function. + +%frame getNextFrame(%frame f); + Return the previous frame on the stack. This function is undefined if f + satisfies the predicate isFirstFrame(f). + +Label *getFrameLabel(%frame f); + If a label was associated with f (as discussed below), this function returns + it. Otherwise, it returns a null pointer. + +doNonLocalBranch(Label *L); + At this point, it is not clear whether this should be a function or + intrinsic. It should probably be an intrinsic in LLVM, but we'll deal with + this issue later. + + +Here is a motivating example that illustrates how these facilities could be +used to implement the C++ exception model: + +void TestFunction(...) { + A a; B b; + foo(); // Any function call may throw + bar(); + C c; + + try { + D d; + baz(); + } catch (int) { + ...int Stuff... + // execution continues after the try block: the exception is consumed + } catch (double) { + ...double stuff... + throw; // Exception is propogated + } +} + +This function would compile to approximately the following code (heavy +pseudo code follows): + +Func: + %a = alloca A + A::A(%a) // These ctors & dtors could throw, but we ignore this + %b = alloca B // minor detail for this example + B::B(%b) + + call foo() with fooCleanup // An exception in foo is propogated to fooCleanup + call bar() with barCleanup // An exception in bar is propogated to barCleanup + + %c = alloca C + C::C(c) + %d = alloca D + D::D(d) + call baz() with bazCleanup // An exception in baz is propogated to bazCleanup + d->~D(); +EndTry: // This label corresponds to the end of the try block + c->~C() // These could also throw, these are also ignored + b->~B() + a->~A() + return + +Note that this is a very straight forward and literal translation: exactly +what we want for zero cost (when unused) exception handling. Especially on +platforms with many registers (ie, the IA64) setjmp/longjmp style exception +handling is *very* impractical. Also, the "with" clauses describe the +control flow paths explicitly so that analysis is not adversly effected. + +The foo/barCleanup labels are implemented as: + +TryCleanup: // Executed if an exception escapes the try block + c->~C() +barCleanup: // Executed if an exception escapes from bar() + // fall through +fooCleanup: // Executed if an exception escapes from foo() + b->~B() + a->~A() + Exception *E = getThreadLocalException() + call throw(E) // Implemented by the C++ runtime, described below + +Which does the work one would expect. getThreadLocalException is a function +implemented by the C++ support library. It returns the current exception +object for the current thread. Note that we do not attempt to recycle the +shutdown code from before, because performance of the mainline code is +critically important. Also, obviously fooCleanup and barCleanup may be +merged and one of them eliminated. This just shows how the code generator +would most likely emit code. + +The bazCleanup label is more interesting. Because the exception may be caught +by the try block, we must dispatch to its handler... but it does not exist +on the call stack (it does not have a VM Call->Label mapping installed), so +we must dispatch statically with a goto. The bazHandler thus appears as: + +bazHandler: + d->~D(); // destruct D as it goes out of scope when entering catch clauses + goto TryHandler + +In general, TryHandler is not the same as bazHandler, because multiple +function calls could be made from the try block. In this case, trivial +optimization could merge the two basic blocks. TryHandler is the code +that actually determines the type of exception, based on the Exception object +itself. For this discussion, assume that the exception object contains *at +least*: + +1. A pointer to the RTTI info for the contained object +2. A pointer to the dtor for the contained object +3. The contained object itself + +Note that it is necessary to maintain #1 & #2 in the exception object itself +because objects without virtual function tables may be thrown (as in this +example). Assuming this, TryHandler would look something like this: + +TryHandler: + Exception *E = getThreadLocalException(); + switch (E->RTTIType) { + case IntRTTIInfo: + ...int Stuff... // The action to perform from the catch block + break; + case DoubleRTTIInfo: + ...double Stuff... // The action to perform from the catch block + goto TryCleanup // This catch block rethrows the exception + break; // Redundant, eliminated by the optimizer + default: + goto TryCleanup // Exception not caught, rethrow + } + + // Exception was consumed + if (E->dtor) + E->dtor(E->object) // Invoke the dtor on the object if it exists + goto EndTry // Continue mainline code... + +And that is all there is to it. + +The throw(E) function would then be implemented like this (which may be +inlined into the caller through standard optimization): + +function throw(Exception *E) { + // Get the start of the stack trace... + %frame %f = call getStackCurrentFrame() + + // Get the label information that corresponds to it + label * %L = call getFrameLabel(%f) + while (%L == 0 && !isFirstFrame(%f)) { + // Loop until a cleanup handler is found + %f = call getNextFrame(%f) + %L = call getFrameLabel(%f) + } + + if (%L != 0) { + call setThreadLocalException(E) // Allow handlers access to this... + call doNonLocalBranch(%L) + } + // No handler found! + call BlowUp() // Ends up calling the terminate() method in use +} + +That's a brief rundown of how C++ exception handling could be implemented in +llvm. Java would be very similar, except it only uses destructors to unlock +synchronized blocks, not to destroy data. Also, it uses two stack walks: a +nondestructive walk that builds a stack trace, then a destructive walk that +unwinds the stack as shown here. + +It would be trivial to get exception interoperability between C++ and Java. + diff --git a/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt b/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt new file mode 100644 index 00000000..3375365f --- /dev/null +++ b/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt @@ -0,0 +1,45 @@ +Date: Sat, 19 May 2001 19:09:13 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Meeting writeup + +> I read it through and it looks great! + +Thanks! + +> The finally clause in Java may need more thought. The code for this clause +> is like a subroutine because it needs to be entered from many points (end of +> try block and beginning of each catch block), and then needs to *return to +> the place from where the code was entered*. That's why JVM has the +> jsr/jsr_w instruction. + +Hrm... I guess that is an implementation decision. It can either be +modelled as a subroutine (as java bytecodes do), which is really +gross... or it can be modelled as code duplication (emitted once inline, +then once in the exception path). Because this could, at worst, +slightly less than double the amount of code in a function (it is +bounded) I don't think this is a big deal. One of the really nice things +about the LLVM representation is that it still allows for runtime code +generation for exception paths (exceptions paths are not compiled until +needed). Obviously a static compiler couldn't do this though. :) + +In this case, only one copy of the code would be compiled... until the +other one is needed on demand. Also this strategy fits with the "zero +cost" exception model... the standard case is not burdened with extra +branches or "call"s. + +> I suppose you could save the return address in a particular register +> (specific to this finally block), jump to the finally block, and then at the +> end of the finally block, jump back indirectly through this register. It +> will complicate building the CFG but I suppose that can be handled. It is +> also unsafe in terms of checking where control returns (which is I suppose +> why the JVM doesn't use this). + +I think that a code duplication method would be cleaner, and would avoid +the caveats that you mention. Also, it does not slow down the normal case +with an indirect branch... + +Like everything, we can probably defer a final decision until later. :) + +-Chris + diff --git a/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt b/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt new file mode 100644 index 00000000..97af16a2 --- /dev/null +++ b/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt @@ -0,0 +1,63 @@ +Date: Fri, 1 Jun 2001 16:38:17 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: Interesting: GCC passes + + +Take a look at this document (which describes the order of optimizations +that GCC performs): + +http://gcc.gnu.org/onlinedocs/gcc_17.html + +The rundown is that after RTL generation, the following happens: + +1 . [t] jump optimization (jumps to jumps, etc) +2 . [t] Delete unreachable code +3 . Compute live ranges for CSE +4 . [t] Jump threading (jumps to jumps with identical or inverse conditions) +5 . [t] CSE +6 . *** Conversion to SSA +7 . [t] SSA Based DCE +8 . *** Conversion to LLVM +9 . UnSSA +10. GCSE +11. LICM +12. Strength Reduction +13. Loop unrolling +14. [t] CSE +15. [t] DCE +16. Instruction combination, register movement, scheduling... etc. + +I've marked optimizations with a [t] to indicate things that I believe to +be relatively trivial to implement in LLVM itself. The time consuming +things to reimplement would be SSA based PRE, Strength reduction & loop +unrolling... these would be the major things we would miss out on if we +did LLVM creation from tree code [inlining and other high level +optimizations are done on the tree representation]. + +Given the lack of "strong" optimizations that would take a long time to +reimplement, I am leaning a bit more towards creating LLVM from the tree +code. Especially given that SGI has GPL'd their compiler, including many +SSA based optimizations that could be adapted (besides the fact that their +code looks MUCH nicer than GCC :) + +Even if we choose to do LLVM code emission from RTL, we will almost +certainly want to move LLVM emission from step 8 down until at least CSE +has been rerun... which causes me to wonder if the SSA generation code +will still work (due to global variable dependencies and stuff). I assume +that it can be made to work, but might be a little more involved than we +would like. + +I'm continuing to look at the Tree -> RTL code. It is pretty gross +because they do some of the translation a statement at a time, and some +of it a function at a time... I'm not quite clear why and how the +distinction is drawn, but it does not appear that there is a wonderful +place to attach extra info. + +Anyways, I'm proceeding with the RTL -> LLVM conversion phase for now. We +can talk about this more on Monday. + +Wouldn't it be nice if there were a obvious decision to be made? :) + +-Chris + diff --git a/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt b/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt new file mode 100644 index 00000000..e61042fd --- /dev/null +++ b/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt @@ -0,0 +1,71 @@ +Date: Fri, 1 Jun 2001 17:08:44 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Interesting: GCC passes + +> That is very interesting. I agree that some of these could be done on LLVM +> at link-time, but it is the extra time required that concerns me. Link-time +> optimization is severely time-constrained. + +If we were to reimplement any of these optimizations, I assume that we +could do them a translation unit at a time, just as GCC does now. This +would lead to a pipeline like this: + +Static optimizations, xlation unit at a time: +.c --GCC--> .llvm --llvmopt--> .llvm + +Link time optimizations: +.llvm --llvm-ld--> .llvm --llvm-link-opt--> .llvm + +Of course, many optimizations could be shared between llvmopt and +llvm-link-opt, but the wouldn't need to be shared... Thus compile time +could be faster, because we are using a "smarter" IR (SSA based). + +> BTW, about SGI, "borrowing" SSA-based optimizations from one compiler and +> putting it into another is not necessarily easier than re-doing it. +> Optimization code is usually heavily tied in to the specific IR they use. + +Understood. The only reason that I brought this up is because SGI's IR is +more similar to LLVM than it is different in many respects (SSA based, +relatively low level, etc), and could be easily adapted. Also their +optimizations are written in C++ and are actually somewhat +structured... of course it would be no walk in the park, but it would be +much less time consuming to adapt, say, SSA-PRE than to rewrite it. + +> But your larger point is valid that adding SSA based optimizations is +> feasible and should be fun. (Again, link time cost is the issue.) + +Assuming linktime cost wasn't an issue, the question is: +Does using GCC's backend buy us anything? + +> It also occurs to me that GCC is probably doing quite a bit of back-end +> optimization (step 16 in your list). Do you have a breakdown of that? + +Not really. The irritating part of GCC is that it mixes it all up and +doesn't have a clean separation of concerns. A lot of the "back end +optimization" happens right along with other data optimizations (ie, CSE +of machine specific things). + +As far as REAL back end optimizations go, it looks something like this: + +1. Instruction combination: try to make CISCy instructions, if available +2. Register movement: try to get registers in the right places for the +architecture to avoid register to register moves. For example, try to get +the first argument of a function to naturally land in %o0 for sparc. +3. Instruction scheduling: 'nuff said :) +4. Register class preferencing: ?? +5. Local register allocation +6. global register allocation +7. Spilling +8. Local regalloc +9. Jump optimization +10. Delay slot scheduling +11. Branch shorting for CISC machines +12. Instruction selection & peephole optimization +13. Debug info output + +But none of this would be usable for LLVM anyways, unless we were using +GCC as a static compiler. + +-Chris + diff --git a/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt b/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt new file mode 100644 index 00000000..1bc2eae7 --- /dev/null +++ b/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt @@ -0,0 +1,30 @@ +Date: Wed, 20 Jun 2001 12:32:22 -0500 +From: Vikram Adve +To: Chris Lattner +Subject: .NET vs. our VM + +One significant difference between .NET CLR and our VM is that the CLR +includes full information about classes and inheritance. In fact, I just +sat through the paper on adding templates to .NET CLR, and the speaker +indicated that the goal seems to be to do simple static compilation (very +little lowering or optimization). Also, the templates implementation in CLR +"relies on dynamic class loading and JIT compilation". + +This is an important difference because I think there are some significant +advantages to have a much lower level VM layer, and do significant static +analysis and optimization. + +I also talked to the lead guy for KAI's C++ compiler (Arch Robison) and he +said that SGI and other commercial compilers have included options to export +their *IR* next to the object code (i.e., .il files) and use them for +link-time code generation. In fact, he said that the .o file was nearly +empty and was entirely generated from the .il at link-time. But he agreed +that this limited the link-time interprocedural optimization to modules +compiled by the same compiler, whereas our approach allows us to link and +optimize modules from multiple different compilers. (Also, of course, they +don't do anything for runtime optimization). + +All issues to bring up in Related Work. + +--Vikram + diff --git a/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt b/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt new file mode 100644 index 00000000..3e10416f --- /dev/null +++ b/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt @@ -0,0 +1,31 @@ +Date: Fri, 6 Jul 2001 16:56:56 -0500 +From: Vikram S. Adve +To: Chris Lattner +Subject: lowering the IR + +BTW, I do think that we should consider lowering the IR as you said. I +didn't get time to raise it today, but it comes up with the SPARC +move-conditional instruction. I don't think we want to put that in the core +VM -- it is a little too specialized. But without a corresponding +conditional move instruction in the VM, it is pretty difficult to maintain a +close mapping between VM and machine code. Other architectures may have +other such instructions. + +What I was going to suggest was that for a particular processor, we define +additional VM instructions that match some of the unusual opcodes on the +processor but have VM semantics otherwise, i.e., all operands are in SSA +form and typed. This means that we can re-generate core VM code from the +more specialized code any time we want (so that portability is not lost). + +Typically, a static compiler like gcc would generate just the core VM, which +is relatively portable. Anyone (an offline tool, the linker, etc., or even +the static compiler itself if it chooses) can transform that into more +specialized target-specific VM code for a particular architecture. If the +linker does it, it can do it after all machine-independent optimizations. +This would be the most convenient, but not necessary. + +The main benefit of lowering will be that we will be able to retain a close +mapping between VM and machine code. + +--Vikram + diff --git a/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt b/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt new file mode 100644 index 00000000..93790810 --- /dev/null +++ b/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt @@ -0,0 +1,56 @@ +Date: Tue, 18 Sep 2001 00:38:37 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: Idea for a simple, useful link time optimization + + +In C++ programs, exceptions suck, and here's why: + +1. In virtually all function calls, you must assume that the function + throws an exception, unless it is defined as 'nothrow'. This means + that every function call has to have code to invoke dtors on objects + locally if one is thrown by the function. Most functions don't throw + exceptions, so this code is dead [with all the bad effects of dead + code, including icache pollution]. +2. Declaring a function nothrow causes catch blocks to be added to every + call that isnot provably nothrow. This makes them very slow. +3. Extra extraneous exception edges reduce the opportunity for code + motion. +4. EH is typically implemented with large lookup tables. Ours is going to + be much smaller (than the "standard" way of doing it) to start with, + but eliminating it entirely would be nice. :) +5. It is physically impossible to correctly put (accurate, correct) + exception specifications on generic, templated code. But it is trivial + to analyze instantiations of said code. +6. Most large C++ programs throw few exceptions. Most well designed + programs only throw exceptions in specific planned portions of the + code. + +Given our _planned_ model of handling exceptions, all of this would be +pretty trivial to eliminate through some pretty simplistic interprocedural +analysis. The DCE factor alone could probably be pretty significant. The +extra code motion opportunities could also be exploited though... + +Additionally, this optimization can be implemented in a straight forward +conservative manner, allowing libraries to be optimized or individual +files even (if there are leaf functions visible in the translation unit +that are called). + +I think it's a reasonable optimization that hasn't really been addressed +(because assembly is way too low level for this), and could have decent +payoffs... without being a overly complex optimization. + +After I wrote all of that, I found this page that is talking about +basically the same thing I just wrote, except that it is translation unit +at a time, tree based approach: +http://www.ocston.org/~jls/ehopt.html + +but is very useful from "expected gain" and references perspective. Note +that their compiler is apparently unable to inline functions that use +exceptions, so there numbers are pretty worthless... also our results +would (hopefully) be better because it's interprocedural... + +What do you think? + +-Chris + diff --git a/docs/HistoricalNotes/2002-05-12-InstListChange.txt b/docs/HistoricalNotes/2002-05-12-InstListChange.txt new file mode 100644 index 00000000..638682b4 --- /dev/null +++ b/docs/HistoricalNotes/2002-05-12-InstListChange.txt @@ -0,0 +1,55 @@ +Date: Sun, 12 May 2002 17:12:53 -0500 (CDT) +From: Chris Lattner +To: "Vikram S. Adve" +Subject: LLVM change + +There is a fairly fundemental change that I would like to make to the LLVM +infrastructure, but I'd like to know if you see any drawbacks that I +don't... + +Basically right now at the basic block level, each basic block contains an +instruction list (returned by getInstList()) that is a ValueHolder of +instructions. To iterate over instructions, we must actually iterate over +the instlist, and access the instructions through the instlist. + +To add or remove an instruction from a basic block, we need to get an +iterator to an instruction, which, given just an Instruction*, requires a +linear search of the basic block the instruction is contained in... just +to insert an instruction before another instruction, or to delete an +instruction! This complicates algorithms that should be very simple (like +simple constant propagation), because they aren't actually sparse anymore, +they have to traverse basic blocks to remove constant propogated +instructions. + +Additionally, adding or removing instructions to a basic block +_invalidates all iterators_ pointing into that block, which is really +irritating. + +To fix these problems (and others), I would like to make the ordering of +the instructions be represented with a doubly linked list in the +instructions themselves, instead of an external data structure. This is +how many other representations do it, and frankly I can't remember why I +originally implemented it the way I did. + +Long term, all of the code that depends on the nasty features in the +instruction list (which can be found by grep'ing for getInstList()) will +be changed to do nice local transformations. In the short term, I'll +change the representation, but preserve the interface (including +getInstList()) so that all of the code doesn't have to change. + +Iteration over the instructions in a basic block remains the simple: +for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) ... + +But we will also support: +for (Instruction *I = BB->front(); I; I = I->getNext()) ... + +After converting instructions over, I'll convert basic blocks and +functions to have a similar interface. + +The only negative aspect of this change that I see is that it increases +the amount of memory consumed by one pointer per instruction. Given the +benefits, I think this is a very reasonable tradeoff. + +What do you think? + +-Chris diff --git a/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt b/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt new file mode 100644 index 00000000..2ca46117 --- /dev/null +++ b/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt @@ -0,0 +1,72 @@ +Changes: +* Change the casting code to be const correct. Now, doing this is invalid: + const Value *V = ...; + Instruction *I = dyn_cast(V); + instead, the second line should be: + const Instruction *I = dyn_cast(V); + +* Change the casting code to allow casting a reference value thus: + const Value &V = ...; + Instruction &I = cast(V); + + dyn_cast does not work with references, because it must return a null pointer + on failure. + +* Fundamentally change how instructions and other values are represented. + Before, every llvm container was an instance of the ValueHolder template, + instantiated for each container type. This ValueHolder was effectively a + wrapper around a vector of pointers to the sub-objects. + + Now, instead of having a vector to pointers of objects, the objects are + maintained in a doubly linked list of values (ie each Instruction now has + Next & Previous fields). The containers are now instances of ilist (intrusive + linked list class), which use the next and previous fields to chain them + together. The advantage of this implementation is that iterators can be + formed directly from pointers to the LLVM value, and invalidation is much + easier to handle. + +* As part of the above change, dereferencing an iterator (for example: + BasicBlock::iterator) now produces a reference to the underlying type (same + example: Instruction&) instead of a pointer to the underlying object. This + makes it much easier to write nested loops that iterator over things, changing + this: + + for (Function::iterator BI = Func->begin(); BI != Func->end(); ++BI) + for (BasicBlock::iterator II = (*BI)->begin(); II != (*BI)->end(); ++II) + (*II)->dump(); + + into: + + for (Function::iterator BI = Func->begin(); BI != Func->end(); ++BI) + for (BasicBlock::iterator II = BI->begin(); II != BI->end(); ++II) + II->dump(); + + which is much more natural and what users expect. + +* Simplification of #include's: Before, it was necessary for a .cpp file to + include every .h file that it used. Now things are batched a little bit more + to make it easier to use. Specifically, the include graph now includes these + edges: + Module.h -> Function.h, GlobalVariable.h + Function.h -> BasicBlock.h, Argument.h + BasicBlock.h -> Instruction.h + + Which means that #including Function.h is usually sufficient for getting the + lower level #includes. + +* Printing out a Value* has now changed: Printing a Value* will soon print out + the address of the value instead of the contents of the Value. To print out + the contents, you must convert it to a reference with (for example) + 'cout << *I' instead of 'cout << I;'. This conversion is not yet complete, + but will be eventually. In the mean time, both forms print out the contents. + +* References are used much more throughout the code base. In general, if a + pointer is known to never be null, it is passed in as a reference instead of a + pointer. For example, the instruction visitor class uses references instead + of pointers, and that Pass subclasses now all receive references to Values + instead of pointers, because they may never be null. + +* The Function class now has helper functions for accessing the Arguments list. + Instead of having to go through getArgumentList for simple things like + iterator over the arguments, now the a*() methods can be used to access them. + diff --git a/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt b/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt new file mode 100644 index 00000000..fbe811d6 --- /dev/null +++ b/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt @@ -0,0 +1,28 @@ +Date: Mon, 20 Jan 2003 00:00:28 -0600 +From: Brian R. Gaeke +Subject: windows vs. llvm + +If you're interested, here are some of the major problems compiling LLVM +under Cygwin and/or Mingw. + +1. Cygwin doesn't have or , so all the INT*_MAX + symbols and standard int*_t types are off in limbo somewhere. Mingw has + , but Cygwin doesn't like it. + +2. Mingw doesn't have (because Windows doesn't have it.) + +3. SA_SIGINFO and friends are not around; only signal() seems to work. + +4. Relink, aka ld -r, doesn't work (probably an ld bug); you need + DONT_BUILD_RELINKED. This breaks all the tools makefiles; you just need to + change them to have .a's. + +5. There isn't a . + +6. There isn't a mallinfo() (or, at least, it's documented, but it doesn't seem + to link). + +7. The version of Bison that cygwin (and newer Linux versions) comes with + does not like = signs in rules. Burg's gram.yc source file uses them. I think + you can just take them out. + diff --git a/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt b/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt new file mode 100644 index 00000000..521526fb --- /dev/null +++ b/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt @@ -0,0 +1,137 @@ +Wed Jun 25 15:13:51 CDT 2003 + +First-level instrumentation +--------------------------- + +We use opt to do Bytecode-to-bytecode instrumentation. Look at +back-edges and insert llvm_first_trigger() function call which takes +no arguments and no return value. This instrumentation is designed to +be easy to remove, for instance by writing a NOP over the function +call instruction. + +Keep count of every call to llvm_first_trigger(), and maintain +counters in a map indexed by return address. If the trigger count +exceeds a threshold, we identify a hot loop and perform second-level +instrumentation on the hot loop region (the instructions between the +target of the back-edge and the branch that causes the back-edge). We +do not move code across basic-block boundaries. + + +Second-level instrumentation +--------------------------- + +We remove the first-level instrumentation by overwriting the CALL to +llvm_first_trigger() with a NOP. + +The reoptimizer maintains a map between machine-code basic blocks and +LLVM BasicBlock*s. We only keep track of paths that start at the +first machine-code basic block of the hot loop region. + +How do we keep track of which edges to instrument, and which edges are +exits from the hot region? 3 step process. + +1) Do a DFS from the first machine-code basic block of the hot loop +region and mark reachable edges. + +2) Do a DFS from the last machine-code basic block of the hot loop +region IGNORING back edges, and mark the edges which are reachable in +1) and also in 2) (i.e., must be reachable from both the start BB and +the end BB of the hot region). + +3) Mark BBs which end in edges that exit the hot region; we need to +instrument these differently. + +Assume that there is 1 free register. On SPARC we use %g1, which LLC +has agreed not to use. Shift a 1 into it at the beginning. At every +edge which corresponds to a conditional branch, we shift 0 for not +taken and 1 for taken into a register. This uniquely numbers the paths +through the hot region. Silently fail if we need more than 64 bits. + +At the end BB we call countPath and increment the counter based on %g1 +and the return address of the countPath call. We keep track of the +number of iterations and the number of paths. We only run this +version 30 or 40 times. + +Find the BBs that total 90% or more of execution, and aggregate them +together to form our trace. But we do not allow more than 5 paths; if +we have more than 5 we take the ones that are executed the most. We +verify our assumption that we picked a hot back-edge in first-level +instrumentation, by making sure that the number of times we took an +exit edge from the hot trace is less than 10% of the number of +iterations. + +LLC has been taught to recognize llvm_first_trigger() calls and NOT +generate saves and restores of caller-saved registers around these +calls. + + +Phase behavior +-------------- + +We turn off llvm_first_trigger() calls with NOPs, but this would hide +phase behavior from us (when some funcs/traces stop being hot and +others become hot.) + +We have a SIGALRM timer that counts time for us. Every time we get a +SIGALRM we look at our priority queue of locations where we have +removed llvm_first_trigger() calls. Each location is inserted along +with a time when we will next turn instrumentation back on for that +call site. If the time has arrived for a particular call site, we pop +that off the prio. queue and turn instrumentation back on for that +call site. + + +Generating traces +----------------- + +When we finally generate an optimized trace we first copy the code +into the trace cache. This leaves us with 3 copies of the code: the +original code, the instrumented code, and the optimized trace. The +optimized trace does not have instrumentation. The original code and +the instrumented code are modified to have a branch to the trace +cache, where the optimized traces are kept. + +We copy the code from the original to the instrumentation version +by tracing the LLVM-to-Machine code basic block map and then copying +each machine code basic block we think is in the hot region into the +trace cache. Then we instrument that code. The process is similar for +generating the final optimized trace; we copy the same basic blocks +because we might need to put in fixup code for exit BBs. + +LLVM basic blocks are not typically used in the Reoptimizer except +for the mapping information. + +We are restricted to using single instructions to branch between the +original code, trace, and instrumented code. So we have to keep the +code copies in memory near the original code (they can't be far enough +away that a single pc-relative branch would not work.) Malloc() or +data region space is too far away. this impacts the design of the +trace cache. + +We use a dummy function that is full of a bunch of for loops which we +overwrite with trace-cache code. The trace manager keeps track of +whether or not we have enough space in the trace cache, etc. + +The trace insertion routine takes an original start address, a vector +of machine instructions representing the trace, index of branches and +their corresponding absolute targets, and index of calls and their +corresponding absolute targets. + +The trace insertion routine is responsible for inserting branches from +the beginning of the original code to the beginning of the optimized +trace. This is because at some point the trace cache may run out of +space and it may have to evict a trace, at which point the branch to +the trace would also have to be removed. It uses a round-robin +replacement policy; we have found that this is almost as good as LRU +and better than random (especially because of problems fitting the new +trace in.) + +We cannot deal with discontiguous trace cache areas. The trace cache +is supposed to be cache-line-aligned, but it is not page-aligned. + +We generate instrumentation traces and optimized traces into separate +trace caches. We keep the instrumented code around because you don't +want to delete a trace when you still might have to return to it +(i.e., return from an llvm_first_trigger() or countPath() call.) + + diff --git a/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt b/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt new file mode 100644 index 00000000..ec4b93fe --- /dev/null +++ b/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt @@ -0,0 +1,110 @@ +Thu Jun 26 14:43:04 CDT 2003 + +Information about BinInterface +------------------------------ + +Take in a set of instructions with some particular register +allocation. It allows you to add, modify, or delete some instructions, +in SSA form (kind of like LLVM's MachineInstrs.) Then re-allocate +registers. It assumes that the transformations you are doing are safe. +It does not update the mapping information or the LLVM representation +for the modified trace (so it would not, for instance, support +multiple optimization passes; passes have to be aware of and update +manually the mapping information.) + +The way you use it is you take the original code and provide it to +BinInterface; then you do optimizations to it, then you put it in the +trace cache. + +The BinInterface tries to find live-outs for traces so that it can do +register allocation on just the trace, and stitch the trace back into +the original code. It has to preserve the live-ins and live-outs when +it does its register allocation. (On exits from the trace we have +epilogues that copy live-outs back into the right registers, but +live-ins have to be in the right registers.) + + +Limitations of BinInterface +--------------------------- + +It does copy insertions for PHIs, which it infers from the machine +code. The mapping info inserted by LLC is not sufficient to determine +the PHIs. + +It does not handle integer or floating-point condition codes and it +does not handle floating-point register allocation. + +It is not aggressively able to use lots of registers. + +There is a problem with alloca: we cannot find our spill space for +spilling registers, normally allocated on the stack, if the trace +follows an alloca(). What might be an acceptable solution would be to +disable trace generation on functions that have variable-sized +alloca()s. Variable-sized allocas in the trace would also probably +screw things up. + +Because of the FP and alloca limitations, the BinInterface is +completely disabled right now. + + +Demo +---- + +This is a demo of the Ball & Larus version that does NOT use 2-level +profiling. + +1. Compile program with llvm-gcc. +2. Run opt -lowerswitch -paths -emitfuncs on the bytecode. + -lowerswitch change switch statements to branches + -paths Ball & Larus path-profiling algorithm + -emitfuncs emit the table of functions +3. Run llc to generate SPARC assembly code for the result of step 2. +4. Use g++ to link the (instrumented) assembly code. + +We use a script to do all this: +------------------------------------------------------------------------------ +#!/bin/sh +llvm-gcc $1.c -o $1 +opt -lowerswitch -paths -emitfuncs $1.bc > $1.run.bc +llc -f $1.run.bc +LIBS=$HOME/llvm_sparc/lib/Debug +GXX=/usr/dcs/software/evaluation/bin/g++ +$GXX -g -L $LIBS $1.run.s -o $1.run.llc \ +$LIBS/tracecache.o \ +$LIBS/mapinfo.o \ +$LIBS/trigger.o \ +$LIBS/profpaths.o \ +$LIBS/bininterface.o \ +$LIBS/support.o \ +$LIBS/vmcore.o \ +$LIBS/transformutils.o \ +$LIBS/bcreader.o \ +-lscalaropts -lscalaropts -lanalysis \ +-lmalloc -lcpc -lm -ldl +------------------------------------------------------------------------------ + +5. Run the resulting binary. You will see output from BinInterface +(described below) intermixed with the output from the program. + + +Output from BinInterface +------------------------ + +BinInterface's debugging code prints out the following stuff in order: + +1. Initial code provided to BinInterface with original register +allocation. + +2. Section 0 is the trace prolog, consisting mainly of live-ins and +register saves which will be restored in epilogs. + +3. Section 1 is the trace itself, in SSA form used by BinInterface, +along with the PHIs that are inserted. +PHIs are followed by the copies that implement them. +Each branch (i.e., out of the trace) is annotated with the +section number that represents the epilog it branches to. + +4. All the other sections starting with Section 2 are trace epilogs. +Every branch from the trace has to go to some epilog. + +5. After the last section is the register allocation output. diff --git a/docs/HistoricalNotes/2007-OriginalClangReadme.txt b/docs/HistoricalNotes/2007-OriginalClangReadme.txt new file mode 100644 index 00000000..611dc9d2 --- /dev/null +++ b/docs/HistoricalNotes/2007-OriginalClangReadme.txt @@ -0,0 +1,178 @@ +//===----------------------------------------------------------------------===// +// C Language Family Front-end +//===----------------------------------------------------------------------===// + Chris Lattner + +I. Introduction: + + clang: noun + 1. A loud, resonant, metallic sound. + 2. The strident call of a crane or goose. + 3. C-language family front-end toolkit. + + The world needs better compiler tools, tools which are built as libraries. This + design point allows reuse of the tools in new and novel ways. However, building + the tools as libraries isn't enough: they must have clean APIs, be as + decoupled from each other as possible, and be easy to modify/extend. This + requires clean layering, decent design, and avoiding tying the libraries to a + specific use. Oh yeah, did I mention that we want the resultant libraries to + be as fast as possible? :) + + This front-end is built as a component of the LLVM toolkit that can be used + with the LLVM backend or independently of it. In this spirit, the API has been + carefully designed as the following components: + + libsupport - Basic support library, reused from LLVM. + + libsystem - System abstraction library, reused from LLVM. + + libbasic - Diagnostics, SourceLocations, SourceBuffer abstraction, + file system caching for input source files. This depends on + libsupport and libsystem. + + libast - Provides classes to represent the C AST, the C type system, + builtin functions, and various helpers for analyzing and + manipulating the AST (visitors, pretty printers, etc). This + library depends on libbasic. + + + liblex - C/C++/ObjC lexing and preprocessing, identifier hash table, + pragma handling, tokens, and macros. This depends on libbasic. + + libparse - C (for now) parsing and local semantic analysis. This library + invokes coarse-grained 'Actions' provided by the client to do + stuff (e.g. libsema builds ASTs). This depends on liblex. + + libsema - Provides a set of parser actions to build a standardized AST + for programs. AST's are 'streamed' out a top-level declaration + at a time, allowing clients to use decl-at-a-time processing, + build up entire translation units, or even build 'whole + program' ASTs depending on how they use the APIs. This depends + on libast and libparse. + + librewrite - Fast, scalable rewriting of source code. This operates on + the raw syntactic text of source code, allowing a client + to insert and delete text in very large source files using + the same source location information embedded in ASTs. This + is intended to be a low-level API that is useful for + higher-level clients and libraries such as code refactoring. + + libanalysis - Source-level dataflow analysis useful for performing analyses + such as computing live variables. It also includes a + path-sensitive "graph-reachability" engine for writing + analyses that reason about different possible paths of + execution through source code. This is currently being + employed to write a set of checks for finding bugs in software. + + libcodegen - Lower the AST to LLVM IR for optimization & codegen. Depends + on libast. + + clang - An example driver, client of the libraries at various levels. + This depends on all these libraries, and on LLVM VMCore. + + This front-end has been intentionally built as a DAG of libraries, making it + easy to reuse individual parts or replace pieces if desired. For example, to + build a preprocessor, you take the Basic and Lexer libraries. If you want an + indexer, you take those plus the Parser library and provide some actions for + indexing. If you want a refactoring, static analysis, or source-to-source + compiler tool, it makes sense to take those plus the AST building and semantic + analyzer library. Finally, if you want to use this with the LLVM backend, + you'd take these components plus the AST to LLVM lowering code. + + In the future I hope this toolkit will grow to include new and interesting + components, including a C++ front-end, ObjC support, and a whole lot of other + things. + + Finally, it should be pointed out that the goal here is to build something that + is high-quality and industrial-strength: all the obnoxious features of the C + family must be correctly supported (trigraphs, preprocessor arcana, K&R-style + prototypes, GCC/MS extensions, etc). It cannot be used if it is not 'real'. + + +II. Usage of clang driver: + + * Basic Command-Line Options: + - Help: clang --help + - Standard GCC options accepted: -E, -I*, -i*, -pedantic, -std=c90, etc. + - To make diagnostics more gcc-like: -fno-caret-diagnostics -fno-show-column + - Enable metric printing: -stats + + * -fsyntax-only is currently the default mode. + + * -E mode works the same way as GCC. + + * -Eonly mode does all preprocessing, but does not print the output, + useful for timing the preprocessor. + + * -fsyntax-only is currently partially implemented, lacking some + semantic analysis (some errors and warnings are not produced). + + * -parse-noop parses code without building an AST. This is useful + for timing the cost of the parser without including AST building + time. + + * -parse-ast builds ASTs, but doesn't print them. This is most + useful for timing AST building vs -parse-noop. + + * -parse-ast-print pretty prints most expression and statements nodes. + + * -parse-ast-check checks that diagnostic messages that are expected + are reported and that those which are reported are expected. + + * -dump-cfg builds ASTs and then CFGs. CFGs are then pretty-printed. + + * -view-cfg builds ASTs and then CFGs. CFGs are then visualized by + invoking Graphviz. + + For more information on getting Graphviz to work with clang/LLVM, + see: http://llvm.org/docs/ProgrammersManual.html#ViewGraph + + +III. Current advantages over GCC: + + * Column numbers are fully tracked (no 256 col limit, no GCC-style pruning). + * All diagnostics have column numbers, includes 'caret diagnostics', and they + highlight regions of interesting code (e.g. the LHS and RHS of a binop). + * Full diagnostic customization by client (can format diagnostics however they + like, e.g. in an IDE or refactoring tool) through DiagnosticClient interface. + * Built as a framework, can be reused by multiple tools. + * All languages supported linked into same library (no cc1,cc1obj, ...). + * mmap's code in read-only, does not dirty the pages like GCC (mem footprint). + * LLVM License, can be linked into non-GPL projects. + * Full diagnostic control, per diagnostic. Diagnostics are identified by ID. + * Significantly faster than GCC at semantic analysis, parsing, preprocessing + and lexing. + * Defers exposing platform-specific stuff to as late as possible, tracks use of + platform-specific features (e.g. #ifdef PPC) to allow 'portable bytecodes'. + * The lexer doesn't rely on the "lexer hack": it has no notion of scope and + does not categorize identifiers as types or variables -- this is up to the + parser to decide. + +Potential Future Features: + + * Fine grained diag control within the source (#pragma enable/disable warning). + * Better token tracking within macros? (Token came from this line, which is + a macro argument instantiated here, recursively instantiated here). + * Fast #import with a module system. + * Dependency tracking: change to header file doesn't recompile every function + that texually depends on it: recompile only those functions that need it. + This is aka 'incremental parsing'. + + +IV. Missing Functionality / Improvements + +Lexer: + * Source character mapping. GCC supports ASCII and UTF-8. + See GCC options: -ftarget-charset and -ftarget-wide-charset. + * Universal character support. Experimental in GCC, enabled with + -fextended-identifiers. + * -fpreprocessed mode. + +Preprocessor: + * #assert/#unassert + * MSExtension: "L#param" stringizes to a wide string literal. + * Add support for -M* + +Traditional Preprocessor: + * Currently, we have none. :) + diff --git a/docs/HowToAddABuilder.rst b/docs/HowToAddABuilder.rst new file mode 100644 index 00000000..893f12d1 --- /dev/null +++ b/docs/HowToAddABuilder.rst @@ -0,0 +1,86 @@ +=================================================================== +How To Add Your Build Configuration To LLVM Buildbot Infrastructure +=================================================================== + +Introduction +============ + +This document contains information about adding a build configuration and +buildslave to private slave builder to LLVM Buildbot Infrastructure +``_. + + +Steps To Add Builder To LLVM Buildbot +===================================== +Volunteers can provide their build machines to work as build slaves to +public LLVM Buildbot. + +Here are the steps you can follow to do so: + +#. Check the existing build configurations to make sure the one you are + interested in is not covered yet or gets built on your computer much + faster than on the existing one. We prefer faster builds so developers + will get feedback sooner after changes get committed. + +#. The computer you will be registering with the LLVM buildbot + infrastructure should have all dependencies installed and you can + actually build your configuration successfully. Please check what degree + of parallelism (-j param) would give the fastest build. You can build + multiple configurations on one computer. + +#. Install buildslave (currently we are using buildbot version 0.8.5). + Depending on the platform, buildslave could be available to download and + install with your packet manager, or you can download it directly from + ``_ and install it manually. + +#. Create a designated user account, your buildslave will be running under, + and set appropriate permissions. + +#. Choose the buildslave root directory (all builds will be placed under + it), buildslave access name and password the build master will be using + to authenticate your buildslave. + +#. Create a buildslave in context of that buildslave account. Point it to + the **lab.llvm.org** port **9990** (see `Buildbot documentation, + Creating a slave + `_ + for more details) by running the following command: + + .. code-block:: bash + + $ buildslave create-slave \ + lab.llvm.org:9990 \ + + +#. Fill the buildslave description and admin name/e-mail. Here is an + example of the buildslave description:: + + Windows 7 x64 + Core i7 (2.66GHz), 16GB of RAM + + g++.exe (TDM-1 mingw32) 4.4.0 + GNU Binutils 2.19.1 + cmake version 2.8.4 + Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 + +#. Make sure you can actually start the buildslave successfully. Then set + up your buildslave to start automatically at the start up time. See the + buildbot documentation for help. You may want to restart your computer + to see if it works. + +#. Send a patch which adds your build slave and your builder to zorg. + + * slaves are added to ``buildbot/osuosl/master/config/slaves.py`` + * builders are added to ``buildbot/osuosl/master/config/builders.py`` + +#. Send the buildslave access name and the access password directly to + `Galina Kistanova `_, and wait till she + will let you know that your changes are applied and buildmaster is + reconfigured. + +#. Check the status of your buildslave on the `Waterfall Display + `_ to make sure it is connected, and + ``http://lab.llvm.org:8011/buildslaves/`` to see + if administrator contact and slave information are correct. + +#. Wait for the first build to succeed and enjoy. diff --git a/docs/HowToBuildOnARM.rst b/docs/HowToBuildOnARM.rst new file mode 100644 index 00000000..f2edaef7 --- /dev/null +++ b/docs/HowToBuildOnARM.rst @@ -0,0 +1,69 @@ +=================================================================== +How To Build On ARM +=================================================================== + +Introduction +============ + +This document contains information about building/testing LLVM and +Clang on an ARM machine. + +This document is *NOT* tailored to help you cross-compile LLVM/Clang +to ARM on another architecture, for example an x86_64 machine. To find +out more about cross-compiling, please check :doc:`HowToCrossCompileLLVM`. + +Notes On Building LLVM/Clang on ARM +===================================== +Here are some notes on building/testing LLVM/Clang on ARM. Note that +ARM encompasses a wide variety of CPUs; this advice is primarily based +on the ARMv6 and ARMv7 architectures and may be inapplicable to older chips. + +#. If you are building LLVM/Clang on an ARM board with 1G of memory or less, + please use ``gold`` rather then GNU ``ld``. + Building LLVM/Clang with ``--enable-optimized`` + is preferred since it consumes less memory. Otherwise, the building + process will very likely fail due to insufficient memory. In any + case it is probably a good idea to set up a swap partition. + +#. If you want to run ``make check-all`` after building LLVM/Clang, to avoid + false alarms (e.g., ARCMT failure) please use at least the following + configuration: + + .. code-block:: bash + + $ ../$LLVM_SRC_DIR/configure --with-abi=aapcs-vfp + +#. The most popular Linaro/Ubuntu OS's for ARM boards, e.g., the + Pandaboard, have become hard-float platforms. The following set + of configuration options appears to be a good choice for this + platform: + + .. code-block:: bash + + ./configure --build=armv7l-unknown-linux-gnueabihf \ + --host=armv7l-unknown-linux-gnueabihf \ + --target=armv7l-unknown-linux-gnueabihf --with-cpu=cortex-a9 \ + --with-float=hard --with-abi=aapcs-vfp --with-fpu=neon \ + --enable-targets=arm --enable-optimized --enable-assertions + +#. ARM development boards can be unstable and you may experience that cores + are disappearing, caches being flushed on every big.LITTLE switch, and + other similar issues. To help ease the effect of this, set the Linux + scheduler to "performance" on **all** cores using this little script: + + .. code-block:: bash + + # The code below requires the package 'cpufrequtils' to be installed. + for ((cpu=0; cpu<`grep -c proc /proc/cpuinfo`; cpu++)); do + sudo cpufreq-set -c $cpu -g performance + done + +#. Running the build on SD cards is ok, but they are more prone to failures + than good quality USB sticks, and those are more prone to failures than + external hard-drives (those are also a lot faster). So, at least, you + should consider to buy a fast USB stick. On systems with a fast eMMC, + that's a good option too. + +#. Make sure you have a decent power supply (dozens of dollars worth) that can + provide *at least* 4 amperes, this is especially important if you use USB + devices with your board. diff --git a/docs/HowToCrossCompileLLVM.rst b/docs/HowToCrossCompileLLVM.rst new file mode 100644 index 00000000..1072517e --- /dev/null +++ b/docs/HowToCrossCompileLLVM.rst @@ -0,0 +1,175 @@ +=================================================================== +How To Cross-Compile Clang/LLVM using Clang/LLVM +=================================================================== + +Introduction +============ + +This document contains information about building LLVM and +Clang on host machine, targeting another platform. + +For more information on how to use Clang as a cross-compiler, +please check http://clang.llvm.org/docs/CrossCompilation.html. + +TODO: Add MIPS and other platforms to this document. + +Cross-Compiling from x86_64 to ARM +================================== + +In this use case, we'll be using CMake and Ninja, on a Debian-based Linux +system, cross-compiling from an x86_64 host (most Intel and AMD chips +nowadays) to a hard-float ARM target (most ARM targets nowadays). + +The packages you'll need are: + + * ``cmake`` + * ``ninja-build`` (from backports in Ubuntu) + * ``gcc-4.7-arm-linux-gnueabihf`` + * ``gcc-4.7-multilib-arm-linux-gnueabihf`` + * ``binutils-arm-linux-gnueabihf`` + * ``libgcc1-armhf-cross`` + * ``libsfgcc1-armhf-cross`` + * ``libstdc++6-armhf-cross`` + * ``libstdc++6-4.7-dev-armhf-cross`` + +Configuring CMake +----------------- + +For more information on how to configure CMake for LLVM/Clang, +see :doc:`CMake`. + +The CMake options you need to add are: + * ``-DCMAKE_CROSSCOMPILING=True`` + * ``-DCMAKE_INSTALL_PREFIX=`` + * ``-DLLVM_TABLEGEN=/llvm-tblgen`` + * ``-DCLANG_TABLEGEN=/clang-tblgen`` + * ``-DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf`` + * ``-DLLVM_TARGET_ARCH=ARM`` + * ``-DLLVM_TARGETS_TO_BUILD=ARM`` + * ``-DCMAKE_CXX_FLAGS='-target armv7a-linux-gnueabihf -mcpu=cortex-a9 -I/usr/arm-linux-gnueabihf/include/c++/4.7.2/arm-linux-gnueabihf/ -I/usr/arm-linux-gnueabihf/include/ -mfloat-abi=hard -ccc-gcc-name arm-linux-gnueabihf-gcc'`` + +The TableGen options are required to compile it with the host compiler, +so you'll need to compile LLVM (or at least ``llvm-tblgen``) to your host +platform before you start. The CXX flags define the target, cpu (which +defaults to ``fpu=VFP3`` with NEON), and forcing the hard-float ABI. If you're +using Clang as a cross-compiler, you will *also* have to set ``-ccc-gcc-name``, +to make sure it picks the correct linker. + +Most of the time, what you want is to have a native compiler to the +platform itself, but not others. It might not even be feasible to +produce x86 binaries from ARM targets, so there's no point in compiling +all back-ends. For that reason, you should also set the +``TARGETS_TO_BUILD`` to only build the ARM back-end. + +You must set the ``CMAKE_INSTALL_PREFIX``, otherwise a ``ninja install`` +will copy ARM binaries to your root filesystem, which is not what you +want. + +Hacks +----- + +There are some bugs in current LLVM, which require some fiddling before +running CMake: + +#. If you're using Clang as the cross-compiler, there is a problem in + the LLVM ARM back-end that is producing absolute relocations on + position-independent code (``R_ARM_THM_MOVW_ABS_NC``), so for now, you + should disable PIC: + + .. code-block:: bash + + -DLLVM_ENABLE_PIC=False + + This is not a problem, since Clang/LLVM libraries are statically + linked anyway, it shouldn't affect much. + +#. The ARM libraries won't be installed in your system, and possibly + not easily installable anyway, so you'll have to build/download + them separately. But the CMake prepare step, which checks for + dependencies, will check the *host* libraries, not the *target* + ones. + + A quick way of getting the libraries is to download them from + a distribution repository, like Debian (http://packages.debian.org/wheezy/), + and download the missing libraries. Note that the ``libXXX`` + will have the shared objects (``.so``) and the ``libXXX-dev`` will + give you the headers and the static (``.a``) library. Just in + case, download both. + + The ones you need for ARM are: ``libtinfo``, ``zlib1g``, + ``libxml2`` and ``liblzma``. In the Debian repository you'll + find downloads for all architectures. + + After you download and unpack all ``.deb`` packages, copy all + ``.so`` and ``.a`` to a directory, make the appropriate + symbolic links (if necessary), and add the relevant ``-L`` + and ``-I`` paths to ``-DCMAKE_CXX_FLAGS`` above. + + +Running CMake and Building +-------------------------- + +Finally, if you're using your platform compiler, run: + + .. code-block:: bash + + $ cmake -G Ninja + +If you're using Clang as the cross-compiler, run: + + .. code-block:: bash + + $ CC='clang' CXX='clang++' cmake -G Ninja + +If you have ``clang``/``clang++`` on the path, it should just work, and special +Ninja files will be created in the build directory. I strongly suggest +you to run ``cmake`` on a separate build directory, *not* inside the +source tree. + +To build, simply type: + + .. code-block:: bash + + $ ninja + +It should automatically find out how many cores you have, what are +the rules that needs building and will build the whole thing. + +You can't run ``ninja check-all`` on this tree because the created +binaries are targeted to ARM, not x86_64. + +Installing and Using +-------------------- + +After the LLVM/Clang has built successfully, you should install it +via: + + .. code-block:: bash + + $ ninja install + +which will create a sysroot on the install-dir. You can then tar +that directory into a binary with the full triple name (for easy +identification), like: + + .. code-block:: bash + + $ ln -sf arm-linux-gnueabihf-clang + $ tar zchf arm-linux-gnueabihf-clang.tar.gz arm-linux-gnueabihf-clang + +If you copy that tarball to your target board, you'll be able to use +it for running the test-suite, for example. Follow the guidelines at +http://llvm.org/docs/lnt/quickstart.html, unpack the tarball in the +test directory, and use options: + + .. code-block:: bash + + $ ./sandbox/bin/python sandbox/bin/lnt runtest nt \ + --sandbox sandbox \ + --test-suite `pwd`/test-suite \ + --cc `pwd`/arm-linux-gnueabihf-clang/bin/clang \ + --cxx `pwd`/arm-linux-gnueabihf-clang/bin/clang++ + +Remember to add the ``-jN`` options to ``lnt`` to the number of CPUs +on your board. Also, the path to your clang has to be absolute, so +you'll need the `pwd` trick above. diff --git a/docs/HowToReleaseLLVM.rst b/docs/HowToReleaseLLVM.rst new file mode 100644 index 00000000..bc3b093d --- /dev/null +++ b/docs/HowToReleaseLLVM.rst @@ -0,0 +1,425 @@ +================================= +How To Release LLVM To The Public +================================= + +.. contents:: + :local: + :depth: 1 + +Introduction +============ + +This document contains information about successfully releasing LLVM --- +including subprojects: e.g., ``clang`` and ``dragonegg`` --- to the public. It +is the Release Manager's responsibility to ensure that a high quality build of +LLVM is released. + +If you're looking for the document on how to test the release candidates and +create the binary packages, please refer to the :doc:`ReleaseProcess` instead. + +.. _timeline: + +Release Timeline +================ + +LLVM is released on a time based schedule --- roughly every 6 months. We do +not normally have dot releases because of the nature of LLVM's incremental +development philosophy. That said, the only thing preventing dot releases for +critical bug fixes from happening is a lack of resources --- testers, +machines, time, etc. And, because of the high quality we desire for LLVM +releases, we cannot allow for a truncated form of release qualification. + +The release process is roughly as follows: + +* Set code freeze and branch creation date for 6 months after last code freeze + date. Announce release schedule to the LLVM community and update the website. + +* Create release branch and begin release process. + +* Send out release candidate sources for first round of testing. Testing lasts + 7-10 days. During the first round of testing, any regressions found should be + fixed. Patches are merged from mainline into the release branch. Also, all + features need to be completed during this time. Any features not completed at + the end of the first round of testing will be removed or disabled for the + release. + +* Generate and send out the second release candidate sources. Only *critial* + bugs found during this testing phase will be fixed. Any bugs introduced by + merged patches will be fixed. If so a third round of testing is needed. + +* The release notes are updated. + +* Finally, release! + +Release Process +=============== + +.. contents:: + :local: + +Release Administrative Tasks +---------------------------- + +This section describes a few administrative tasks that need to be done for the +release process to begin. Specifically, it involves: + +* Creating the release branch, + +* Setting version numbers, and + +* Tagging release candidates for the release team to begin testing. + +Create Release Branch +^^^^^^^^^^^^^^^^^^^^^ + +Branch the Subversion trunk using the following procedure: + +#. Remind developers that the release branching is imminent and to refrain from + committing patches that might break the build. E.g., new features, large + patches for works in progress, an overhaul of the type system, an exciting + new TableGen feature, etc. + +#. Verify that the current Subversion trunk is in decent shape by + examining nightly tester and buildbot results. + +#. Create the release branch for ``llvm``, ``clang``, the ``test-suite``, and + ``dragonegg`` from the last known good revision. The branch's name is + ``release_XY``, where ``X`` is the major and ``Y`` the minor release + numbers. The branches should be created using the following commands: + + :: + + $ svn copy https://llvm.org/svn/llvm-project/llvm/trunk \ + https://llvm.org/svn/llvm-project/llvm/branches/release_XY + + $ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \ + https://llvm.org/svn/llvm-project/cfe/branches/release_XY + + $ svn copy https://llvm.org/svn/llvm-project/dragonegg/trunk \ + https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY + + $ svn copy https://llvm.org/svn/llvm-project/test-suite/trunk \ + https://llvm.org/svn/llvm-project/test-suite/branches/release_XY + +#. Advise developers that they may now check their patches into the Subversion + tree again. + +#. The Release Manager should switch to the release branch, because all changes + to the release will now be done in the branch. The easiest way to do this is + to grab a working copy using the following commands: + + :: + + $ svn co https://llvm.org/svn/llvm-project/llvm/branches/release_XY llvm-X.Y + + $ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_XY clang-X.Y + + $ svn co https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY dragonegg-X.Y + + $ svn co https://llvm.org/svn/llvm-project/test-suite/branches/release_XY test-suite-X.Y + +Update LLVM Version +^^^^^^^^^^^^^^^^^^^ + +After creating the LLVM release branch, update the release branches' +``autoconf`` and ``configure.ac`` versions from '``X.Ysvn``' to '``X.Y``'. +Update it on mainline as well to be the next version ('``X.Y+1svn``'). +Regenerate the configure scripts for both ``llvm`` and the ``test-suite``. + +In addition, the version numbers of all the Bugzilla components must be updated +for the next release. + +Build the LLVM Release Candidates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Create release candidates for ``llvm``, ``clang``, ``dragonegg``, and the LLVM +``test-suite`` by tagging the branch with the respective release candidate +number. For instance, to create **Release Candidate 1** you would issue the +following commands: + +:: + + $ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY + $ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \ + https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY/rc1 + + $ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY + $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \ + https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY/rc1 + + $ svn mkdir https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XY + $ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \ + https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XY/rc1 + + $ svn mkdir https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY + $ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \ + https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY/rc1 + +Similarly, **Release Candidate 2** would be named ``RC2`` and so on. This keeps +a permanent copy of the release candidate around for people to export and build +as they wish. The final released sources will be tagged in the ``RELEASE_XY`` +directory as ``Final`` (c.f. :ref:`tag`). + +The Release Manager may supply pre-packaged source tarballs for users. This can +be done with the following commands: + +:: + + $ svn export https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY/rc1 llvm-X.Yrc1 + $ svn export https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY/rc1 clang-X.Yrc1 + $ svn export https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XY/rc1 dragonegg-X.Yrc1 + $ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY/rc1 llvm-test-X.Yrc1 + + $ tar -cvf - llvm-X.Yrc1 | gzip > llvm-X.Yrc1.src.tar.gz + $ tar -cvf - clang-X.Yrc1 | gzip > clang-X.Yrc1.src.tar.gz + $ tar -cvf - dragonegg-X.Yrc1 | gzip > dragonegg-X.Yrc1.src.tar.gz + $ tar -cvf - llvm-test-X.Yrc1 | gzip > llvm-test-X.Yrc1.src.tar.gz + +Building the Release +-------------------- + +The builds of ``llvm``, ``clang``, and ``dragonegg`` *must* be free of +errors and warnings in Debug, Release+Asserts, and Release builds. If all +builds are clean, then the release passes Build Qualification. + +The ``make`` options for building the different modes: + ++-----------------+---------------------------------------------+ +| Mode | Options | ++=================+=============================================+ +| Debug | ``ENABLE_OPTIMIZED=0`` | ++-----------------+---------------------------------------------+ +| Release+Asserts | ``ENABLE_OPTIMIZED=1`` | ++-----------------+---------------------------------------------+ +| Release | ``ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1`` | ++-----------------+---------------------------------------------+ + +Build LLVM +^^^^^^^^^^ + +Build ``Debug``, ``Release+Asserts``, and ``Release`` versions +of ``llvm`` on all supported platforms. Directions to build ``llvm`` +are :doc:`here `. + +Build Clang Binary Distribution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Creating the ``clang`` binary distribution (Debug/Release+Asserts/Release) +requires performing the following steps for each supported platform: + +#. Build clang according to the directions `here + `__. + +#. Build both a Debug and Release version of clang. The binary will be the + Release build. + +#. Package ``clang`` (details to follow). + +Target Specific Build Details +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The table below specifies which compilers are used for each Arch/OS combination +when qualifying the build of ``llvm``, ``clang``, and ``dragonegg``. + ++--------------+---------------+----------------------+ +| Architecture | OS | compiler | ++==============+===============+======================+ +| x86-32 | Mac OS 10.5 | gcc 4.0.1 | ++--------------+---------------+----------------------+ +| x86-32 | Linux | gcc 4.2.X, gcc 4.3.X | ++--------------+---------------+----------------------+ +| x86-32 | FreeBSD | gcc 4.2.X | ++--------------+---------------+----------------------+ +| x86-32 | mingw | gcc 3.4.5 | ++--------------+---------------+----------------------+ +| x86-64 | Mac OS 10.5 | gcc 4.0.1 | ++--------------+---------------+----------------------+ +| x86-64 | Linux | gcc 4.2.X, gcc 4.3.X | ++--------------+---------------+----------------------+ +| x86-64 | FreeBSD | gcc 4.2.X | ++--------------+---------------+----------------------+ + +Release Qualification Criteria +------------------------------ + +A release is qualified when it has no regressions from the previous release (or +baseline). Regressions are related to correctness first and performance second. +(We may tolerate some minor performance regressions if they are deemed +necessary for the general quality of the compiler.) + +**Regressions are new failures in the set of tests that are used to qualify +each product and only include things on the list. Every release will have +some bugs in it. It is the reality of developing a complex piece of +software. We need a very concrete and definitive release criteria that +ensures we have monotonically improving quality on some metric. The metric we +use is described below. This doesn't mean that we don't care about other +criteria, but these are the criteria which we found to be most important and +which must be satisfied before a release can go out.** + +Qualify LLVM +^^^^^^^^^^^^ + +LLVM is qualified when it has a clean test run without a front-end. And it has +no regressions when using either ``clang`` or ``dragonegg`` with the +``test-suite`` from the previous release. + +Qualify Clang +^^^^^^^^^^^^^ + +``Clang`` is qualified when front-end specific tests in the ``llvm`` regression +test suite all pass, clang's own test suite passes cleanly, and there are no +regressions in the ``test-suite``. + +Specific Target Qualification Details +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ++--------------+-------------+----------------+-----------------------------+ +| Architecture | OS | clang baseline | tests | ++==============+=============+================+=============================+ +| x86-32 | Linux | last release | llvm regression tests, | +| | | | clang regression tests, | +| | | | test-suite (including spec) | ++--------------+-------------+----------------+-----------------------------+ +| x86-32 | FreeBSD | last release | llvm regression tests, | +| | | | clang regression tests, | +| | | | test-suite | ++--------------+-------------+----------------+-----------------------------+ +| x86-32 | mingw | none | QT | ++--------------+-------------+----------------+-----------------------------+ +| x86-64 | Mac OS 10.X | last release | llvm regression tests, | +| | | | clang regression tests, | +| | | | test-suite (including spec) | ++--------------+-------------+----------------+-----------------------------+ +| x86-64 | Linux | last release | llvm regression tests, | +| | | | clang regression tests, | +| | | | test-suite (including spec) | ++--------------+-------------+----------------+-----------------------------+ +| x86-64 | FreeBSD | last release | llvm regression tests, | +| | | | clang regression tests, | +| | | | test-suite | ++--------------+-------------+----------------+-----------------------------+ + +Community Testing +----------------- + +Once all testing has been completed and appropriate bugs filed, the release +candidate tarballs are put on the website and the LLVM community is notified. +Ask that all LLVM developers test the release in 2 ways: + +#. Download ``llvm-X.Y``, ``llvm-test-X.Y``, and the appropriate ``clang`` + binary. Build LLVM. Run ``make check`` and the full LLVM test suite (``make + TEST=nightly report``). + +#. Download ``llvm-X.Y``, ``llvm-test-X.Y``, and the ``clang`` sources. Compile + everything. Run ``make check`` and the full LLVM test suite (``make + TEST=nightly report``). + +Ask LLVM developers to submit the test suite report and ``make check`` results +to the list. Verify that there are no regressions from the previous release. +The results are not used to qualify a release, but to spot other potential +problems. For unsupported targets, verify that ``make check`` is at least +clean. + +During the first round of testing, all regressions must be fixed before the +second release candidate is tagged. + +If this is the second round of testing, the testing is only to ensure that bug +fixes previously merged in have not created new major problems. *This is not +the time to solve additional and unrelated bugs!* If no patches are merged in, +the release is determined to be ready and the release manager may move onto the +next stage. + +Release Patch Rules +------------------- + +Below are the rules regarding patching the release branch: + +#. Patches applied to the release branch may only be applied by the release + manager. + +#. During the first round of testing, patches that fix regressions or that are + small and relatively risk free (verified by the appropriate code owner) are + applied to the branch. Code owners are asked to be very conservative in + approving patches for the branch. We reserve the right to reject any patch + that does not fix a regression as previously defined. + +#. During the remaining rounds of testing, only patches that fix critical + regressions may be applied. + +Release Final Tasks +------------------- + +The final stages of the release process involves tagging the "final" release +branch, updating documentation that refers to the release, and updating the +demo page. + +Update Documentation +^^^^^^^^^^^^^^^^^^^^ + +Review the documentation and ensure that it is up to date. The "Release Notes" +must be updated to reflect new features, bug fixes, new known issues, and +changes in the list of supported platforms. The "Getting Started Guide" should +be updated to reflect the new release version number tag available from +Subversion and changes in basic system requirements. Merge both changes from +mainline into the release branch. + +.. _tag: + +Tag the LLVM Final Release +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Tag the final release sources using the following procedure: + +:: + + $ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \ + https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY/Final + + $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \ + https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY/Final + + $ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \ + https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XY/Final + + $ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \ + https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY/Final + +Update the LLVM Demo Page +------------------------- + +The LLVM demo page must be updated to use the new release. This consists of +using the new ``clang`` binary and building LLVM. + +Update the LLVM Website +^^^^^^^^^^^^^^^^^^^^^^^ + +The website must be updated before the release announcement is sent out. Here +is what to do: + +#. Check out the ``www`` module from Subversion. + +#. Create a new subdirectory ``X.Y`` in the releases directory. + +#. Commit the ``llvm``, ``test-suite``, ``clang`` source, ``clang binaries``, + ``dragonegg`` source, and ``dragonegg`` binaries in this new directory. + +#. Copy and commit the ``llvm/docs`` and ``LICENSE.txt`` files into this new + directory. The docs should be built with ``BUILD_FOR_WEBSITE=1``. + +#. Commit the ``index.html`` to the ``release/X.Y`` directory to redirect (use + from previous release). + +#. Update the ``releases/download.html`` file with the new release. + +#. Update the ``releases/index.html`` with the new release and link to release + documentation. + +#. Finally, update the main page (``index.html`` and sidebar) to point to the + new release and release announcement. Make sure this all gets committed back + into Subversion. + +Announce the Release +^^^^^^^^^^^^^^^^^^^^ + +Have Chris send out the release announcement when everything is finished. + diff --git a/docs/HowToSetUpLLVMStyleRTTI.rst b/docs/HowToSetUpLLVMStyleRTTI.rst new file mode 100644 index 00000000..e0f865a1 --- /dev/null +++ b/docs/HowToSetUpLLVMStyleRTTI.rst @@ -0,0 +1,400 @@ +====================================================== +How to set up LLVM-style RTTI for your class hierarchy +====================================================== + +.. contents:: + +Background +========== + +LLVM avoids using C++'s built in RTTI. Instead, it pervasively uses its +own hand-rolled form of RTTI which is much more efficient and flexible, +although it requires a bit more work from you as a class author. + +A description of how to use LLVM-style RTTI from a client's perspective is +given in the `Programmer's Manual `_. This +document, in contrast, discusses the steps you need to take as a class +hierarchy author to make LLVM-style RTTI available to your clients. + +Before diving in, make sure that you are familiar with the Object Oriented +Programming concept of "`is-a`_". + +.. _is-a: http://en.wikipedia.org/wiki/Is-a + +Basic Setup +=========== + +This section describes how to set up the most basic form of LLVM-style RTTI +(which is sufficient for 99.9% of the cases). We will set up LLVM-style +RTTI for this class hierarchy: + +.. code-block:: c++ + + class Shape { + public: + Shape() {} + virtual double computeArea() = 0; + }; + + class Square : public Shape { + double SideLength; + public: + Square(double S) : SideLength(S) {} + double computeArea() /* override */; + }; + + class Circle : public Shape { + double Radius; + public: + Circle(double R) : Radius(R) {} + double computeArea() /* override */; + }; + +The most basic working setup for LLVM-style RTTI requires the following +steps: + +#. In the header where you declare ``Shape``, you will want to ``#include + "llvm/Support/Casting.h"``, which declares LLVM's RTTI templates. That + way your clients don't even have to think about it. + + .. code-block:: c++ + + #include "llvm/Support/Casting.h" + +#. In the base class, introduce an enum which discriminates all of the + different concrete classes in the hierarchy, and stash the enum value + somewhere in the base class. + + Here is the code after introducing this change: + + .. code-block:: c++ + + class Shape { + public: + + /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) + + enum ShapeKind { + + SK_Square, + + SK_Circle + + }; + +private: + + const ShapeKind Kind; + +public: + + ShapeKind getKind() const { return Kind; } + + + Shape() {} + virtual double computeArea() = 0; + }; + + You will usually want to keep the ``Kind`` member encapsulated and + private, but let the enum ``ShapeKind`` be public along with providing a + ``getKind()`` method. This is convenient for clients so that they can do + a ``switch`` over the enum. + + A common naming convention is that these enums are "kind"s, to avoid + ambiguity with the words "type" or "class" which have overloaded meanings + in many contexts within LLVM. Sometimes there will be a natural name for + it, like "opcode". Don't bikeshed over this; when in doubt use ``Kind``. + + You might wonder why the ``Kind`` enum doesn't have an entry for + ``Shape``. The reason for this is that since ``Shape`` is abstract + (``computeArea() = 0;``), you will never actually have non-derived + instances of exactly that class (only subclasses). See `Concrete Bases + and Deeper Hierarchies`_ for information on how to deal with + non-abstract bases. It's worth mentioning here that unlike + ``dynamic_cast<>``, LLVM-style RTTI can be used (and is often used) for + classes that don't have v-tables. + +#. Next, you need to make sure that the ``Kind`` gets initialized to the + value corresponding to the dynamic type of the class. Typically, you will + want to have it be an argument to the constructor of the base class, and + then pass in the respective ``XXXKind`` from subclass constructors. + + Here is the code after that change: + + .. code-block:: c++ + + class Shape { + public: + /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) + enum ShapeKind { + SK_Square, + SK_Circle + }; + private: + const ShapeKind Kind; + public: + ShapeKind getKind() const { return Kind; } + + - Shape() {} + + Shape(ShapeKind K) : Kind(K) {} + virtual double computeArea() = 0; + }; + + class Square : public Shape { + double SideLength; + public: + - Square(double S) : SideLength(S) {} + + Square(double S) : Shape(SK_Square), SideLength(S) {} + double computeArea() /* override */; + }; + + class Circle : public Shape { + double Radius; + public: + - Circle(double R) : Radius(R) {} + + Circle(double R) : Shape(SK_Circle), Radius(R) {} + double computeArea() /* override */; + }; + +#. Finally, you need to inform LLVM's RTTI templates how to dynamically + determine the type of a class (i.e. whether the ``isa<>``/``dyn_cast<>`` + should succeed). The default "99.9% of use cases" way to accomplish this + is through a small static member function ``classof``. In order to have + proper context for an explanation, we will display this code first, and + then below describe each part: + + .. code-block:: c++ + + class Shape { + public: + /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) + enum ShapeKind { + SK_Square, + SK_Circle + }; + private: + const ShapeKind Kind; + public: + ShapeKind getKind() const { return Kind; } + + Shape(ShapeKind K) : Kind(K) {} + virtual double computeArea() = 0; + }; + + class Square : public Shape { + double SideLength; + public: + Square(double S) : Shape(SK_Square), SideLength(S) {} + double computeArea() /* override */; + + + + static bool classof(const Shape *S) { + + return S->getKind() == SK_Square; + + } + }; + + class Circle : public Shape { + double Radius; + public: + Circle(double R) : Shape(SK_Circle), Radius(R) {} + double computeArea() /* override */; + + + + static bool classof(const Shape *S) { + + return S->getKind() == SK_Circle; + + } + }; + + The job of ``classof`` is to dynamically determine whether an object of + a base class is in fact of a particular derived class. In order to + downcast a type ``Base`` to a type ``Derived``, there needs to be a + ``classof`` in ``Derived`` which will accept an object of type ``Base``. + + To be concrete, consider the following code: + + .. code-block:: c++ + + Shape *S = ...; + if (isa(S)) { + /* do something ... */ + } + + The code of the ``isa<>`` test in this code will eventually boil + down---after template instantiation and some other machinery---to a + check roughly like ``Circle::classof(S)``. For more information, see + :ref:`classof-contract`. + + The argument to ``classof`` should always be an *ancestor* class because + the implementation has logic to allow and optimize away + upcasts/up-``isa<>``'s automatically. It is as though every class + ``Foo`` automatically has a ``classof`` like: + + .. code-block:: c++ + + class Foo { + [...] + template + static bool classof(const T *, + ::llvm::enable_if_c< + ::llvm::is_base_of::value + >::type* = 0) { return true; } + [...] + }; + + Note that this is the reason that we did not need to introduce a + ``classof`` into ``Shape``: all relevant classes derive from ``Shape``, + and ``Shape`` itself is abstract (has no entry in the ``Kind`` enum), + so this notional inferred ``classof`` is all we need. See `Concrete + Bases and Deeper Hierarchies`_ for more information about how to extend + this example to more general hierarchies. + +Although for this small example setting up LLVM-style RTTI seems like a lot +of "boilerplate", if your classes are doing anything interesting then this +will end up being a tiny fraction of the code. + +Concrete Bases and Deeper Hierarchies +===================================== + +For concrete bases (i.e. non-abstract interior nodes of the inheritance +tree), the ``Kind`` check inside ``classof`` needs to be a bit more +complicated. The situation differs from the example above in that + +* Since the class is concrete, it must itself have an entry in the ``Kind`` + enum because it is possible to have objects with this class as a dynamic + type. + +* Since the class has children, the check inside ``classof`` must take them + into account. + +Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive +from ``Square``, and so ``ShapeKind`` becomes: + +.. code-block:: c++ + + enum ShapeKind { + SK_Square, + + SK_SpecialSquare, + + SK_OtherSpecialSquare, + SK_Circle + } + +Then in ``Square``, we would need to modify the ``classof`` like so: + +.. code-block:: c++ + + - static bool classof(const Shape *S) { + - return S->getKind() == SK_Square; + - } + + static bool classof(const Shape *S) { + + return S->getKind() >= SK_Square && + + S->getKind() <= SK_OtherSpecialSquare; + + } + +The reason that we need to test a range like this instead of just equality +is that both ``SpecialSquare`` and ``OtherSpecialSquare`` "is-a" +``Square``, and so ``classof`` needs to return ``true`` for them. + +This approach can be made to scale to arbitrarily deep hierarchies. The +trick is that you arrange the enum values so that they correspond to a +preorder traversal of the class hierarchy tree. With that arrangement, all +subclass tests can be done with two comparisons as shown above. If you just +list the class hierarchy like a list of bullet points, you'll get the +ordering right:: + + | Shape + | Square + | SpecialSquare + | OtherSpecialSquare + | Circle + +A Bug to be Aware Of +-------------------- + +The example just given opens the door to bugs where the ``classof``\s are +not updated to match the ``Kind`` enum when adding (or removing) classes to +(from) the hierarchy. + +Continuing the example above, suppose we add a ``SomewhatSpecialSquare`` as +a subclass of ``Square``, and update the ``ShapeKind`` enum like so: + +.. code-block:: c++ + + enum ShapeKind { + SK_Square, + SK_SpecialSquare, + SK_OtherSpecialSquare, + + SK_SomewhatSpecialSquare, + SK_Circle + } + +Now, suppose that we forget to update ``Square::classof()``, so it still +looks like: + +.. code-block:: c++ + + static bool classof(const Shape *S) { + // BUG: Returns false when S->getKind() == SK_SomewhatSpecialSquare, + // even though SomewhatSpecialSquare "is a" Square. + return S->getKind() >= SK_Square && + S->getKind() <= SK_OtherSpecialSquare; + } + +As the comment indicates, this code contains a bug. A straightforward and +non-clever way to avoid this is to introduce an explicit ``SK_LastSquare`` +entry in the enum when adding the first subclass(es). For example, we could +rewrite the example at the beginning of `Concrete Bases and Deeper +Hierarchies`_ as: + +.. code-block:: c++ + + enum ShapeKind { + SK_Square, + + SK_SpecialSquare, + + SK_OtherSpecialSquare, + + SK_LastSquare, + SK_Circle + } + ... + // Square::classof() + - static bool classof(const Shape *S) { + - return S->getKind() == SK_Square; + - } + + static bool classof(const Shape *S) { + + return S->getKind() >= SK_Square && + + S->getKind() <= SK_LastSquare; + + } + +Then, adding new subclasses is easy: + +.. code-block:: c++ + + enum ShapeKind { + SK_Square, + SK_SpecialSquare, + SK_OtherSpecialSquare, + + SK_SomewhatSpecialSquare, + SK_LastSquare, + SK_Circle + } + +Notice that ``Square::classof`` does not need to be changed. + +.. _classof-contract: + +The Contract of ``classof`` +--------------------------- + +To be more precise, let ``classof`` be inside a class ``C``. Then the +contract for ``classof`` is "return ``true`` if the dynamic type of the +argument is-a ``C``". As long as your implementation fulfills this +contract, you can tweak and optimize it as much as you want. + +.. TODO:: + + Touch on some of the more advanced features, like ``isa_impl`` and + ``simplify_type``. However, those two need reference documentation in + the form of doxygen comments as well. We need the doxygen so that we can + say "for full details, see http://llvm.org/doxygen/..." + +Rules of Thumb +============== + +#. The ``Kind`` enum should have one entry per concrete class, ordered + according to a preorder traversal of the inheritance tree. +#. The argument to ``classof`` should be a ``const Base *``, where ``Base`` + is some ancestor in the inheritance hierarchy. The argument should + *never* be a derived class or the class itself: the template machinery + for ``isa<>`` already handles this case and optimizes it. +#. For each class in the hierarchy that has no children, implement a + ``classof`` that checks only against its ``Kind``. +#. For each class in the hierarchy that has children, implement a + ``classof`` that checks a range of the first child's ``Kind`` and the + last child's ``Kind``. diff --git a/docs/HowToSubmitABug.rst b/docs/HowToSubmitABug.rst new file mode 100644 index 00000000..45be2826 --- /dev/null +++ b/docs/HowToSubmitABug.rst @@ -0,0 +1,229 @@ +================================ +How to submit an LLVM bug report +================================ + +Introduction - Got bugs? +======================== + + +If you're working with LLVM and run into a bug, we definitely want to know +about it. This document describes what you can do to increase the odds of +getting it fixed quickly. + +Basically you have to do two things at a minimum. First, decide whether +the bug `crashes the compiler`_ (or an LLVM pass), or if the +compiler is `miscompiling`_ the program (i.e., the +compiler successfully produces an executable, but it doesn't run right). +Based on what type of bug it is, follow the instructions in the linked +section to narrow down the bug so that the person who fixes it will be able +to find the problem more easily. + +Once you have a reduced test-case, go to `the LLVM Bug Tracking System +`_ and fill out the form with the +necessary details (note that you don't need to pick a category, just use +the "new-bugs" category if you're not sure). The bug description should +contain the following information: + +* All information necessary to reproduce the problem. +* The reduced test-case that triggers the bug. +* The location where you obtained LLVM (if not from our Subversion + repository). + +Thanks for helping us make LLVM better! + +.. _crashes the compiler: + +Crashing Bugs +============= + +More often than not, bugs in the compiler cause it to crash---often due to +an assertion failure of some sort. The most important piece of the puzzle +is to figure out if it is crashing in the GCC front-end or if it is one of +the LLVM libraries (e.g. the optimizer or code generator) that has +problems. + +To figure out which component is crashing (the front-end, optimizer or code +generator), run the ``llvm-gcc`` command line as you were when the crash +occurred, but with the following extra command line options: + +* ``-O0 -emit-llvm``: If ``llvm-gcc`` still crashes when passed these + options (which disable the optimizer and code generator), then the crash + is in the front-end. Jump ahead to the section on :ref:`front-end bugs + `. + +* ``-emit-llvm``: If ``llvm-gcc`` crashes with this option (which disables + the code generator), you found an optimizer bug. Jump ahead to + `compile-time optimization bugs`_. + +* Otherwise, you have a code generator crash. Jump ahead to `code + generator bugs`_. + +.. _front-end bug: +.. _front-end: + +Front-end bugs +-------------- + +If the problem is in the front-end, you should re-run the same ``llvm-gcc`` +command that resulted in the crash, but add the ``-save-temps`` option. +The compiler will crash again, but it will leave behind a ``foo.i`` file +(containing preprocessed C source code) and possibly ``foo.s`` for each +compiled ``foo.c`` file. Send us the ``foo.i`` file, along with the options +you passed to ``llvm-gcc``, and a brief description of the error it caused. + +The `delta `_ tool helps to reduce the +preprocessed file down to the smallest amount of code that still replicates +the problem. You're encouraged to use delta to reduce the code to make the +developers' lives easier. `This website +`_ has instructions +on the best way to use delta. + +.. _compile-time optimization bugs: + +Compile-time optimization bugs +------------------------------ + +If you find that a bug crashes in the optimizer, compile your test-case to a +``.bc`` file by passing "``-emit-llvm -O0 -c -o foo.bc``". +Then run: + +.. code-block:: bash + + opt -std-compile-opts -debug-pass=Arguments foo.bc -disable-output + +This command should do two things: it should print out a list of passes, and +then it should crash in the same way as llvm-gcc. If it doesn't crash, please +follow the instructions for a `front-end bug`_. + +If this does crash, then you should be able to debug this with the following +bugpoint command: + +.. code-block:: bash + + bugpoint foo.bc + +Please run this, then file a bug with the instructions and reduced .bc +files that bugpoint emits. If something goes wrong with bugpoint, please +submit the "foo.bc" file and the list of passes printed by ``opt``. + +.. _code generator bugs: + +Code generator bugs +------------------- + +If you find a bug that crashes llvm-gcc in the code generator, compile your +source file to a .bc file by passing "``-emit-llvm -c -o foo.bc``" to +llvm-gcc (in addition to the options you already pass). Once your have +foo.bc, one of the following commands should fail: + +#. ``llc foo.bc`` +#. ``llc foo.bc -relocation-model=pic`` +#. ``llc foo.bc -relocation-model=static`` + +If none of these crash, please follow the instructions for a `front-end +bug`_. If one of these do crash, you should be able to reduce this with +one of the following bugpoint command lines (use the one corresponding to +the command above that failed): + +#. ``bugpoint -run-llc foo.bc`` +#. ``bugpoint -run-llc foo.bc --tool-args -relocation-model=pic`` +#. ``bugpoint -run-llc foo.bc --tool-args -relocation-model=static`` + +Please run this, then file a bug with the instructions and reduced .bc file +that bugpoint emits. If something goes wrong with bugpoint, please submit +the "foo.bc" file and the option that llc crashes with. + +.. _miscompiling: + +Miscompilations +=============== + +If llvm-gcc successfully produces an executable, but that executable +doesn't run right, this is either a bug in the code or a bug in the +compiler. The first thing to check is to make sure it is not using +undefined behavior (e.g. reading a variable before it is defined). In +particular, check to see if the program `valgrind +`_'s clean, passes purify, or some other memory +checker tool. Many of the "LLVM bugs" that we have chased down ended up +being bugs in the program being compiled, not LLVM. + +Once you determine that the program itself is not buggy, you should choose +which code generator you wish to compile the program with (e.g. LLC or the JIT) +and optionally a series of LLVM passes to run. For example: + +.. code-block:: bash + + bugpoint -run-llc [... optzn passes ...] file-to-test.bc --args -- [program arguments] + +bugpoint will try to narrow down your list of passes to the one pass that +causes an error, and simplify the bitcode file as much as it can to assist +you. It will print a message letting you know how to reproduce the +resulting error. + +Incorrect code generation +========================= + +Similarly to debugging incorrect compilation by mis-behaving passes, you +can debug incorrect code generation by either LLC or the JIT, using +``bugpoint``. The process ``bugpoint`` follows in this case is to try to +narrow the code down to a function that is miscompiled by one or the other +method, but since for correctness, the entire program must be run, +``bugpoint`` will compile the code it deems to not be affected with the C +Backend, and then link in the shared object it generates. + +To debug the JIT: + +.. code-block:: bash + + bugpoint -run-jit -output=[correct output file] [bitcode file] \ + --tool-args -- [arguments to pass to lli] \ + --args -- [program arguments] + +Similarly, to debug the LLC, one would run: + +.. code-block:: bash + + bugpoint -run-llc -output=[correct output file] [bitcode file] \ + --tool-args -- [arguments to pass to llc] \ + --args -- [program arguments] + +**Special note:** if you are debugging MultiSource or SPEC tests that +already exist in the ``llvm/test`` hierarchy, there is an easier way to +debug the JIT, LLC, and CBE, using the pre-written Makefile targets, which +will pass the program options specified in the Makefiles: + +.. code-block:: bash + + cd llvm/test/../../program + make bugpoint-jit + +At the end of a successful ``bugpoint`` run, you will be presented +with two bitcode files: a *safe* file which can be compiled with the C +backend and the *test* file which either LLC or the JIT +mis-codegenerates, and thus causes the error. + +To reproduce the error that ``bugpoint`` found, it is sufficient to do +the following: + +#. Regenerate the shared object from the safe bitcode file: + + .. code-block:: bash + + llc -march=c safe.bc -o safe.c + gcc -shared safe.c -o safe.so + +#. If debugging LLC, compile test bitcode native and link with the shared + object: + + .. code-block:: bash + + llc test.bc -o test.s + gcc test.s safe.so -o test.llc + ./test.llc [program options] + +#. If debugging the JIT, load the shared object and supply the test + bitcode: + + .. code-block:: bash + + lli -load=safe.so test.bc [program options] diff --git a/docs/HowToUseAttributes.rst b/docs/HowToUseAttributes.rst new file mode 100644 index 00000000..66c44c01 --- /dev/null +++ b/docs/HowToUseAttributes.rst @@ -0,0 +1,81 @@ +===================== +How To Use Attributes +===================== + +.. contents:: + :local: + +Introduction +============ + +Attributes in LLVM have changed in some fundamental ways. It was necessary to +do this to support expanding the attributes to encompass more than a handful of +attributes --- e.g. command line options. The old way of handling attributes +consisted of representing them as a bit mask of values. This bit mask was +stored in a "list" structure that was reference counted. The advantage of this +was that attributes could be manipulated with 'or's and 'and's. The +disadvantage of this was that there was limited room for expansion, and +virtually no support for attribute-value pairs other than alignment. + +In the new scheme, an ``Attribute`` object represents a single attribute that's +uniqued. You use the ``Attribute::get`` methods to create a new ``Attribute`` +object. An attribute can be a single "enum" value (the enum being the +``Attribute::AttrKind`` enum), a string representing a target-dependent +attribute, or an attribute-value pair. Some examples: + +* Target-independent: ``noinline``, ``zext`` +* Target-dependent: ``"no-sse"``, ``"thumb2"`` +* Attribute-value pair: ``"cpu" = "cortex-a8"``, ``align = 4`` + +Note: for an attribute value pair, we expect a target-dependent attribute to +have a string for the value. + +``Attribute`` +============= +An ``Attribute`` object is designed to be passed around by value. + +Because attributes are no longer represented as a bit mask, you will need to +convert any code which does treat them as a bit mask to use the new query +methods on the Attribute class. + +``AttributeSet`` +================ + +The ``AttributeSet`` class replaces the old ``AttributeList`` class. The +``AttributeSet`` stores a collection of Attribute objects for each kind of +object that may have an attribute associated with it: the function as a +whole, the return type, or the function's parameters. A function's attributes +are at index ``AttributeSet::FunctionIndex``; the return type's attributes are +at index ``AttributeSet::ReturnIndex``; and the function's parameters' +attributes are at indices 1, ..., n (where 'n' is the number of parameters). +Most methods on the ``AttributeSet`` class take an index parameter. + +An ``AttributeSet`` is also a uniqued and immutable object. You create an +``AttributeSet`` through the ``AttributeSet::get`` methods. You can add and +remove attributes, which result in the creation of a new ``AttributeSet``. + +An ``AttributeSet`` object is designed to be passed around by value. + +Note: It is advised that you do *not* use the ``AttributeSet`` "introspection" +methods (e.g. ``Raw``, ``getRawPointer``, etc.). These methods break +encapsulation, and may be removed in a future release (i.e. LLVM 4.0). + +``AttrBuilder`` +=============== + +Lastly, we have a "builder" class to help create the ``AttributeSet`` object +without having to create several different intermediate uniqued +``AttributeSet`` objects. The ``AttrBuilder`` class allows you to add and +remove attributes at will. The attributes won't be uniqued until you call the +appropriate ``AttributeSet::get`` method. + +An ``AttrBuilder`` object is *not* designed to be passed around by value. It +should be passed by reference. + +Note: It is advised that you do *not* use the ``AttrBuilder::addRawValue()`` +method or the ``AttrBuilder(uint64_t Val)`` constructor. These are for +backwards compatibility and may be removed in a future release (i.e. LLVM 4.0). + +And that's basically it! A lot of functionality is hidden behind these classes, +but the interfaces are pretty straight forward. + diff --git a/docs/HowToUseInstrMappings.rst b/docs/HowToUseInstrMappings.rst new file mode 100644 index 00000000..8a3e7c8d --- /dev/null +++ b/docs/HowToUseInstrMappings.rst @@ -0,0 +1,175 @@ +=============================== +How To Use Instruction Mappings +=============================== + +.. contents:: + :local: + +Introduction +============ + +This document contains information about adding instruction mapping support +for a target. The motivation behind this feature comes from the need to switch +between different instruction formats during various optimizations. One approach +could be to use switch cases which list all the instructions along with formats +they can transition to. However, it has large maintenance overhead +because of the hardcoded instruction names. Also, whenever a new instruction is +added in the .td files, all the relevant switch cases should be modified +accordingly. Instead, the same functionality could be achieved with TableGen and +some support from the .td files for a fraction of maintenance cost. + +``InstrMapping`` Class Overview +=============================== + +TableGen uses relationship models to map instructions with each other. These +models are described using ``InstrMapping`` class as a base. Each model sets +various fields of the ``InstrMapping`` class such that they can uniquely +describe all the instructions using that model. TableGen parses all the relation +models and uses the information to construct relation tables which relate +instructions with each other. These tables are emitted in the +``XXXInstrInfo.inc`` file along with the functions to query them. Following +is the definition of ``InstrMapping`` class definied in Target.td file: + +.. code-block:: llvm + + class InstrMapping { + // Used to reduce search space only to the instructions using this + // relation model. + string FilterClass; + + // List of fields/attributes that should be same for all the instructions in + // a row of the relation table. Think of this as a set of properties shared + // by all the instructions related by this relationship. + list RowFields = []; + + // List of fields/attributes that are same for all the instructions + // in a column of the relation table. + list ColFields = []; + + // Values for the fields/attributes listed in 'ColFields' corresponding to + // the key instruction. This is the instruction that will be transformed + // using this relation model. + list KeyCol = []; + + // List of values for the fields/attributes listed in 'ColFields', one for + // each column in the relation table. These are the instructions a key + // instruction will be transformed into. + list > ValueCols = []; + } + +Sample Example +-------------- + +Let's say that we want to have a function +``int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)`` which +takes a non-predicated instruction and returns its predicated true or false form +depending on some input flag, ``inPredSense``. The first step in the process is +to define a relationship model that relates predicated instructions to their +non-predicated form by assigning appropriate values to the ``InstrMapping`` +fields. For this relationship, non-predicated instructions are treated as key +instruction since they are the one used to query the interface function. + +.. code-block:: llvm + + def getPredOpcode : InstrMapping { + // Choose a FilterClass that is used as a base class for all the + // instructions modeling this relationship. This is done to reduce the + // search space only to these set of instructions. + let FilterClass = "PredRel"; + + // Instructions with same values for all the fields in RowFields form a + // row in the resulting relation table. + // For example, if we want to relate 'ADD' (non-predicated) with 'Add_pt' + // (predicated true) and 'Add_pf' (predicated false), then all 3 + // instructions need to have same value for BaseOpcode field. It can be any + // unique value (Ex: XYZ) and should not be shared with any other + // instruction not related to 'add'. + let RowFields = ["BaseOpcode"]; + + // List of attributes that can be used to define key and column instructions + // for a relation. Key instruction is passed as an argument + // to the function used for querying relation tables. Column instructions + // are the instructions they (key) can transform into. + // + // Here, we choose 'PredSense' as ColFields since this is the unique + // attribute of the key (non-predicated) and column (true/false) + // instructions involved in this relationship model. + let ColFields = ["PredSense"]; + + // The key column contains non-predicated instructions. + let KeyCol = ["none"]; + + // Two value columns - first column contains instructions with + // PredSense=true while second column has instructions with PredSense=false. + let ValueCols = [["true"], ["false"]]; + } + +TableGen uses the above relationship model to emit relation table that maps +non-predicated instructions with their predicated forms. It also outputs the +interface function +``int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)`` to query +the table. Here, Function ``getPredOpcode`` takes two arguments, opcode of the +current instruction and PredSense of the desired instruction, and returns +predicated form of the instruction, if found in the relation table. +In order for an instruction to be added into the relation table, it needs +to include relevant information in its definition. For example, consider +following to be the current definitions of ADD, ADD_pt (true) and ADD_pf (false) +instructions: + +.. code-block:: llvm + + def ADD : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$a, IntRegs:$b), + "$dst = add($a, $b)", + [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$a), + (i32 IntRegs:$b)))]>; + + def ADD_Pt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), + "if ($p) $dst = add($a, $b)", + []>; + + def ADD_Pf : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), + "if (!$p) $dst = add($a, $b)", + []>; + +In this step, we modify these instructions to include the information +required by the relationship model, getPredOpcode, so that they can +be related. + +.. code-block:: llvm + + def ADD : PredRel, ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$a, IntRegs:$b), + "$dst = add($a, $b)", + [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$a), + (i32 IntRegs:$b)))]> { + let BaseOpcode = "ADD"; + let PredSense = "none"; + } + + def ADD_Pt : PredRel, ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), + "if ($p) $dst = add($a, $b)", + []> { + let BaseOpcode = "ADD"; + let PredSense = "true"; + } + + def ADD_Pf : PredRel, ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), + "if (!$p) $dst = add($a, $b)", + []> { + let BaseOpcode = "ADD"; + let PredSense = "false"; + } + +Please note that all the above instructions use ``PredRel`` as a base class. +This is extremely important since TableGen uses it as a filter for selecting +instructions for ``getPredOpcode`` model. Any instruction not derived from +``PredRel`` is excluded from the analysis. ``BaseOpcode`` is another important +field. Since it's selected as a ``RowFields`` of the model, it is required +to have the same value for all 3 instructions in order to be related. Next, +``PredSense`` is used to determine their column positions by comparing its value +with ``KeyCol`` and ``ValueCols``. If an instruction sets its ``PredSense`` +value to something not used in the relation model, it will not be assigned +a column in the relation table. diff --git a/docs/LLVMBuild.rst b/docs/LLVMBuild.rst new file mode 100644 index 00000000..040b0448 --- /dev/null +++ b/docs/LLVMBuild.rst @@ -0,0 +1,325 @@ +=============== +LLVMBuild Guide +=============== + +.. contents:: + :local: + +Introduction +============ + +This document describes the ``LLVMBuild`` organization and files which +we use to describe parts of the LLVM ecosystem. For description of +specific LLVMBuild related tools, please see the command guide. + +LLVM is designed to be a modular set of libraries which can be flexibly +mixed together in order to build a variety of tools, like compilers, +JITs, custom code generators, optimization passes, interpreters, and so +on. Related projects in the LLVM system like Clang and LLDB also tend to +follow this philosophy. + +In order to support this usage style, LLVM has a fairly strict structure +as to how the source code and various components are organized. The +``LLVMBuild.txt`` files are the explicit specification of that +structure, and are used by the build systems and other tools in order to +develop the LLVM project. + +Project Organization +==================== + +The source code for LLVM projects using the LLVMBuild system (LLVM, +Clang, and LLDB) is organized into *components*, which define the +separate pieces of functionality that make up the project. These +projects may consist of many libraries, associated tools, build tools, +or other utility tools (for example, testing tools). + +For the most part, the project contents are organized around defining +one main component per each subdirectory. Each such directory contains +an ``LLVMBuild.txt`` which contains the component definitions. + +The component descriptions for the project as a whole are automatically +gathered by the LLVMBuild tools. The tools automatically traverse the +source directory structure to find all of the component description +files. NOTE: For performance/sanity reasons, we only traverse into +subdirectories when the parent itself contains an ``LLVMBuild.txt`` +description file. + +Build Integration +================= + +The LLVMBuild files themselves are just a declarative way to describe +the project structure. The actual building of the LLVM project is +handled by another build system (currently we support both +:doc:`Makefiles ` and :doc:`CMake `). + +The build system implementation will load the relevant contents of the +LLVMBuild files and use that to drive the actual project build. +Typically, the build system will only need to load this information at +"configure" time, and use it to generative native information. Build +systems will also handle automatically reconfiguring their information +when the contents of the ``LLVMBuild.txt`` files change. + +Developers generally are not expected to need to be aware of the details +of how the LLVMBuild system is integrated into their build. Ideally, +LLVM developers who are not working on the build system would only ever +need to modify the contents of the ``LLVMBuild.txt`` description files +(although we have not reached this goal yet). + +For more information on the utility tool we provide to help interfacing +with the build system, please see the :doc:`llvm-build +` documentation. + +Component Overview +================== + +As mentioned earlier, LLVM projects are organized into logical +*components*. Every component is typically grouped into its own +subdirectory. Generally, a component is organized around a coherent +group of sources which have some kind of clear API separation from other +parts of the code. + +LLVM primarily uses the following types of components: + +- *Libraries* - Library components define a distinct API which can be + independently linked into LLVM client applications. Libraries typically + have private and public header files, and may specify a link of required + libraries that they build on top of. +- *Build Tools* - Build tools are applications which are designed to be run + as part of the build process (typically to generate other source files). + Currently, LLVM uses one main build tool called :doc:`TableGen + ` to generate a variety of source files. +- *Tools* - Command line applications which are built using the LLVM + component libraries. Most LLVM tools are small and are primarily + frontends to the library interfaces. + +Components are described using ``LLVMBuild.txt`` files in the directories +that define the component. See the `LLVMBuild Format Reference`_ section +for information on the exact format of these files. + +LLVMBuild Format Reference +========================== + +LLVMBuild files are written in a simple variant of the INI or configuration +file format (`Wikipedia entry`_). The format defines a list of sections +each of which may contain some number of properties. A simple example of +the file format is below: + +.. _Wikipedia entry: http://en.wikipedia.org/wiki/INI_file + +.. code-block:: ini + + ; Comments start with a semi-colon. + + ; Sections are declared using square brackets. + [component_0] + + ; Properties are declared using '=' and are contained in the previous section. + ; + ; We support simple string and boolean scalar values and list values, where + ; items are separated by spaces. There is no support for quoting, and so + ; property values may not contain spaces. + property_name = property_value + list_property_name = value_1 value_2 ... value_n + boolean_property_name = 1 (or 0) + +LLVMBuild files are expected to define a strict set of sections and +properties. A typical component description file for a library +component would look like the following example: + +.. code-block:: ini + + [component_0] + type = Library + name = Linker + parent = Libraries + required_libraries = Archive BitReader Core Support TransformUtils + +A full description of the exact sections and properties which are +allowed follows. + +Each file may define exactly one common component, named ``common``. The +common component may define the following properties: + +- ``subdirectories`` **[optional]** + + If given, a list of the names of the subdirectories from the current + subpath to search for additional LLVMBuild files. + +Each file may define multiple components. Each component is described by a +section who name starts with ``component``. The remainder of the section +name is ignored, but each section name must be unique. Typically components +are just number in order for files with multiple components +(``component_0``, ``component_1``, and so on). + +.. warning:: + + Section names not matching this format (or the ``common`` section) are + currently unused and are disallowed. + +Every component is defined by the properties in the section. The exact +list of properties that are allowed depends on the component type. +Components **may not** define any properties other than those expected +by the component type. + +Every component must define the following properties: + +- ``type`` **[required]** + + The type of the component. Supported component types are detailed + below. Most components will define additional properties which may be + required or optional. + +- ``name`` **[required]** + + The name of the component. Names are required to be unique across the + entire project. + +- ``parent`` **[required]** + + The name of the logical parent of the component. Components are + organized into a logical tree to make it easier to navigate and + organize groups of components. The parents have no semantics as far + as the project build is concerned, however. Typically, the parent + will be the main component of the parent directory. + + Components may reference the root pseudo component using ``$ROOT`` to + indicate they should logically be grouped at the top-level. + +Components may define the following properties: + +- ``dependencies`` **[optional]** + + If specified, a list of names of components which *must* be built + prior to this one. This should only be exactly those components which + produce some tool or source code required for building the component. + + .. note:: + + ``Group`` and ``LibraryGroup`` components have no semantics for the + actual build, and are not allowed to specify dependencies. + +The following section lists the available component types, as well as +the properties which are associated with that component. + +- ``type = Group`` + + Group components exist purely to allow additional arbitrary structuring + of the logical components tree. For example, one might define a + ``Libraries`` group to hold all of the root library components. + + ``Group`` components have no additionally properties. + +- ``type = Library`` + + Library components define an individual library which should be built + from the source code in the component directory. + + Components with this type use the following properties: + + - ``library_name`` **[optional]** + + If given, the name to use for the actual library file on disk. If + not given, the name is derived from the component name itself. + + - ``required_libraries`` **[optional]** + + If given, a list of the names of ``Library`` or ``LibraryGroup`` + components which must also be linked in whenever this library is + used. That is, the link time dependencies for this component. When + tools are built, the build system will include the transitive closure + of all ``required_libraries`` for the components the tool needs. + + - ``add_to_library_groups`` **[optional]** + + If given, a list of the names of ``LibraryGroup`` components which + this component is also part of. This allows nesting groups of + components. For example, the ``X86`` target might define a library + group for all of the ``X86`` components. That library group might + then be included in the ``all-targets`` library group. + + - ``installed`` **[optional]** **[boolean]** + + Whether this library is installed. Libraries that are not installed + are only reported by ``llvm-config`` when it is run as part of a + development directory. + +- ``type = LibraryGroup`` + + ``LibraryGroup`` components are a mechanism to allow easy definition of + useful sets of related components. In particular, we use them to easily + specify things like "all targets", or "all assembly printers". + + Components with this type use the following properties: + + - ``required_libraries`` **[optional]** + + See the ``Library`` type for a description of this property. + + - ``add_to_library_groups`` **[optional]** + + See the ``Library`` type for a description of this property. + +- ``type = TargetGroup`` + + ``TargetGroup`` components are an extension of ``LibraryGroup``\s, + specifically for defining LLVM targets (which are handled specially in a + few places). + + The name of the component should always be the name of the target. + + Components with this type use the ``LibraryGroup`` properties in + addition to: + + - ``has_asmparser`` **[optional]** **[boolean]** + + Whether this target defines an assembly parser. + + - ``has_asmprinter`` **[optional]** **[boolean]** + + Whether this target defines an assembly printer. + + - ``has_disassembler`` **[optional]** **[boolean]** + + Whether this target defines a disassembler. + + - ``has_jit`` **[optional]** **[boolean]** + + Whether this target supports JIT compilation. + +- ``type = Tool`` + + ``Tool`` components define standalone command line tools which should be + built from the source code in the component directory and linked. + + Components with this type use the following properties: + + - ``required_libraries`` **[optional]** + + If given, a list of the names of ``Library`` or ``LibraryGroup`` + components which this tool is required to be linked with. + + .. note:: + + The values should be the component names, which may not always + match up with the actual library names on disk. + + Build systems are expected to properly include all of the libraries + required by the linked components (i.e., the transitive closure of + ``required_libraries``). + + Build systems are also expected to understand that those library + components must be built prior to linking -- they do not also need + to be listed under ``dependencies``. + +- ``type = BuildTool`` + + ``BuildTool`` components are like ``Tool`` components, except that the + tool is supposed to be built for the platform where the build is running + (instead of that platform being targetted). Build systems are expected + to handle the fact that required libraries may need to be built for + multiple platforms in order to be able to link this tool. + + ``BuildTool`` components currently use the exact same properties as + ``Tool`` components, the type distinction is only used to differentiate + what the tool is built for. + diff --git a/docs/LLVMBuild.txt b/docs/LLVMBuild.txt new file mode 100644 index 00000000..d5aea864 --- /dev/null +++ b/docs/LLVMBuild.txt @@ -0,0 +1,21 @@ +;===- ./docs/LLVMBuild.txt -------------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Group +name = Docs +parent = $ROOT diff --git a/docs/LangRef.rst b/docs/LangRef.rst new file mode 100644 index 00000000..810455cb --- /dev/null +++ b/docs/LangRef.rst @@ -0,0 +1,8960 @@ +============================== +LLVM Language Reference Manual +============================== + +.. contents:: + :local: + :depth: 3 + +Abstract +======== + +This document is a reference manual for the LLVM assembly language. LLVM +is a Static Single Assignment (SSA) based representation that provides +type safety, low-level operations, flexibility, and the capability of +representing 'all' high-level languages cleanly. It is the common code +representation used throughout all phases of the LLVM compilation +strategy. + +Introduction +============ + +The LLVM code representation is designed to be used in three different +forms: as an in-memory compiler IR, as an on-disk bitcode representation +(suitable for fast loading by a Just-In-Time compiler), and as a human +readable assembly language representation. This allows LLVM to provide a +powerful intermediate representation for efficient compiler +transformations and analysis, while providing a natural means to debug +and visualize the transformations. The three different forms of LLVM are +all equivalent. This document describes the human readable +representation and notation. + +The LLVM representation aims to be light-weight and low-level while +being expressive, typed, and extensible at the same time. It aims to be +a "universal IR" of sorts, by being at a low enough level that +high-level ideas may be cleanly mapped to it (similar to how +microprocessors are "universal IR's", allowing many source languages to +be mapped to them). By providing type information, LLVM can be used as +the target of optimizations: for example, through pointer analysis, it +can be proven that a C automatic variable is never accessed outside of +the current function, allowing it to be promoted to a simple SSA value +instead of a memory location. + +.. _wellformed: + +Well-Formedness +--------------- + +It is important to note that this document describes 'well formed' LLVM +assembly language. There is a difference between what the parser accepts +and what is considered 'well formed'. For example, the following +instruction is syntactically okay, but not well formed: + +.. code-block:: llvm + + %x = add i32 1, %x + +because the definition of ``%x`` does not dominate all of its uses. The +LLVM infrastructure provides a verification pass that may be used to +verify that an LLVM module is well formed. This pass is automatically +run by the parser after parsing input assembly and by the optimizer +before it outputs bitcode. The violations pointed out by the verifier +pass indicate bugs in transformation passes or input to the parser. + +.. _identifiers: + +Identifiers +=========== + +LLVM identifiers come in two basic types: global and local. Global +identifiers (functions, global variables) begin with the ``'@'`` +character. Local identifiers (register names, types) begin with the +``'%'`` character. Additionally, there are three different formats for +identifiers, for different purposes: + +#. Named values are represented as a string of characters with their + prefix. For example, ``%foo``, ``@DivisionByZero``, + ``%a.really.long.identifier``. The actual regular expression used is + '``[%@][a-zA-Z$._][a-zA-Z$._0-9]*``'. Identifiers which require other + characters in their names can be surrounded with quotes. Special + characters may be escaped using ``"\xx"`` where ``xx`` is the ASCII + code for the character in hexadecimal. In this way, any character can + be used in a name value, even quotes themselves. +#. Unnamed values are represented as an unsigned numeric value with + their prefix. For example, ``%12``, ``@2``, ``%44``. +#. Constants, which are described in the section Constants_ below. + +LLVM requires that values start with a prefix for two reasons: Compilers +don't need to worry about name clashes with reserved words, and the set +of reserved words may be expanded in the future without penalty. +Additionally, unnamed identifiers allow a compiler to quickly come up +with a temporary variable without having to avoid symbol table +conflicts. + +Reserved words in LLVM are very similar to reserved words in other +languages. There are keywords for different opcodes ('``add``', +'``bitcast``', '``ret``', etc...), for primitive type names ('``void``', +'``i32``', etc...), and others. These reserved words cannot conflict +with variable names, because none of them start with a prefix character +(``'%'`` or ``'@'``). + +Here is an example of LLVM code to multiply the integer variable +'``%X``' by 8: + +The easy way: + +.. code-block:: llvm + + %result = mul i32 %X, 8 + +After strength reduction: + +.. code-block:: llvm + + %result = shl i32 %X, 3 + +And the hard way: + +.. code-block:: llvm + + %0 = add i32 %X, %X ; yields {i32}:%0 + %1 = add i32 %0, %0 ; yields {i32}:%1 + %result = add i32 %1, %1 + +This last way of multiplying ``%X`` by 8 illustrates several important +lexical features of LLVM: + +#. Comments are delimited with a '``;``' and go until the end of line. +#. Unnamed temporaries are created when the result of a computation is + not assigned to a named value. +#. Unnamed temporaries are numbered sequentially (using a per-function + incrementing counter, starting with 0). Note that basic blocks are + included in this numbering. For example, if the entry basic block is not + given a label name, then it will get number 0. + +It also shows a convention that we follow in this document. When +demonstrating instructions, we will follow an instruction with a comment +that defines the type and name of value produced. + +High Level Structure +==================== + +Module Structure +---------------- + +LLVM programs are composed of ``Module``'s, each of which is a +translation unit of the input programs. Each module consists of +functions, global variables, and symbol table entries. Modules may be +combined together with the LLVM linker, which merges function (and +global variable) definitions, resolves forward declarations, and merges +symbol table entries. Here is an example of the "hello world" module: + +.. code-block:: llvm + + ; Declare the string constant as a global constant. + @.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00" + + ; External declaration of the puts function + declare i32 @puts(i8* nocapture) nounwind + + ; Definition of main function + define i32 @main() { ; i32()* + ; Convert [13 x i8]* to i8 *... + %cast210 = getelementptr [13 x i8]* @.str, i64 0, i64 0 + + ; Call puts function to write out the string to stdout. + call i32 @puts(i8* %cast210) + ret i32 0 + } + + ; Named metadata + !1 = metadata !{i32 42} + !foo = !{!1, null} + +This example is made up of a :ref:`global variable ` named +"``.str``", an external declaration of the "``puts``" function, a +:ref:`function definition ` for "``main``" and +:ref:`named metadata ` "``foo``". + +In general, a module is made up of a list of global values (where both +functions and global variables are global values). Global values are +represented by a pointer to a memory location (in this case, a pointer +to an array of char, and a pointer to a function), and have one of the +following :ref:`linkage types `. + +.. _linkage: + +Linkage Types +------------- + +All Global Variables and Functions have one of the following types of +linkage: + +``private`` + Global values with "``private``" linkage are only directly + accessible by objects in the current module. In particular, linking + code into a module with an private global value may cause the + private to be renamed as necessary to avoid collisions. Because the + symbol is private to the module, all references can be updated. This + doesn't show up in any symbol table in the object file. +``linker_private`` + Similar to ``private``, but the symbol is passed through the + assembler and evaluated by the linker. Unlike normal strong symbols, + they are removed by the linker from the final linked image + (executable or dynamic library). +``linker_private_weak`` + Similar to "``linker_private``", but the symbol is weak. Note that + ``linker_private_weak`` symbols are subject to coalescing by the + linker. The symbols are removed by the linker from the final linked + image (executable or dynamic library). +``internal`` + Similar to private, but the value shows as a local symbol + (``STB_LOCAL`` in the case of ELF) in the object file. This + corresponds to the notion of the '``static``' keyword in C. +``available_externally`` + Globals with "``available_externally``" linkage are never emitted + into the object file corresponding to the LLVM module. They exist to + allow inlining and other optimizations to take place given knowledge + of the definition of the global, which is known to be somewhere + outside the module. Globals with ``available_externally`` linkage + are allowed to be discarded at will, and are otherwise the same as + ``linkonce_odr``. This linkage type is only allowed on definitions, + not declarations. +``linkonce`` + Globals with "``linkonce``" linkage are merged with other globals of + the same name when linkage occurs. This can be used to implement + some forms of inline functions, templates, or other code which must + be generated in each translation unit that uses it, but where the + body may be overridden with a more definitive definition later. + Unreferenced ``linkonce`` globals are allowed to be discarded. Note + that ``linkonce`` linkage does not actually allow the optimizer to + inline the body of this function into callers because it doesn't + know if this definition of the function is the definitive definition + within the program or whether it will be overridden by a stronger + definition. To enable inlining and other optimizations, use + "``linkonce_odr``" linkage. +``weak`` + "``weak``" linkage has the same merging semantics as ``linkonce`` + linkage, except that unreferenced globals with ``weak`` linkage may + not be discarded. This is used for globals that are declared "weak" + in C source code. +``common`` + "``common``" linkage is most similar to "``weak``" linkage, but they + are used for tentative definitions in C, such as "``int X;``" at + global scope. Symbols with "``common``" linkage are merged in the + same way as ``weak symbols``, and they may not be deleted if + unreferenced. ``common`` symbols may not have an explicit section, + must have a zero initializer, and may not be marked + ':ref:`constant `'. Functions and aliases may not have + common linkage. + +.. _linkage_appending: + +``appending`` + "``appending``" linkage may only be applied to global variables of + pointer to array type. When two global variables with appending + linkage are linked together, the two global arrays are appended + together. This is the LLVM, typesafe, equivalent of having the + system linker append together "sections" with identical names when + .o files are linked. +``extern_weak`` + The semantics of this linkage follow the ELF object file model: the + symbol is weak until linked, if not linked, the symbol becomes null + instead of being an undefined reference. +``linkonce_odr``, ``weak_odr`` + Some languages allow differing globals to be merged, such as two + functions with different semantics. Other languages, such as + ``C++``, ensure that only equivalent globals are ever merged (the + "one definition rule" --- "ODR"). Such languages can use the + ``linkonce_odr`` and ``weak_odr`` linkage types to indicate that the + global will only be merged with equivalent globals. These linkage + types are otherwise the same as their non-``odr`` versions. +``external`` + If none of the above identifiers are used, the global is externally + visible, meaning that it participates in linkage and can be used to + resolve external symbol references. + +The next two types of linkage are targeted for Microsoft Windows +platform only. They are designed to support importing (exporting) +symbols from (to) DLLs (Dynamic Link Libraries). + +``dllimport`` + "``dllimport``" linkage causes the compiler to reference a function + or variable via a global pointer to a pointer that is set up by the + DLL exporting the symbol. On Microsoft Windows targets, the pointer + name is formed by combining ``__imp_`` and the function or variable + name. +``dllexport`` + "``dllexport``" linkage causes the compiler to provide a global + pointer to a pointer in a DLL, so that it can be referenced with the + ``dllimport`` attribute. On Microsoft Windows targets, the pointer + name is formed by combining ``__imp_`` and the function or variable + name. + +For example, since the "``.LC0``" variable is defined to be internal, if +another module defined a "``.LC0``" variable and was linked with this +one, one of the two would be renamed, preventing a collision. Since +"``main``" and "``puts``" are external (i.e., lacking any linkage +declarations), they are accessible outside of the current module. + +It is illegal for a function *declaration* to have any linkage type +other than ``external``, ``dllimport`` or ``extern_weak``. + +.. _callingconv: + +Calling Conventions +------------------- + +LLVM :ref:`functions `, :ref:`calls ` and +:ref:`invokes ` can all have an optional calling convention +specified for the call. The calling convention of any pair of dynamic +caller/callee must match, or the behavior of the program is undefined. +The following calling conventions are supported by LLVM, and more may be +added in the future: + +"``ccc``" - The C calling convention + This calling convention (the default if no other calling convention + is specified) matches the target C calling conventions. This calling + convention supports varargs function calls and tolerates some + mismatch in the declared prototype and implemented declaration of + the function (as does normal C). +"``fastcc``" - The fast calling convention + This calling convention attempts to make calls as fast as possible + (e.g. by passing things in registers). This calling convention + allows the target to use whatever tricks it wants to produce fast + code for the target, without having to conform to an externally + specified ABI (Application Binary Interface). `Tail calls can only + be optimized when this, the GHC or the HiPE convention is + used. `_ This calling convention does not + support varargs and requires the prototype of all callees to exactly + match the prototype of the function definition. +"``coldcc``" - The cold calling convention + This calling convention attempts to make code in the caller as + efficient as possible under the assumption that the call is not + commonly executed. As such, these calls often preserve all registers + so that the call does not break any live ranges in the caller side. + This calling convention does not support varargs and requires the + prototype of all callees to exactly match the prototype of the + function definition. +"``cc 10``" - GHC convention + This calling convention has been implemented specifically for use by + the `Glasgow Haskell Compiler (GHC) `_. + It passes everything in registers, going to extremes to achieve this + by disabling callee save registers. This calling convention should + not be used lightly but only for specific situations such as an + alternative to the *register pinning* performance technique often + used when implementing functional programming languages. At the + moment only X86 supports this convention and it has the following + limitations: + + - On *X86-32* only supports up to 4 bit type parameters. No + floating point types are supported. + - On *X86-64* only supports up to 10 bit type parameters and 6 + floating point parameters. + + This calling convention supports `tail call + optimization `_ but requires both the + caller and callee are using it. +"``cc 11``" - The HiPE calling convention + This calling convention has been implemented specifically for use by + the `High-Performance Erlang + (HiPE) `_ compiler, *the* + native code compiler of the `Ericsson's Open Source Erlang/OTP + system `_. It uses more + registers for argument passing than the ordinary C calling + convention and defines no callee-saved registers. The calling + convention properly supports `tail call + optimization `_ but requires that both the + caller and the callee use it. It uses a *register pinning* + mechanism, similar to GHC's convention, for keeping frequently + accessed runtime components pinned to specific hardware registers. + At the moment only X86 supports this convention (both 32 and 64 + bit). +"``cc ``" - Numbered convention + Any calling convention may be specified by number, allowing + target-specific calling conventions to be used. Target specific + calling conventions start at 64. + +More calling conventions can be added/defined on an as-needed basis, to +support Pascal conventions or any other well-known target-independent +convention. + +.. _visibilitystyles: + +Visibility Styles +----------------- + +All Global Variables and Functions have one of the following visibility +styles: + +"``default``" - Default style + On targets that use the ELF object file format, default visibility + means that the declaration is visible to other modules and, in + shared libraries, means that the declared entity may be overridden. + On Darwin, default visibility means that the declaration is visible + to other modules. Default visibility corresponds to "external + linkage" in the language. +"``hidden``" - Hidden style + Two declarations of an object with hidden visibility refer to the + same object if they are in the same shared object. Usually, hidden + visibility indicates that the symbol will not be placed into the + dynamic symbol table, so no other module (executable or shared + library) can reference it directly. +"``protected``" - Protected style + On ELF, protected visibility indicates that the symbol will be + placed in the dynamic symbol table, but that references within the + defining module will bind to the local symbol. That is, the symbol + cannot be overridden by another module. + +.. _namedtypes: + +Named Types +----------- + +LLVM IR allows you to specify name aliases for certain types. This can +make it easier to read the IR and make the IR more condensed +(particularly when recursive types are involved). An example of a name +specification is: + +.. code-block:: llvm + + %mytype = type { %mytype*, i32 } + +You may give a name to any :ref:`type ` except +":ref:`void `". Type name aliases may be used anywhere a type is +expected with the syntax "%mytype". + +Note that type names are aliases for the structural type that they +indicate, and that you can therefore specify multiple names for the same +type. This often leads to confusing behavior when dumping out a .ll +file. Since LLVM IR uses structural typing, the name is not part of the +type. When printing out LLVM IR, the printer will pick *one name* to +render all types of a particular shape. This means that if you have code +where two different source types end up having the same LLVM type, that +the dumper will sometimes print the "wrong" or unexpected type. This is +an important design point and isn't going to change. + +.. _globalvars: + +Global Variables +---------------- + +Global variables define regions of memory allocated at compilation time +instead of run-time. + +Global variables definitions must be initialized, may have an explicit section +to be placed in, and may have an optional explicit alignment specified. + +Global variables in other translation units can also be declared, in which +case they don't have an initializer. + +A variable may be defined as ``thread_local``, which means that it will +not be shared by threads (each thread will have a separated copy of the +variable). Not all targets support thread-local variables. Optionally, a +TLS model may be specified: + +``localdynamic`` + For variables that are only used within the current shared library. +``initialexec`` + For variables in modules that will not be loaded dynamically. +``localexec`` + For variables defined in the executable and only used within it. + +The models correspond to the ELF TLS models; see `ELF Handling For +Thread-Local Storage `_ for +more information on under which circumstances the different models may +be used. The target may choose a different TLS model if the specified +model is not supported, or if a better choice of model can be made. + +A variable may be defined as a global ``constant``, which indicates that +the contents of the variable will **never** be modified (enabling better +optimization, allowing the global data to be placed in the read-only +section of an executable, etc). Note that variables that need runtime +initialization cannot be marked ``constant`` as there is a store to the +variable. + +LLVM explicitly allows *declarations* of global variables to be marked +constant, even if the final definition of the global is not. This +capability can be used to enable slightly better optimization of the +program, but requires the language definition to guarantee that +optimizations based on the 'constantness' are valid for the translation +units that do not include the definition. + +As SSA values, global variables define pointer values that are in scope +(i.e. they dominate) all basic blocks in the program. Global variables +always define a pointer to their "content" type because they describe a +region of memory, and all memory objects in LLVM are accessed through +pointers. + +Global variables can be marked with ``unnamed_addr`` which indicates +that the address is not significant, only the content. Constants marked +like this can be merged with other constants if they have the same +initializer. Note that a constant with significant address *can* be +merged with a ``unnamed_addr`` constant, the result being a constant +whose address is significant. + +A global variable may be declared to reside in a target-specific +numbered address space. For targets that support them, address spaces +may affect how optimizations are performed and/or what target +instructions are used to access the variable. The default address space +is zero. The address space qualifier must precede any other attributes. + +LLVM allows an explicit section to be specified for globals. If the +target supports it, it will emit globals to the section specified. + +By default, global initializers are optimized by assuming that global +variables defined within the module are not modified from their +initial values before the start of the global initializer. This is +true even for variables potentially accessible from outside the +module, including those with external linkage or appearing in +``@llvm.used``. This assumption may be suppressed by marking the +variable with ``externally_initialized``. + +An explicit alignment may be specified for a global, which must be a +power of 2. If not present, or if the alignment is set to zero, the +alignment of the global is set by the target to whatever it feels +convenient. If an explicit alignment is specified, the global is forced +to have exactly that alignment. Targets and optimizers are not allowed +to over-align the global if the global has an assigned section. In this +case, the extra alignment could be observable: for example, code could +assume that the globals are densely packed in their section and try to +iterate over them as an array, alignment padding would break this +iteration. + +For example, the following defines a global in a numbered address space +with an initializer, section, and alignment: + +.. code-block:: llvm + + @G = addrspace(5) constant float 1.0, section "foo", align 4 + +The following example just declares a global variable + +.. code-block:: llvm + + @G = external global i32 + +The following example defines a thread-local global with the +``initialexec`` TLS model: + +.. code-block:: llvm + + @G = thread_local(initialexec) global i32 0, align 4 + +.. _functionstructure: + +Functions +--------- + +LLVM function definitions consist of the "``define``" keyword, an +optional :ref:`linkage type `, an optional :ref:`visibility +style `, an optional :ref:`calling convention `, +an optional ``unnamed_addr`` attribute, a return type, an optional +:ref:`parameter attribute ` for the return type, a function +name, a (possibly empty) argument list (each with optional :ref:`parameter +attributes `), optional :ref:`function attributes `, +an optional section, an optional alignment, an optional :ref:`garbage +collector name `, an optional :ref:`prefix `, an opening +curly brace, a list of basic blocks, and a closing curly brace. + +LLVM function declarations consist of the "``declare``" keyword, an +optional :ref:`linkage type `, an optional :ref:`visibility +style `, an optional :ref:`calling convention `, +an optional ``unnamed_addr`` attribute, a return type, an optional +:ref:`parameter attribute ` for the return type, a function +name, a possibly empty list of arguments, an optional alignment, an optional +:ref:`garbage collector name ` and an optional :ref:`prefix `. + +A function definition contains a list of basic blocks, forming the CFG (Control +Flow Graph) for the function. Each basic block may optionally start with a label +(giving the basic block a symbol table entry), contains a list of instructions, +and ends with a :ref:`terminator ` instruction (such as a branch or +function return). If an explicit label is not provided, a block is assigned an +implicit numbered label, using the next value from the same counter as used for +unnamed temporaries (:ref:`see above`). For example, if a function +entry block does not have an explicit label, it will be assigned label "%0", +then the first unnamed temporary in that block will be "%1", etc. + +The first basic block in a function is special in two ways: it is +immediately executed on entrance to the function, and it is not allowed +to have predecessor basic blocks (i.e. there can not be any branches to +the entry block of a function). Because the block can have no +predecessors, it also cannot have any :ref:`PHI nodes `. + +LLVM allows an explicit section to be specified for functions. If the +target supports it, it will emit functions to the section specified. + +An explicit alignment may be specified for a function. If not present, +or if the alignment is set to zero, the alignment of the function is set +by the target to whatever it feels convenient. If an explicit alignment +is specified, the function is forced to have at least that much +alignment. All alignments must be a power of 2. + +If the ``unnamed_addr`` attribute is given, the address is know to not +be significant and two identical functions can be merged. + +Syntax:: + + define [linkage] [visibility] + [cconv] [ret attrs] + @ ([argument list]) + [fn Attrs] [section "name"] [align N] + [gc] [prefix Constant] { ... } + +.. _langref_aliases: + +Aliases +------- + +Aliases act as "second name" for the aliasee value (which can be either +function, global variable, another alias or bitcast of global value). +Aliases may have an optional :ref:`linkage type `, and an optional +:ref:`visibility style `. + +Syntax:: + + @ = alias [Linkage] [Visibility] @ + +The linkage must be one of ``private``, ``linker_private``, +``linker_private_weak``, ``internal``, ``linkonce``, ``weak``, +``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers +might not correctly handle dropping a weak symbol that is aliased by a non weak +alias. + +.. _namedmetadatastructure: + +Named Metadata +-------------- + +Named metadata is a collection of metadata. :ref:`Metadata +nodes ` (but not metadata strings) are the only valid +operands for a named metadata. + +Syntax:: + + ; Some unnamed metadata nodes, which are referenced by the named metadata. + !0 = metadata !{metadata !"zero"} + !1 = metadata !{metadata !"one"} + !2 = metadata !{metadata !"two"} + ; A named metadata. + !name = !{!0, !1, !2} + +.. _paramattrs: + +Parameter Attributes +-------------------- + +The return type and each parameter of a function type may have a set of +*parameter attributes* associated with them. Parameter attributes are +used to communicate additional information about the result or +parameters of a function. Parameter attributes are considered to be part +of the function, not of the function type, so functions with different +parameter attributes can have the same function type. + +Parameter attributes are simple keywords that follow the type specified. +If multiple parameter attributes are needed, they are space separated. +For example: + +.. code-block:: llvm + + declare i32 @printf(i8* noalias nocapture, ...) + declare i32 @atoi(i8 zeroext) + declare signext i8 @returns_signed_char() + +Note that any attributes for the function result (``nounwind``, +``readonly``) come immediately after the argument list. + +Currently, only the following parameter attributes are defined: + +``zeroext`` + This indicates to the code generator that the parameter or return + value should be zero-extended to the extent required by the target's + ABI (which is usually 32-bits, but is 8-bits for a i1 on x86-64) by + the caller (for a parameter) or the callee (for a return value). +``signext`` + This indicates to the code generator that the parameter or return + value should be sign-extended to the extent required by the target's + ABI (which is usually 32-bits) by the caller (for a parameter) or + the callee (for a return value). +``inreg`` + This indicates that this parameter or return value should be treated + in a special target-dependent fashion during while emitting code for + a function call or return (usually, by putting it in a register as + opposed to memory, though some targets use it to distinguish between + two different kinds of registers). Use of this attribute is + target-specific. +``byval`` + This indicates that the pointer parameter should really be passed by + value to the function. The attribute implies that a hidden copy of + the pointee is made between the caller and the callee, so the callee + is unable to modify the value in the caller. This attribute is only + valid on LLVM pointer arguments. It is generally used to pass + structs and arrays by value, but is also valid on pointers to + scalars. The copy is considered to belong to the caller not the + callee (for example, ``readonly`` functions should not write to + ``byval`` parameters). This is not a valid attribute for return + values. + + The byval attribute also supports specifying an alignment with the + align attribute. It indicates the alignment of the stack slot to + form and the known alignment of the pointer specified to the call + site. If the alignment is not specified, then the code generator + makes a target-specific assumption. + +``sret`` + This indicates that the pointer parameter specifies the address of a + structure that is the return value of the function in the source + program. This pointer must be guaranteed by the caller to be valid: + loads and stores to the structure may be assumed by the callee + not to trap and to be properly aligned. This may only be applied to + the first parameter. This is not a valid attribute for return + values. +``noalias`` + This indicates that pointer values :ref:`based ` on + the argument or return value do not alias pointer values which are + not *based* on it, ignoring certain "irrelevant" dependencies. For a + call to the parent function, dependencies between memory references + from before or after the call and from those during the call are + "irrelevant" to the ``noalias`` keyword for the arguments and return + value used in that call. The caller shares the responsibility with + the callee for ensuring that these requirements are met. For further + details, please see the discussion of the NoAlias response in `alias + analysis `_. + + Note that this definition of ``noalias`` is intentionally similar + to the definition of ``restrict`` in C99 for function arguments, + though it is slightly weaker. + + For function return values, C99's ``restrict`` is not meaningful, + while LLVM's ``noalias`` is. +``nocapture`` + This indicates that the callee does not make any copies of the + pointer that outlive the callee itself. This is not a valid + attribute for return values. + +.. _nest: + +``nest`` + This indicates that the pointer parameter can be excised using the + :ref:`trampoline intrinsics `. This is not a valid + attribute for return values and can only be applied to one parameter. + +``returned`` + This indicates that the function always returns the argument as its return + value. This is an optimization hint to the code generator when generating + the caller, allowing tail call optimization and omission of register saves + and restores in some cases; it is not checked or enforced when generating + the callee. The parameter and the function return type must be valid + operands for the :ref:`bitcast instruction `. This is not a + valid attribute for return values and can only be applied to one parameter. + +.. _gc: + +Garbage Collector Names +----------------------- + +Each function may specify a garbage collector name, which is simply a +string: + +.. code-block:: llvm + + define void @f() gc "name" { ... } + +The compiler declares the supported values of *name*. Specifying a +collector which will cause the compiler to alter its output in order to +support the named garbage collection algorithm. + +.. _prefixdata: + +Prefix Data +----------- + +Prefix data is data associated with a function which the code generator +will emit immediately before the function body. The purpose of this feature +is to allow frontends to associate language-specific runtime metadata with +specific functions and make it available through the function pointer while +still allowing the function pointer to be called. To access the data for a +given function, a program may bitcast the function pointer to a pointer to +the constant's type. This implies that the IR symbol points to the start +of the prefix data. + +To maintain the semantics of ordinary function calls, the prefix data must +have a particular format. Specifically, it must begin with a sequence of +bytes which decode to a sequence of machine instructions, valid for the +module's target, which transfer control to the point immediately succeeding +the prefix data, without performing any other visible action. This allows +the inliner and other passes to reason about the semantics of the function +definition without needing to reason about the prefix data. Obviously this +makes the format of the prefix data highly target dependent. + +Prefix data is laid out as if it were an initializer for a global variable +of the prefix data's type. No padding is automatically placed between the +prefix data and the function body. If padding is required, it must be part +of the prefix data. + +A trivial example of valid prefix data for the x86 architecture is ``i8 144``, +which encodes the ``nop`` instruction: + +.. code-block:: llvm + + define void @f() prefix i8 144 { ... } + +Generally prefix data can be formed by encoding a relative branch instruction +which skips the metadata, as in this example of valid prefix data for the +x86_64 architecture, where the first two bytes encode ``jmp .+10``: + +.. code-block:: llvm + + %0 = type <{ i8, i8, i8* }> + + define void @f() prefix %0 <{ i8 235, i8 8, i8* @md}> { ... } + +A function may have prefix data but no body. This has similar semantics +to the ``available_externally`` linkage in that the data may be used by the +optimizers but will not be emitted in the object file. + +.. _attrgrp: + +Attribute Groups +---------------- + +Attribute groups are groups of attributes that are referenced by objects within +the IR. They are important for keeping ``.ll`` files readable, because a lot of +functions will use the same set of attributes. In the degenerative case of a +``.ll`` file that corresponds to a single ``.c`` file, the single attribute +group will capture the important command line flags used to build that file. + +An attribute group is a module-level object. To use an attribute group, an +object references the attribute group's ID (e.g. ``#37``). An object may refer +to more than one attribute group. In that situation, the attributes from the +different groups are merged. + +Here is an example of attribute groups for a function that should always be +inlined, has a stack alignment of 4, and which shouldn't use SSE instructions: + +.. code-block:: llvm + + ; Target-independent attributes: + attributes #0 = { alwaysinline alignstack=4 } + + ; Target-dependent attributes: + attributes #1 = { "no-sse" } + + ; Function @f has attributes: alwaysinline, alignstack=4, and "no-sse". + define void @f() #0 #1 { ... } + +.. _fnattrs: + +Function Attributes +------------------- + +Function attributes are set to communicate additional information about +a function. Function attributes are considered to be part of the +function, not of the function type, so functions with different function +attributes can have the same function type. + +Function attributes are simple keywords that follow the type specified. +If multiple attributes are needed, they are space separated. For +example: + +.. code-block:: llvm + + define void @f() noinline { ... } + define void @f() alwaysinline { ... } + define void @f() alwaysinline optsize { ... } + define void @f() optsize { ... } + +``alignstack()`` + This attribute indicates that, when emitting the prologue and + epilogue, the backend should forcibly align the stack pointer. + Specify the desired alignment, which must be a power of two, in + parentheses. +``alwaysinline`` + This attribute indicates that the inliner should attempt to inline + this function into callers whenever possible, ignoring any active + inlining size threshold for this caller. +``builtin`` + This indicates that the callee function at a call site should be + recognized as a built-in function, even though the function's declaration + uses the ``nobuiltin`` attribute. This is only valid at call sites for + direct calls to functions which are declared with the ``nobuiltin`` + attribute. +``cold`` + This attribute indicates that this function is rarely called. When + computing edge weights, basic blocks post-dominated by a cold + function call are also considered to be cold; and, thus, given low + weight. +``inlinehint`` + This attribute indicates that the source code contained a hint that + inlining this function is desirable (such as the "inline" keyword in + C/C++). It is just a hint; it imposes no requirements on the + inliner. +``minsize`` + This attribute suggests that optimization passes and code generator + passes make choices that keep the code size of this function as small + as possible and perform optimizations that may sacrifice runtime + performance in order to minimize the size of the generated code. +``naked`` + This attribute disables prologue / epilogue emission for the + function. This can have very system-specific consequences. +``nobuiltin`` + This indicates that the callee function at a call site is not recognized as + a built-in function. LLVM will retain the original call and not replace it + with equivalent code based on the semantics of the built-in function, unless + the call site uses the ``builtin`` attribute. This is valid at call sites + and on function declarations and definitions. +``noduplicate`` + This attribute indicates that calls to the function cannot be + duplicated. A call to a ``noduplicate`` function may be moved + within its parent function, but may not be duplicated within + its parent function. + + A function containing a ``noduplicate`` call may still + be an inlining candidate, provided that the call is not + duplicated by inlining. That implies that the function has + internal linkage and only has one call site, so the original + call is dead after inlining. +``noimplicitfloat`` + This attributes disables implicit floating point instructions. +``noinline`` + This attribute indicates that the inliner should never inline this + function in any situation. This attribute may not be used together + with the ``alwaysinline`` attribute. +``nonlazybind`` + This attribute suppresses lazy symbol binding for the function. This + may make calls to the function faster, at the cost of extra program + startup time if the function is not called during program startup. +``noredzone`` + This attribute indicates that the code generator should not use a + red zone, even if the target-specific ABI normally permits it. +``noreturn`` + This function attribute indicates that the function never returns + normally. This produces undefined behavior at runtime if the + function ever does dynamically return. +``nounwind`` + This function attribute indicates that the function never returns + with an unwind or exceptional control flow. If the function does + unwind, its runtime behavior is undefined. +``optnone`` + This function attribute indicates that the function is not optimized + by any optimization or code generator passes with the + exception of interprocedural optimization passes. + This attribute cannot be used together with the ``alwaysinline`` + attribute; this attribute is also incompatible + with the ``minsize`` attribute and the ``optsize`` attribute. + + This attribute requires the ``noinline`` attribute to be specified on + the function as well, so the function is never inlined into any caller. + Only functions with the ``alwaysinline`` attribute are valid + candidates for inlining into the body of this function. +``optsize`` + This attribute suggests that optimization passes and code generator + passes make choices that keep the code size of this function low, + and otherwise do optimizations specifically to reduce code size as + long as they do not significantly impact runtime performance. +``readnone`` + On a function, this attribute indicates that the function computes its + result (or decides to unwind an exception) based strictly on its arguments, + without dereferencing any pointer arguments or otherwise accessing + any mutable state (e.g. memory, control registers, etc) visible to + caller functions. It does not write through any pointer arguments + (including ``byval`` arguments) and never changes any state visible + to callers. This means that it cannot unwind exceptions by calling + the ``C++`` exception throwing methods. + + On an argument, this attribute indicates that the function does not + dereference that pointer argument, even though it may read or write the + memory that the pointer points to if accessed through other pointers. +``readonly`` + On a function, this attribute indicates that the function does not write + through any pointer arguments (including ``byval`` arguments) or otherwise + modify any state (e.g. memory, control registers, etc) visible to + caller functions. It may dereference pointer arguments and read + state that may be set in the caller. A readonly function always + returns the same value (or unwinds an exception identically) when + called with the same set of arguments and global state. It cannot + unwind an exception by calling the ``C++`` exception throwing + methods. + + On an argument, this attribute indicates that the function does not write + through this pointer argument, even though it may write to the memory that + the pointer points to. +``returns_twice`` + This attribute indicates that this function can return twice. The C + ``setjmp`` is an example of such a function. The compiler disables + some optimizations (like tail calls) in the caller of these + functions. +``sanitize_address`` + This attribute indicates that AddressSanitizer checks + (dynamic address safety analysis) are enabled for this function. +``sanitize_memory`` + This attribute indicates that MemorySanitizer checks (dynamic detection + of accesses to uninitialized memory) are enabled for this function. +``sanitize_thread`` + This attribute indicates that ThreadSanitizer checks + (dynamic thread safety analysis) are enabled for this function. +``ssp`` + This attribute indicates that the function should emit a stack + smashing protector. It is in the form of a "canary" --- a random value + placed on the stack before the local variables that's checked upon + return from the function to see if it has been overwritten. A + heuristic is used to determine if a function needs stack protectors + or not. The heuristic used will enable protectors for functions with: + + - Character arrays larger than ``ssp-buffer-size`` (default 8). + - Aggregates containing character arrays larger than ``ssp-buffer-size``. + - Calls to alloca() with variable sizes or constant sizes greater than + ``ssp-buffer-size``. + + If a function that has an ``ssp`` attribute is inlined into a + function that doesn't have an ``ssp`` attribute, then the resulting + function will have an ``ssp`` attribute. +``sspreq`` + This attribute indicates that the function should *always* emit a + stack smashing protector. This overrides the ``ssp`` function + attribute. + + If a function that has an ``sspreq`` attribute is inlined into a + function that doesn't have an ``sspreq`` attribute or which has an + ``ssp`` or ``sspstrong`` attribute, then the resulting function will have + an ``sspreq`` attribute. +``sspstrong`` + This attribute indicates that the function should emit a stack smashing + protector. This attribute causes a strong heuristic to be used when + determining if a function needs stack protectors. The strong heuristic + will enable protectors for functions with: + + - Arrays of any size and type + - Aggregates containing an array of any size and type. + - Calls to alloca(). + - Local variables that have had their address taken. + + This overrides the ``ssp`` function attribute. + + If a function that has an ``sspstrong`` attribute is inlined into a + function that doesn't have an ``sspstrong`` attribute, then the + resulting function will have an ``sspstrong`` attribute. +``uwtable`` + This attribute indicates that the ABI being targeted requires that + an unwind table entry be produce for this function even if we can + show that no exceptions passes by it. This is normally the case for + the ELF x86-64 abi, but it can be disabled for some compilation + units. + +.. _moduleasm: + +Module-Level Inline Assembly +---------------------------- + +Modules may contain "module-level inline asm" blocks, which corresponds +to the GCC "file scope inline asm" blocks. These blocks are internally +concatenated by LLVM and treated as a single unit, but may be separated +in the ``.ll`` file if desired. The syntax is very simple: + +.. code-block:: llvm + + module asm "inline asm code goes here" + module asm "more can go here" + +The strings can contain any character by escaping non-printable +characters. The escape sequence used is simply "\\xx" where "xx" is the +two digit hex code for the number. + +The inline asm code is simply printed to the machine code .s file when +assembly code is generated. + +.. _langref_datalayout: + +Data Layout +----------- + +A module may specify a target specific data layout string that specifies +how data is to be laid out in memory. The syntax for the data layout is +simply: + +.. code-block:: llvm + + target datalayout = "layout specification" + +The *layout specification* consists of a list of specifications +separated by the minus sign character ('-'). Each specification starts +with a letter and may include other information after the letter to +define some aspect of the data layout. The specifications accepted are +as follows: + +``E`` + Specifies that the target lays out data in big-endian form. That is, + the bits with the most significance have the lowest address + location. +``e`` + Specifies that the target lays out data in little-endian form. That + is, the bits with the least significance have the lowest address + location. +``S`` + Specifies the natural alignment of the stack in bits. Alignment + promotion of stack variables is limited to the natural stack + alignment to avoid dynamic stack realignment. The stack alignment + must be a multiple of 8-bits. If omitted, the natural stack + alignment defaults to "unspecified", which does not prevent any + alignment promotions. +``p[n]:::`` + This specifies the *size* of a pointer and its ```` and + ````\erred alignments for address space ``n``. All sizes are in + bits. Specifying the ```` alignment is optional. If omitted, the + preceding ``:`` should be omitted too. The address space, ``n`` is + optional, and if not specified, denotes the default address space 0. + The value of ``n`` must be in the range [1,2^23). +``i::`` + This specifies the alignment for an integer type of a given bit + ````. The value of ```` must be in the range [1,2^23). +``v::`` + This specifies the alignment for a vector type of a given bit + ````. +``f::`` + This specifies the alignment for a floating point type of a given bit + ````. Only values of ```` that are supported by the target + will work. 32 (float) and 64 (double) are supported on all targets; 80 + or 128 (different flavors of long double) are also supported on some + targets. +``a::`` + This specifies the alignment for an aggregate type of a given bit + ````. +``s::`` + This specifies the alignment for a stack object of a given bit + ````. +``n::...`` + This specifies a set of native integer widths for the target CPU in + bits. For example, it might contain ``n32`` for 32-bit PowerPC, + ``n32:64`` for PowerPC 64, or ``n8:16:32:64`` for X86-64. Elements of + this set are considered to support most general arithmetic operations + efficiently. + +When constructing the data layout for a given target, LLVM starts with a +default set of specifications which are then (possibly) overridden by +the specifications in the ``datalayout`` keyword. The default +specifications are given in this list: + +- ``E`` - big endian +- ``p:64:64:64`` - 64-bit pointers with 64-bit alignment. +- ``p[n]:64:64:64`` - Other address spaces are assumed to be the + same as the default address space. +- ``S0`` - natural stack alignment is unspecified +- ``i1:8:8`` - i1 is 8-bit (byte) aligned +- ``i8:8:8`` - i8 is 8-bit (byte) aligned +- ``i16:16:16`` - i16 is 16-bit aligned +- ``i32:32:32`` - i32 is 32-bit aligned +- ``i64:32:64`` - i64 has ABI alignment of 32-bits but preferred + alignment of 64-bits +- ``f16:16:16`` - half is 16-bit aligned +- ``f32:32:32`` - float is 32-bit aligned +- ``f64:64:64`` - double is 64-bit aligned +- ``f128:128:128`` - quad is 128-bit aligned +- ``v64:64:64`` - 64-bit vector is 64-bit aligned +- ``v128:128:128`` - 128-bit vector is 128-bit aligned +- ``a0:0:64`` - aggregates are 64-bit aligned + +When LLVM is determining the alignment for a given type, it uses the +following rules: + +#. If the type sought is an exact match for one of the specifications, + that specification is used. +#. If no match is found, and the type sought is an integer type, then + the smallest integer type that is larger than the bitwidth of the + sought type is used. If none of the specifications are larger than + the bitwidth then the largest integer type is used. For example, + given the default specifications above, the i7 type will use the + alignment of i8 (next largest) while both i65 and i256 will use the + alignment of i64 (largest specified). +#. If no match is found, and the type sought is a vector type, then the + largest vector type that is smaller than the sought vector type will + be used as a fall back. This happens because <128 x double> can be + implemented in terms of 64 <2 x double>, for example. + +The function of the data layout string may not be what you expect. +Notably, this is not a specification from the frontend of what alignment +the code generator should use. + +Instead, if specified, the target data layout is required to match what +the ultimate *code generator* expects. This string is used by the +mid-level optimizers to improve code, and this only works if it matches +what the ultimate code generator uses. If you would like to generate IR +that does not embed this target-specific detail into the IR, then you +don't have to specify the string. This will disable some optimizations +that require precise layout information, but this also prevents those +optimizations from introducing target specificity into the IR. + +.. _langref_triple: + +Target Triple +------------- + +A module may specify a target triple string that describes the target +host. The syntax for the target triple is simply: + +.. code-block:: llvm + + target triple = "x86_64-apple-macosx10.7.0" + +The *target triple* string consists of a series of identifiers delimited +by the minus sign character ('-'). The canonical forms are: + +:: + + ARCHITECTURE-VENDOR-OPERATING_SYSTEM + ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT + +This information is passed along to the backend so that it generates +code for the proper architecture. It's possible to override this on the +command line with the ``-mtriple`` command line option. + +.. _pointeraliasing: + +Pointer Aliasing Rules +---------------------- + +Any memory access must be done through a pointer value associated with +an address range of the memory access, otherwise the behavior is +undefined. Pointer values are associated with address ranges according +to the following rules: + +- A pointer value is associated with the addresses associated with any + value it is *based* on. +- An address of a global variable is associated with the address range + of the variable's storage. +- The result value of an allocation instruction is associated with the + address range of the allocated storage. +- A null pointer in the default address-space is associated with no + address. +- An integer constant other than zero or a pointer value returned from + a function not defined within LLVM may be associated with address + ranges allocated through mechanisms other than those provided by + LLVM. Such ranges shall not overlap with any ranges of addresses + allocated by mechanisms provided by LLVM. + +A pointer value is *based* on another pointer value according to the +following rules: + +- A pointer value formed from a ``getelementptr`` operation is *based* + on the first operand of the ``getelementptr``. +- The result value of a ``bitcast`` is *based* on the operand of the + ``bitcast``. +- A pointer value formed by an ``inttoptr`` is *based* on all pointer + values that contribute (directly or indirectly) to the computation of + the pointer's value. +- The "*based* on" relationship is transitive. + +Note that this definition of *"based"* is intentionally similar to the +definition of *"based"* in C99, though it is slightly weaker. + +LLVM IR does not associate types with memory. The result type of a +``load`` merely indicates the size and alignment of the memory from +which to load, as well as the interpretation of the value. The first +operand type of a ``store`` similarly only indicates the size and +alignment of the store. + +Consequently, type-based alias analysis, aka TBAA, aka +``-fstrict-aliasing``, is not applicable to general unadorned LLVM IR. +:ref:`Metadata ` may be used to encode additional information +which specialized optimization passes may use to implement type-based +alias analysis. + +.. _volatile: + +Volatile Memory Accesses +------------------------ + +Certain memory accesses, such as :ref:`load `'s, +:ref:`store `'s, and :ref:`llvm.memcpy `'s may be +marked ``volatile``. The optimizers must not change the number of +volatile operations or change their order of execution relative to other +volatile operations. The optimizers *may* change the order of volatile +operations relative to non-volatile operations. This is not Java's +"volatile" and has no cross-thread synchronization behavior. + +IR-level volatile loads and stores cannot safely be optimized into +llvm.memcpy or llvm.memmove intrinsics even when those intrinsics are +flagged volatile. Likewise, the backend should never split or merge +target-legal volatile load/store instructions. + +.. admonition:: Rationale + + Platforms may rely on volatile loads and stores of natively supported + data width to be executed as single instruction. For example, in C + this holds for an l-value of volatile primitive type with native + hardware support, but not necessarily for aggregate types. The + frontend upholds these expectations, which are intentionally + unspecified in the IR. The rules above ensure that IR transformation + do not violate the frontend's contract with the language. + +.. _memmodel: + +Memory Model for Concurrent Operations +-------------------------------------- + +The LLVM IR does not define any way to start parallel threads of +execution or to register signal handlers. Nonetheless, there are +platform-specific ways to create them, and we define LLVM IR's behavior +in their presence. This model is inspired by the C++0x memory model. + +For a more informal introduction to this model, see the :doc:`Atomics`. + +We define a *happens-before* partial order as the least partial order +that + +- Is a superset of single-thread program order, and +- When a *synchronizes-with* ``b``, includes an edge from ``a`` to + ``b``. *Synchronizes-with* pairs are introduced by platform-specific + techniques, like pthread locks, thread creation, thread joining, + etc., and by atomic instructions. (See also :ref:`Atomic Memory Ordering + Constraints `). + +Note that program order does not introduce *happens-before* edges +between a thread and signals executing inside that thread. + +Every (defined) read operation (load instructions, memcpy, atomic +loads/read-modify-writes, etc.) R reads a series of bytes written by +(defined) write operations (store instructions, atomic +stores/read-modify-writes, memcpy, etc.). For the purposes of this +section, initialized globals are considered to have a write of the +initializer which is atomic and happens before any other read or write +of the memory in question. For each byte of a read R, R\ :sub:`byte` +may see any write to the same byte, except: + +- If write\ :sub:`1` happens before write\ :sub:`2`, and + write\ :sub:`2` happens before R\ :sub:`byte`, then + R\ :sub:`byte` does not see write\ :sub:`1`. +- If R\ :sub:`byte` happens before write\ :sub:`3`, then + R\ :sub:`byte` does not see write\ :sub:`3`. + +Given that definition, R\ :sub:`byte` is defined as follows: + +- If R is volatile, the result is target-dependent. (Volatile is + supposed to give guarantees which can support ``sig_atomic_t`` in + C/C++, and may be used for accesses to addresses which do not behave + like normal memory. It does not generally provide cross-thread + synchronization.) +- Otherwise, if there is no write to the same byte that happens before + R\ :sub:`byte`, R\ :sub:`byte` returns ``undef`` for that byte. +- Otherwise, if R\ :sub:`byte` may see exactly one write, + R\ :sub:`byte` returns the value written by that write. +- Otherwise, if R is atomic, and all the writes R\ :sub:`byte` may + see are atomic, it chooses one of the values written. See the :ref:`Atomic + Memory Ordering Constraints ` section for additional + constraints on how the choice is made. +- Otherwise R\ :sub:`byte` returns ``undef``. + +R returns the value composed of the series of bytes it read. This +implies that some bytes within the value may be ``undef`` **without** +the entire value being ``undef``. Note that this only defines the +semantics of the operation; it doesn't mean that targets will emit more +than one instruction to read the series of bytes. + +Note that in cases where none of the atomic intrinsics are used, this +model places only one restriction on IR transformations on top of what +is required for single-threaded execution: introducing a store to a byte +which might not otherwise be stored is not allowed in general. +(Specifically, in the case where another thread might write to and read +from an address, introducing a store can change a load that may see +exactly one write into a load that may see multiple writes.) + +.. _ordering: + +Atomic Memory Ordering Constraints +---------------------------------- + +Atomic instructions (:ref:`cmpxchg `, +:ref:`atomicrmw `, :ref:`fence `, +:ref:`atomic load `, and :ref:`atomic store `) take +an ordering parameter that determines which other atomic instructions on +the same address they *synchronize with*. These semantics are borrowed +from Java and C++0x, but are somewhat more colloquial. If these +descriptions aren't precise enough, check those specs (see spec +references in the :doc:`atomics guide `). +:ref:`fence ` instructions treat these orderings somewhat +differently since they don't take an address. See that instruction's +documentation for details. + +For a simpler introduction to the ordering constraints, see the +:doc:`Atomics`. + +``unordered`` + The set of values that can be read is governed by the happens-before + partial order. A value cannot be read unless some operation wrote + it. This is intended to provide a guarantee strong enough to model + Java's non-volatile shared variables. This ordering cannot be + specified for read-modify-write operations; it is not strong enough + to make them atomic in any interesting way. +``monotonic`` + In addition to the guarantees of ``unordered``, there is a single + total order for modifications by ``monotonic`` operations on each + address. All modification orders must be compatible with the + happens-before order. There is no guarantee that the modification + orders can be combined to a global total order for the whole program + (and this often will not be possible). The read in an atomic + read-modify-write operation (:ref:`cmpxchg ` and + :ref:`atomicrmw `) reads the value in the modification + order immediately before the value it writes. If one atomic read + happens before another atomic read of the same address, the later + read must see the same value or a later value in the address's + modification order. This disallows reordering of ``monotonic`` (or + stronger) operations on the same address. If an address is written + ``monotonic``-ally by one thread, and other threads ``monotonic``-ally + read that address repeatedly, the other threads must eventually see + the write. This corresponds to the C++0x/C1x + ``memory_order_relaxed``. +``acquire`` + In addition to the guarantees of ``monotonic``, a + *synchronizes-with* edge may be formed with a ``release`` operation. + This is intended to model C++'s ``memory_order_acquire``. +``release`` + In addition to the guarantees of ``monotonic``, if this operation + writes a value which is subsequently read by an ``acquire`` + operation, it *synchronizes-with* that operation. (This isn't a + complete description; see the C++0x definition of a release + sequence.) This corresponds to the C++0x/C1x + ``memory_order_release``. +``acq_rel`` (acquire+release) + Acts as both an ``acquire`` and ``release`` operation on its + address. This corresponds to the C++0x/C1x ``memory_order_acq_rel``. +``seq_cst`` (sequentially consistent) + In addition to the guarantees of ``acq_rel`` (``acquire`` for an + operation which only reads, ``release`` for an operation which only + writes), there is a global total order on all + sequentially-consistent operations on all addresses, which is + consistent with the *happens-before* partial order and with the + modification orders of all the affected addresses. Each + sequentially-consistent read sees the last preceding write to the + same address in this global order. This corresponds to the C++0x/C1x + ``memory_order_seq_cst`` and Java volatile. + +.. _singlethread: + +If an atomic operation is marked ``singlethread``, it only *synchronizes +with* or participates in modification and seq\_cst total orderings with +other operations running in the same thread (for example, in signal +handlers). + +.. _fastmath: + +Fast-Math Flags +--------------- + +LLVM IR floating-point binary ops (:ref:`fadd `, +:ref:`fsub `, :ref:`fmul `, :ref:`fdiv `, +:ref:`frem `) have the following flags that can set to enable +otherwise unsafe floating point operations + +``nnan`` + No NaNs - Allow optimizations to assume the arguments and result are not + NaN. Such optimizations are required to retain defined behavior over + NaNs, but the value of the result is undefined. + +``ninf`` + No Infs - Allow optimizations to assume the arguments and result are not + +/-Inf. Such optimizations are required to retain defined behavior over + +/-Inf, but the value of the result is undefined. + +``nsz`` + No Signed Zeros - Allow optimizations to treat the sign of a zero + argument or result as insignificant. + +``arcp`` + Allow Reciprocal - Allow optimizations to use the reciprocal of an + argument rather than perform division. + +``fast`` + Fast - Allow algebraically equivalent transformations that may + dramatically change results in floating point (e.g. reassociate). This + flag implies all the others. + +.. _typesystem: + +Type System +=========== + +The LLVM type system is one of the most important features of the +intermediate representation. Being typed enables a number of +optimizations to be performed on the intermediate representation +directly, without having to do extra analyses on the side before the +transformation. A strong type system makes it easier to read the +generated code and enables novel analyses and transformations that are +not feasible to perform on normal three address code representations. + +.. _typeclassifications: + +Type Classifications +-------------------- + +The types fall into a few useful classifications: + + +.. list-table:: + :header-rows: 1 + + * - Classification + - Types + + * - :ref:`integer ` + - ``i1``, ``i2``, ``i3``, ... ``i8``, ... ``i16``, ... ``i32``, ... + ``i64``, ... + + * - :ref:`floating point ` + - ``half``, ``float``, ``double``, ``x86_fp80``, ``fp128``, + ``ppc_fp128`` + + + * - first class + + .. _t_firstclass: + + - :ref:`integer `, :ref:`floating point `, + :ref:`pointer `, :ref:`vector `, + :ref:`structure `, :ref:`array `, + :ref:`label `, :ref:`metadata `. + + * - :ref:`primitive ` + - :ref:`label `, + :ref:`void `, + :ref:`integer `, + :ref:`floating point `, + :ref:`x86mmx `, + :ref:`metadata `. + + * - :ref:`derived ` + - :ref:`array `, + :ref:`function `, + :ref:`pointer `, + :ref:`structure `, + :ref:`vector `, + :ref:`opaque `. + +The :ref:`first class ` types are perhaps the most important. +Values of these types are the only ones which can be produced by +instructions. + +.. _t_primitive: + +Primitive Types +--------------- + +The primitive types are the fundamental building blocks of the LLVM +system. + +.. _t_integer: + +Integer Type +^^^^^^^^^^^^ + +Overview: +""""""""" + +The integer type is a very simple type that simply specifies an +arbitrary bit width for the integer type desired. Any bit width from 1 +bit to 2\ :sup:`23`\ -1 (about 8 million) can be specified. + +Syntax: +""""""" + +:: + + iN + +The number of bits the integer will occupy is specified by the ``N`` +value. + +Examples: +""""""""" + ++----------------+------------------------------------------------+ +| ``i1`` | a single-bit integer. | ++----------------+------------------------------------------------+ +| ``i32`` | a 32-bit integer. | ++----------------+------------------------------------------------+ +| ``i1942652`` | a really big integer of over 1 million bits. | ++----------------+------------------------------------------------+ + +.. _t_floating: + +Floating Point Types +^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :header-rows: 1 + + * - Type + - Description + + * - ``half`` + - 16-bit floating point value + + * - ``float`` + - 32-bit floating point value + + * - ``double`` + - 64-bit floating point value + + * - ``fp128`` + - 128-bit floating point value (112-bit mantissa) + + * - ``x86_fp80`` + - 80-bit floating point value (X87) + + * - ``ppc_fp128`` + - 128-bit floating point value (two 64-bits) + +.. _t_x86mmx: + +X86mmx Type +^^^^^^^^^^^ + +Overview: +""""""""" + +The x86mmx type represents a value held in an MMX register on an x86 +machine. The operations allowed on it are quite limited: parameters and +return values, load and store, and bitcast. User-specified MMX +instructions are represented as intrinsic or asm calls with arguments +and/or results of this type. There are no arrays, vectors or constants +of this type. + +Syntax: +""""""" + +:: + + x86mmx + +.. _t_void: + +Void Type +^^^^^^^^^ + +Overview: +""""""""" + +The void type does not represent any value and has no size. + +Syntax: +""""""" + +:: + + void + +.. _t_label: + +Label Type +^^^^^^^^^^ + +Overview: +""""""""" + +The label type represents code labels. + +Syntax: +""""""" + +:: + + label + +.. _t_metadata: + +Metadata Type +^^^^^^^^^^^^^ + +Overview: +""""""""" + +The metadata type represents embedded metadata. No derived types may be +created from metadata except for :ref:`function ` arguments. + +Syntax: +""""""" + +:: + + metadata + +.. _t_derived: + +Derived Types +------------- + +The real power in LLVM comes from the derived types in the system. This +is what allows a programmer to represent arrays, functions, pointers, +and other useful types. Each of these types contain one or more element +types which may be a primitive type, or another derived type. For +example, it is possible to have a two dimensional array, using an array +as the element type of another array. + +.. _t_aggregate: + +Aggregate Types +^^^^^^^^^^^^^^^ + +Aggregate Types are a subset of derived types that can contain multiple +member types. :ref:`Arrays ` and :ref:`structs ` are +aggregate types. :ref:`Vectors ` are not considered to be +aggregate types. + +.. _t_array: + +Array Type +^^^^^^^^^^ + +Overview: +""""""""" + +The array type is a very simple derived type that arranges elements +sequentially in memory. The array type requires a size (number of +elements) and an underlying data type. + +Syntax: +""""""" + +:: + + [<# elements> x ] + +The number of elements is a constant integer value; ``elementtype`` may +be any type with a size. + +Examples: +""""""""" + ++------------------+--------------------------------------+ +| ``[40 x i32]`` | Array of 40 32-bit integer values. | ++------------------+--------------------------------------+ +| ``[41 x i32]`` | Array of 41 32-bit integer values. | ++------------------+--------------------------------------+ +| ``[4 x i8]`` | Array of 4 8-bit integer values. | ++------------------+--------------------------------------+ + +Here are some examples of multidimensional arrays: + ++-----------------------------+----------------------------------------------------------+ +| ``[3 x [4 x i32]]`` | 3x4 array of 32-bit integer values. | ++-----------------------------+----------------------------------------------------------+ +| ``[12 x [10 x float]]`` | 12x10 array of single precision floating point values. | ++-----------------------------+----------------------------------------------------------+ +| ``[2 x [3 x [4 x i16]]]`` | 2x3x4 array of 16-bit integer values. | ++-----------------------------+----------------------------------------------------------+ + +There is no restriction on indexing beyond the end of the array implied +by a static type (though there are restrictions on indexing beyond the +bounds of an allocated object in some cases). This means that +single-dimension 'variable sized array' addressing can be implemented in +LLVM with a zero length array type. An implementation of 'pascal style +arrays' in LLVM could use the type "``{ i32, [0 x float]}``", for +example. + +.. _t_function: + +Function Type +^^^^^^^^^^^^^ + +Overview: +""""""""" + +The function type can be thought of as a function signature. It consists of a +return type and a list of formal parameter types. The return type of a function +type is a void type or first class type --- except for :ref:`label ` +and :ref:`metadata ` types. + +Syntax: +""""""" + +:: + + () + +...where '````' is a comma-separated list of type +specifiers. Optionally, the parameter list may include a type ``...``, which +indicates that the function takes a variable number of arguments. Variable +argument functions can access their arguments with the :ref:`variable argument +handling intrinsic ` functions. '````' is any type +except :ref:`label ` and :ref:`metadata `. + +Examples: +""""""""" + ++---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``i32 (i32)`` | function taking an ``i32``, returning an ``i32`` | ++---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``float (i16, i32 *) *`` | :ref:`Pointer ` to a function that takes an ``i16`` and a :ref:`pointer ` to ``i32``, returning ``float``. | ++---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``i32 (i8*, ...)`` | A vararg function that takes at least one :ref:`pointer ` to ``i8`` (char in C), which returns an integer. This is the signature for ``printf`` in LLVM. | ++---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``{i32, i32} (i32)`` | A function taking an ``i32``, returning a :ref:`structure ` containing two ``i32`` values | ++---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +.. _t_struct: + +Structure Type +^^^^^^^^^^^^^^ + +Overview: +""""""""" + +The structure type is used to represent a collection of data members +together in memory. The elements of a structure may be any type that has +a size. + +Structures in memory are accessed using '``load``' and '``store``' by +getting a pointer to a field with the '``getelementptr``' instruction. +Structures in registers are accessed using the '``extractvalue``' and +'``insertvalue``' instructions. + +Structures may optionally be "packed" structures, which indicate that +the alignment of the struct is one byte, and that there is no padding +between the elements. In non-packed structs, padding between field types +is inserted as defined by the DataLayout string in the module, which is +required to match what the underlying code generator expects. + +Structures can either be "literal" or "identified". A literal structure +is defined inline with other types (e.g. ``{i32, i32}*``) whereas +identified types are always defined at the top level with a name. +Literal types are uniqued by their contents and can never be recursive +or opaque since there is no way to write one. Identified types can be +recursive, can be opaqued, and are never uniqued. + +Syntax: +""""""" + +:: + + %T1 = type { } ; Identified normal struct type + %T2 = type <{ }> ; Identified packed struct type + +Examples: +""""""""" + ++------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``{ i32, i32, i32 }`` | A triple of three ``i32`` values | ++------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``{ float, i32 (i32) * }`` | A pair, where the first element is a ``float`` and the second element is a :ref:`pointer ` to a :ref:`function ` that takes an ``i32``, returning an ``i32``. | ++------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``<{ i8, i32 }>`` | A packed struct known to be 5 bytes in size. | ++------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +.. _t_opaque: + +Opaque Structure Types +^^^^^^^^^^^^^^^^^^^^^^ + +Overview: +""""""""" + +Opaque structure types are used to represent named structure types that +do not have a body specified. This corresponds (for example) to the C +notion of a forward declared structure. + +Syntax: +""""""" + +:: + + %X = type opaque + %52 = type opaque + +Examples: +""""""""" + ++--------------+-------------------+ +| ``opaque`` | An opaque type. | ++--------------+-------------------+ + +.. _t_pointer: + +Pointer Type +^^^^^^^^^^^^ + +Overview: +""""""""" + +The pointer type is used to specify memory locations. Pointers are +commonly used to reference objects in memory. + +Pointer types may have an optional address space attribute defining the +numbered address space where the pointed-to object resides. The default +address space is number zero. The semantics of non-zero address spaces +are target-specific. + +Note that LLVM does not permit pointers to void (``void*``) nor does it +permit pointers to labels (``label*``). Use ``i8*`` instead. + +Syntax: +""""""" + +:: + + * + +Examples: +""""""""" + ++-------------------------+--------------------------------------------------------------------------------------------------------------+ +| ``[4 x i32]*`` | A :ref:`pointer ` to :ref:`array ` of four ``i32`` values. | ++-------------------------+--------------------------------------------------------------------------------------------------------------+ +| ``i32 (i32*) *`` | A :ref:`pointer ` to a :ref:`function ` that takes an ``i32*``, returning an ``i32``. | ++-------------------------+--------------------------------------------------------------------------------------------------------------+ +| ``i32 addrspace(5)*`` | A :ref:`pointer ` to an ``i32`` value that resides in address space #5. | ++-------------------------+--------------------------------------------------------------------------------------------------------------+ + +.. _t_vector: + +Vector Type +^^^^^^^^^^^ + +Overview: +""""""""" + +A vector type is a simple derived type that represents a vector of +elements. Vector types are used when multiple primitive data are +operated in parallel using a single instruction (SIMD). A vector type +requires a size (number of elements) and an underlying primitive data +type. Vector types are considered :ref:`first class `. + +Syntax: +""""""" + +:: + + < <# elements> x > + +The number of elements is a constant integer value larger than 0; +elementtype may be any integer or floating point type, or a pointer to +these types. Vectors of size zero are not allowed. + +Examples: +""""""""" + ++-------------------+--------------------------------------------------+ +| ``<4 x i32>`` | Vector of 4 32-bit integer values. | ++-------------------+--------------------------------------------------+ +| ``<8 x float>`` | Vector of 8 32-bit floating-point values. | ++-------------------+--------------------------------------------------+ +| ``<2 x i64>`` | Vector of 2 64-bit integer values. | ++-------------------+--------------------------------------------------+ +| ``<4 x i64*>`` | Vector of 4 pointers to 64-bit integer values. | ++-------------------+--------------------------------------------------+ + +Constants +========= + +LLVM has several different basic types of constants. This section +describes them all and their syntax. + +Simple Constants +---------------- + +**Boolean constants** + The two strings '``true``' and '``false``' are both valid constants + of the ``i1`` type. +**Integer constants** + Standard integers (such as '4') are constants of the + :ref:`integer ` type. Negative numbers may be used with + integer types. +**Floating point constants** + Floating point constants use standard decimal notation (e.g. + 123.421), exponential notation (e.g. 1.23421e+2), or a more precise + hexadecimal notation (see below). The assembler requires the exact + decimal value of a floating-point constant. For example, the + assembler accepts 1.25 but rejects 1.3 because 1.3 is a repeating + decimal in binary. Floating point constants must have a :ref:`floating + point ` type. +**Null pointer constants** + The identifier '``null``' is recognized as a null pointer constant + and must be of :ref:`pointer type `. + +The one non-intuitive notation for constants is the hexadecimal form of +floating point constants. For example, the form +'``double 0x432ff973cafa8000``' is equivalent to (but harder to read +than) '``double 4.5e+15``'. The only time hexadecimal floating point +constants are required (and the only time that they are generated by the +disassembler) is when a floating point constant must be emitted but it +cannot be represented as a decimal floating point number in a reasonable +number of digits. For example, NaN's, infinities, and other special +values are represented in their IEEE hexadecimal format so that assembly +and disassembly do not cause any bits to change in the constants. + +When using the hexadecimal form, constants of types half, float, and +double are represented using the 16-digit form shown above (which +matches the IEEE754 representation for double); half and float values +must, however, be exactly representable as IEEE 754 half and single +precision, respectively. Hexadecimal format is always used for long +double, and there are three forms of long double. The 80-bit format used +by x86 is represented as ``0xK`` followed by 20 hexadecimal digits. The +128-bit format used by PowerPC (two adjacent doubles) is represented by +``0xM`` followed by 32 hexadecimal digits. The IEEE 128-bit format is +represented by ``0xL`` followed by 32 hexadecimal digits. Long doubles +will only work if they match the long double format on your target. +The IEEE 16-bit format (half precision) is represented by ``0xH`` +followed by 4 hexadecimal digits. All hexadecimal formats are big-endian +(sign bit at the left). + +There are no constants of type x86mmx. + +.. _complexconstants: + +Complex Constants +----------------- + +Complex constants are a (potentially recursive) combination of simple +constants and smaller complex constants. + +**Structure constants** + Structure constants are represented with notation similar to + structure type definitions (a comma separated list of elements, + surrounded by braces (``{}``)). For example: + "``{ i32 4, float 17.0, i32* @G }``", where "``@G``" is declared as + "``@G = external global i32``". Structure constants must have + :ref:`structure type `, and the number and types of elements + must match those specified by the type. +**Array constants** + Array constants are represented with notation similar to array type + definitions (a comma separated list of elements, surrounded by + square brackets (``[]``)). For example: + "``[ i32 42, i32 11, i32 74 ]``". Array constants must have + :ref:`array type `, and the number and types of elements must + match those specified by the type. +**Vector constants** + Vector constants are represented with notation similar to vector + type definitions (a comma separated list of elements, surrounded by + less-than/greater-than's (``<>``)). For example: + "``< i32 42, i32 11, i32 74, i32 100 >``". Vector constants + must have :ref:`vector type `, and the number and types of + elements must match those specified by the type. +**Zero initialization** + The string '``zeroinitializer``' can be used to zero initialize a + value to zero of *any* type, including scalar and + :ref:`aggregate ` types. This is often used to avoid + having to print large zero initializers (e.g. for large arrays) and + is always exactly equivalent to using explicit zero initializers. +**Metadata node** + A metadata node is a structure-like constant with :ref:`metadata + type `. For example: + "``metadata !{ i32 0, metadata !"test" }``". Unlike other + constants that are meant to be interpreted as part of the + instruction stream, metadata is a place to attach additional + information such as debug info. + +Global Variable and Function Addresses +-------------------------------------- + +The addresses of :ref:`global variables ` and +:ref:`functions ` are always implicitly valid +(link-time) constants. These constants are explicitly referenced when +the :ref:`identifier for the global ` is used and always have +:ref:`pointer ` type. For example, the following is a legal LLVM +file: + +.. code-block:: llvm + + @X = global i32 17 + @Y = global i32 42 + @Z = global [2 x i32*] [ i32* @X, i32* @Y ] + +.. _undefvalues: + +Undefined Values +---------------- + +The string '``undef``' can be used anywhere a constant is expected, and +indicates that the user of the value may receive an unspecified +bit-pattern. Undefined values may be of any type (other than '``label``' +or '``void``') and be used anywhere a constant is permitted. + +Undefined values are useful because they indicate to the compiler that +the program is well defined no matter what value is used. This gives the +compiler more freedom to optimize. Here are some examples of +(potentially surprising) transformations that are valid (in pseudo IR): + +.. code-block:: llvm + + %A = add %X, undef + %B = sub %X, undef + %C = xor %X, undef + Safe: + %A = undef + %B = undef + %C = undef + +This is safe because all of the output bits are affected by the undef +bits. Any output bit can have a zero or one depending on the input bits. + +.. code-block:: llvm + + %A = or %X, undef + %B = and %X, undef + Safe: + %A = -1 + %B = 0 + Unsafe: + %A = undef + %B = undef + +These logical operations have bits that are not always affected by the +input. For example, if ``%X`` has a zero bit, then the output of the +'``and``' operation will always be a zero for that bit, no matter what +the corresponding bit from the '``undef``' is. As such, it is unsafe to +optimize or assume that the result of the '``and``' is '``undef``'. +However, it is safe to assume that all bits of the '``undef``' could be +0, and optimize the '``and``' to 0. Likewise, it is safe to assume that +all the bits of the '``undef``' operand to the '``or``' could be set, +allowing the '``or``' to be folded to -1. + +.. code-block:: llvm + + %A = select undef, %X, %Y + %B = select undef, 42, %Y + %C = select %X, %Y, undef + Safe: + %A = %X (or %Y) + %B = 42 (or %Y) + %C = %Y + Unsafe: + %A = undef + %B = undef + %C = undef + +This set of examples shows that undefined '``select``' (and conditional +branch) conditions can go *either way*, but they have to come from one +of the two operands. In the ``%A`` example, if ``%X`` and ``%Y`` were +both known to have a clear low bit, then ``%A`` would have to have a +cleared low bit. However, in the ``%C`` example, the optimizer is +allowed to assume that the '``undef``' operand could be the same as +``%Y``, allowing the whole '``select``' to be eliminated. + +.. code-block:: llvm + + %A = xor undef, undef + + %B = undef + %C = xor %B, %B + + %D = undef + %E = icmp lt %D, 4 + %F = icmp gte %D, 4 + + Safe: + %A = undef + %B = undef + %C = undef + %D = undef + %E = undef + %F = undef + +This example points out that two '``undef``' operands are not +necessarily the same. This can be surprising to people (and also matches +C semantics) where they assume that "``X^X``" is always zero, even if +``X`` is undefined. This isn't true for a number of reasons, but the +short answer is that an '``undef``' "variable" can arbitrarily change +its value over its "live range". This is true because the variable +doesn't actually *have a live range*. Instead, the value is logically +read from arbitrary registers that happen to be around when needed, so +the value is not necessarily consistent over time. In fact, ``%A`` and +``%C`` need to have the same semantics or the core LLVM "replace all +uses with" concept would not hold. + +.. code-block:: llvm + + %A = fdiv undef, %X + %B = fdiv %X, undef + Safe: + %A = undef + b: unreachable + +These examples show the crucial difference between an *undefined value* +and *undefined behavior*. An undefined value (like '``undef``') is +allowed to have an arbitrary bit-pattern. This means that the ``%A`` +operation can be constant folded to '``undef``', because the '``undef``' +could be an SNaN, and ``fdiv`` is not (currently) defined on SNaN's. +However, in the second example, we can make a more aggressive +assumption: because the ``undef`` is allowed to be an arbitrary value, +we are allowed to assume that it could be zero. Since a divide by zero +has *undefined behavior*, we are allowed to assume that the operation +does not execute at all. This allows us to delete the divide and all +code after it. Because the undefined operation "can't happen", the +optimizer can assume that it occurs in dead code. + +.. code-block:: llvm + + a: store undef -> %X + b: store %X -> undef + Safe: + a: + b: unreachable + +These examples reiterate the ``fdiv`` example: a store *of* an undefined +value can be assumed to not have any effect; we can assume that the +value is overwritten with bits that happen to match what was already +there. However, a store *to* an undefined location could clobber +arbitrary memory, therefore, it has undefined behavior. + +.. _poisonvalues: + +Poison Values +------------- + +Poison values are similar to :ref:`undef values `, however +they also represent the fact that an instruction or constant expression +which cannot evoke side effects has nevertheless detected a condition +which results in undefined behavior. + +There is currently no way of representing a poison value in the IR; they +only exist when produced by operations such as :ref:`add ` with +the ``nsw`` flag. + +Poison value behavior is defined in terms of value *dependence*: + +- Values other than :ref:`phi ` nodes depend on their operands. +- :ref:`Phi ` nodes depend on the operand corresponding to + their dynamic predecessor basic block. +- Function arguments depend on the corresponding actual argument values + in the dynamic callers of their functions. +- :ref:`Call ` instructions depend on the :ref:`ret ` + instructions that dynamically transfer control back to them. +- :ref:`Invoke ` instructions depend on the + :ref:`ret `, :ref:`resume `, or exception-throwing + call instructions that dynamically transfer control back to them. +- Non-volatile loads and stores depend on the most recent stores to all + of the referenced memory addresses, following the order in the IR + (including loads and stores implied by intrinsics such as + :ref:`@llvm.memcpy `.) +- An instruction with externally visible side effects depends on the + most recent preceding instruction with externally visible side + effects, following the order in the IR. (This includes :ref:`volatile + operations `.) +- An instruction *control-depends* on a :ref:`terminator + instruction ` if the terminator instruction has + multiple successors and the instruction is always executed when + control transfers to one of the successors, and may not be executed + when control is transferred to another. +- Additionally, an instruction also *control-depends* on a terminator + instruction if the set of instructions it otherwise depends on would + be different if the terminator had transferred control to a different + successor. +- Dependence is transitive. + +Poison Values have the same behavior as :ref:`undef values `, +with the additional affect that any instruction which has a *dependence* +on a poison value has undefined behavior. + +Here are some examples: + +.. code-block:: llvm + + entry: + %poison = sub nuw i32 0, 1 ; Results in a poison value. + %still_poison = and i32 %poison, 0 ; 0, but also poison. + %poison_yet_again = getelementptr i32* @h, i32 %still_poison + store i32 0, i32* %poison_yet_again ; memory at @h[0] is poisoned + + store i32 %poison, i32* @g ; Poison value stored to memory. + %poison2 = load i32* @g ; Poison value loaded back from memory. + + store volatile i32 %poison, i32* @g ; External observation; undefined behavior. + + %narrowaddr = bitcast i32* @g to i16* + %wideaddr = bitcast i32* @g to i64* + %poison3 = load i16* %narrowaddr ; Returns a poison value. + %poison4 = load i64* %wideaddr ; Returns a poison value. + + %cmp = icmp slt i32 %poison, 0 ; Returns a poison value. + br i1 %cmp, label %true, label %end ; Branch to either destination. + + true: + store volatile i32 0, i32* @g ; This is control-dependent on %cmp, so + ; it has undefined behavior. + br label %end + + end: + %p = phi i32 [ 0, %entry ], [ 1, %true ] + ; Both edges into this PHI are + ; control-dependent on %cmp, so this + ; always results in a poison value. + + store volatile i32 0, i32* @g ; This would depend on the store in %true + ; if %cmp is true, or the store in %entry + ; otherwise, so this is undefined behavior. + + br i1 %cmp, label %second_true, label %second_end + ; The same branch again, but this time the + ; true block doesn't have side effects. + + second_true: + ; No side effects! + ret void + + second_end: + store volatile i32 0, i32* @g ; This time, the instruction always depends + ; on the store in %end. Also, it is + ; control-equivalent to %end, so this is + ; well-defined (ignoring earlier undefined + ; behavior in this example). + +.. _blockaddress: + +Addresses of Basic Blocks +------------------------- + +``blockaddress(@function, %block)`` + +The '``blockaddress``' constant computes the address of the specified +basic block in the specified function, and always has an ``i8*`` type. +Taking the address of the entry block is illegal. + +This value only has defined behavior when used as an operand to the +':ref:`indirectbr `' instruction, or for comparisons +against null. Pointer equality tests between labels addresses results in +undefined behavior --- though, again, comparison against null is ok, and +no label is equal to the null pointer. This may be passed around as an +opaque pointer sized value as long as the bits are not inspected. This +allows ``ptrtoint`` and arithmetic to be performed on these values so +long as the original value is reconstituted before the ``indirectbr`` +instruction. + +Finally, some targets may provide defined semantics when using the value +as the operand to an inline assembly, but that is target specific. + +.. _constantexprs: + +Constant Expressions +-------------------- + +Constant expressions are used to allow expressions involving other +constants to be used as constants. Constant expressions may be of any +:ref:`first class ` type and may involve any LLVM operation +that does not have side effects (e.g. load and call are not supported). +The following is the syntax for constant expressions: + +``trunc (CST to TYPE)`` + Truncate a constant to another type. The bit size of CST must be + larger than the bit size of TYPE. Both types must be integers. +``zext (CST to TYPE)`` + Zero extend a constant to another type. The bit size of CST must be + smaller than the bit size of TYPE. Both types must be integers. +``sext (CST to TYPE)`` + Sign extend a constant to another type. The bit size of CST must be + smaller than the bit size of TYPE. Both types must be integers. +``fptrunc (CST to TYPE)`` + Truncate a floating point constant to another floating point type. + The size of CST must be larger than the size of TYPE. Both types + must be floating point. +``fpext (CST to TYPE)`` + Floating point extend a constant to another type. The size of CST + must be smaller or equal to the size of TYPE. Both types must be + floating point. +``fptoui (CST to TYPE)`` + Convert a floating point constant to the corresponding unsigned + integer constant. TYPE must be a scalar or vector integer type. CST + must be of scalar or vector floating point type. Both CST and TYPE + must be scalars, or vectors of the same number of elements. If the + value won't fit in the integer type, the results are undefined. +``fptosi (CST to TYPE)`` + Convert a floating point constant to the corresponding signed + integer constant. TYPE must be a scalar or vector integer type. CST + must be of scalar or vector floating point type. Both CST and TYPE + must be scalars, or vectors of the same number of elements. If the + value won't fit in the integer type, the results are undefined. +``uitofp (CST to TYPE)`` + Convert an unsigned integer constant to the corresponding floating + point constant. TYPE must be a scalar or vector floating point type. + CST must be of scalar or vector integer type. Both CST and TYPE must + be scalars, or vectors of the same number of elements. If the value + won't fit in the floating point type, the results are undefined. +``sitofp (CST to TYPE)`` + Convert a signed integer constant to the corresponding floating + point constant. TYPE must be a scalar or vector floating point type. + CST must be of scalar or vector integer type. Both CST and TYPE must + be scalars, or vectors of the same number of elements. If the value + won't fit in the floating point type, the results are undefined. +``ptrtoint (CST to TYPE)`` + Convert a pointer typed constant to the corresponding integer + constant. ``TYPE`` must be an integer type. ``CST`` must be of + pointer type. The ``CST`` value is zero extended, truncated, or + unchanged to make it fit in ``TYPE``. +``inttoptr (CST to TYPE)`` + Convert an integer constant to a pointer constant. TYPE must be a + pointer type. CST must be of integer type. The CST value is zero + extended, truncated, or unchanged to make it fit in a pointer size. + This one is *really* dangerous! +``bitcast (CST to TYPE)`` + Convert a constant, CST, to another TYPE. The constraints of the + operands are the same as those for the :ref:`bitcast + instruction `. +``addrspacecast (CST to TYPE)`` + Convert a constant pointer or constant vector of pointer, CST, to another + TYPE in a different address space. The constraints of the operands are the + same as those for the :ref:`addrspacecast instruction `. +``getelementptr (CSTPTR, IDX0, IDX1, ...)``, ``getelementptr inbounds (CSTPTR, IDX0, IDX1, ...)`` + Perform the :ref:`getelementptr operation ` on + constants. As with the :ref:`getelementptr ` + instruction, the index list may have zero or more indexes, which are + required to make sense for the type of "CSTPTR". +``select (COND, VAL1, VAL2)`` + Perform the :ref:`select operation ` on constants. +``icmp COND (VAL1, VAL2)`` + Performs the :ref:`icmp operation ` on constants. +``fcmp COND (VAL1, VAL2)`` + Performs the :ref:`fcmp operation ` on constants. +``extractelement (VAL, IDX)`` + Perform the :ref:`extractelement operation ` on + constants. +``insertelement (VAL, ELT, IDX)`` + Perform the :ref:`insertelement operation ` on + constants. +``shufflevector (VEC1, VEC2, IDXMASK)`` + Perform the :ref:`shufflevector operation ` on + constants. +``extractvalue (VAL, IDX0, IDX1, ...)`` + Perform the :ref:`extractvalue operation ` on + constants. The index list is interpreted in a similar manner as + indices in a ':ref:`getelementptr `' operation. At + least one index value must be specified. +``insertvalue (VAL, ELT, IDX0, IDX1, ...)`` + Perform the :ref:`insertvalue operation ` on constants. + The index list is interpreted in a similar manner as indices in a + ':ref:`getelementptr `' operation. At least one index + value must be specified. +``OPCODE (LHS, RHS)`` + Perform the specified operation of the LHS and RHS constants. OPCODE + may be any of the :ref:`binary ` or :ref:`bitwise + binary ` operations. The constraints on operands are + the same as those for the corresponding instruction (e.g. no bitwise + operations on floating point values are allowed). + +Other Values +============ + +.. _inlineasmexprs: + +Inline Assembler Expressions +---------------------------- + +LLVM supports inline assembler expressions (as opposed to :ref:`Module-Level +Inline Assembly `) through the use of a special value. This +value represents the inline assembler as a string (containing the +instructions to emit), a list of operand constraints (stored as a +string), a flag that indicates whether or not the inline asm expression +has side effects, and a flag indicating whether the function containing +the asm needs to align its stack conservatively. An example inline +assembler expression is: + +.. code-block:: llvm + + i32 (i32) asm "bswap $0", "=r,r" + +Inline assembler expressions may **only** be used as the callee operand +of a :ref:`call ` or an :ref:`invoke ` instruction. +Thus, typically we have: + +.. code-block:: llvm + + %X = call i32 asm "bswap $0", "=r,r"(i32 %Y) + +Inline asms with side effects not visible in the constraint list must be +marked as having side effects. This is done through the use of the +'``sideeffect``' keyword, like so: + +.. code-block:: llvm + + call void asm sideeffect "eieio", ""() + +In some cases inline asms will contain code that will not work unless +the stack is aligned in some way, such as calls or SSE instructions on +x86, yet will not contain code that does that alignment within the asm. +The compiler should make conservative assumptions about what the asm +might contain and should generate its usual stack alignment code in the +prologue if the '``alignstack``' keyword is present: + +.. code-block:: llvm + + call void asm alignstack "eieio", ""() + +Inline asms also support using non-standard assembly dialects. The +assumed dialect is ATT. When the '``inteldialect``' keyword is present, +the inline asm is using the Intel dialect. Currently, ATT and Intel are +the only supported dialects. An example is: + +.. code-block:: llvm + + call void asm inteldialect "eieio", ""() + +If multiple keywords appear the '``sideeffect``' keyword must come +first, the '``alignstack``' keyword second and the '``inteldialect``' +keyword last. + +Inline Asm Metadata +^^^^^^^^^^^^^^^^^^^ + +The call instructions that wrap inline asm nodes may have a +"``!srcloc``" MDNode attached to it that contains a list of constant +integers. If present, the code generator will use the integer as the +location cookie value when report errors through the ``LLVMContext`` +error reporting mechanisms. This allows a front-end to correlate backend +errors that occur with inline asm back to the source code that produced +it. For example: + +.. code-block:: llvm + + call void asm sideeffect "something bad", ""(), !srcloc !42 + ... + !42 = !{ i32 1234567 } + +It is up to the front-end to make sense of the magic numbers it places +in the IR. If the MDNode contains multiple constants, the code generator +will use the one that corresponds to the line of the asm that the error +occurs on. + +.. _metadata: + +Metadata Nodes and Metadata Strings +----------------------------------- + +LLVM IR allows metadata to be attached to instructions in the program +that can convey extra information about the code to the optimizers and +code generator. One example application of metadata is source-level +debug information. There are two metadata primitives: strings and nodes. +All metadata has the ``metadata`` type and is identified in syntax by a +preceding exclamation point ('``!``'). + +A metadata string is a string surrounded by double quotes. It can +contain any character by escaping non-printable characters with +"``\xx``" where "``xx``" is the two digit hex code. For example: +"``!"test\00"``". + +Metadata nodes are represented with notation similar to structure +constants (a comma separated list of elements, surrounded by braces and +preceded by an exclamation point). Metadata nodes can have any values as +their operand. For example: + +.. code-block:: llvm + + !{ metadata !"test\00", i32 10} + +A :ref:`named metadata ` is a collection of +metadata nodes, which can be looked up in the module symbol table. For +example: + +.. code-block:: llvm + + !foo = metadata !{!4, !3} + +Metadata can be used as function arguments. Here ``llvm.dbg.value`` +function is using two metadata arguments: + +.. code-block:: llvm + + call void @llvm.dbg.value(metadata !24, i64 0, metadata !25) + +Metadata can be attached with an instruction. Here metadata ``!21`` is +attached to the ``add`` instruction using the ``!dbg`` identifier: + +.. code-block:: llvm + + %indvar.next = add i64 %indvar, 1, !dbg !21 + +More information about specific metadata nodes recognized by the +optimizers and code generator is found below. + +'``tbaa``' Metadata +^^^^^^^^^^^^^^^^^^^ + +In LLVM IR, memory does not have types, so LLVM's own type system is not +suitable for doing TBAA. Instead, metadata is added to the IR to +describe a type system of a higher level language. This can be used to +implement typical C/C++ TBAA, but it can also be used to implement +custom alias analysis behavior for other languages. + +The current metadata format is very simple. TBAA metadata nodes have up +to three fields, e.g.: + +.. code-block:: llvm + + !0 = metadata !{ metadata !"an example type tree" } + !1 = metadata !{ metadata !"int", metadata !0 } + !2 = metadata !{ metadata !"float", metadata !0 } + !3 = metadata !{ metadata !"const float", metadata !2, i64 1 } + +The first field is an identity field. It can be any value, usually a +metadata string, which uniquely identifies the type. The most important +name in the tree is the name of the root node. Two trees with different +root node names are entirely disjoint, even if they have leaves with +common names. + +The second field identifies the type's parent node in the tree, or is +null or omitted for a root node. A type is considered to alias all of +its descendants and all of its ancestors in the tree. Also, a type is +considered to alias all types in other trees, so that bitcode produced +from multiple front-ends is handled conservatively. + +If the third field is present, it's an integer which if equal to 1 +indicates that the type is "constant" (meaning +``pointsToConstantMemory`` should return true; see `other useful +AliasAnalysis methods `_). + +'``tbaa.struct``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :ref:`llvm.memcpy ` is often used to implement +aggregate assignment operations in C and similar languages, however it +is defined to copy a contiguous region of memory, which is more than +strictly necessary for aggregate types which contain holes due to +padding. Also, it doesn't contain any TBAA information about the fields +of the aggregate. + +``!tbaa.struct`` metadata can describe which memory subregions in a +memcpy are padding and what the TBAA tags of the struct are. + +The current metadata format is very simple. ``!tbaa.struct`` metadata +nodes are a list of operands which are in conceptual groups of three. +For each group of three, the first operand gives the byte offset of a +field in bytes, the second gives its size in bytes, and the third gives +its tbaa tag. e.g.: + +.. code-block:: llvm + + !4 = metadata !{ i64 0, i64 4, metadata !1, i64 8, i64 4, metadata !2 } + +This describes a struct with two fields. The first is at offset 0 bytes +with size 4 bytes, and has tbaa tag !1. The second is at offset 8 bytes +and has size 4 bytes and has tbaa tag !2. + +Note that the fields need not be contiguous. In this example, there is a +4 byte gap between the two fields. This gap represents padding which +does not carry useful data and need not be preserved. + +'``fpmath``' Metadata +^^^^^^^^^^^^^^^^^^^^^ + +``fpmath`` metadata may be attached to any instruction of floating point +type. It can be used to express the maximum acceptable error in the +result of that instruction, in ULPs, thus potentially allowing the +compiler to use a more efficient but less accurate method of computing +it. ULP is defined as follows: + + If ``x`` is a real number that lies between two finite consecutive + floating-point numbers ``a`` and ``b``, without being equal to one + of them, then ``ulp(x) = |b - a|``, otherwise ``ulp(x)`` is the + distance between the two non-equal finite floating-point numbers + nearest ``x``. Moreover, ``ulp(NaN)`` is ``NaN``. + +The metadata node shall consist of a single positive floating point +number representing the maximum relative error, for example: + +.. code-block:: llvm + + !0 = metadata !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs + +'``range``' Metadata +^^^^^^^^^^^^^^^^^^^^ + +``range`` metadata may be attached only to loads of integer types. It +expresses the possible ranges the loaded value is in. The ranges are +represented with a flattened list of integers. The loaded value is known +to be in the union of the ranges defined by each consecutive pair. Each +pair has the following properties: + +- The type must match the type loaded by the instruction. +- The pair ``a,b`` represents the range ``[a,b)``. +- Both ``a`` and ``b`` are constants. +- The range is allowed to wrap. +- The range should not represent the full or empty set. That is, + ``a!=b``. + +In addition, the pairs must be in signed order of the lower bound and +they must be non-contiguous. + +Examples: + +.. code-block:: llvm + + %a = load i8* %x, align 1, !range !0 ; Can only be 0 or 1 + %b = load i8* %y, align 1, !range !1 ; Can only be 255 (-1), 0 or 1 + %c = load i8* %z, align 1, !range !2 ; Can only be 0, 1, 3, 4 or 5 + %d = load i8* %z, align 1, !range !3 ; Can only be -2, -1, 3, 4 or 5 + ... + !0 = metadata !{ i8 0, i8 2 } + !1 = metadata !{ i8 255, i8 2 } + !2 = metadata !{ i8 0, i8 2, i8 3, i8 6 } + !3 = metadata !{ i8 -2, i8 0, i8 3, i8 6 } + +'``llvm.loop``' +^^^^^^^^^^^^^^^ + +It is sometimes useful to attach information to loop constructs. Currently, +loop metadata is implemented as metadata attached to the branch instruction +in the loop latch block. This type of metadata refer to a metadata node that is +guaranteed to be separate for each loop. The loop identifier metadata is +specified with the name ``llvm.loop``. + +The loop identifier metadata is implemented using a metadata that refers to +itself to avoid merging it with any other identifier metadata, e.g., +during module linkage or function inlining. That is, each loop should refer +to their own identification metadata even if they reside in separate functions. +The following example contains loop identifier metadata for two separate loop +constructs: + +.. code-block:: llvm + + !0 = metadata !{ metadata !0 } + !1 = metadata !{ metadata !1 } + +The loop identifier metadata can be used to specify additional per-loop +metadata. Any operands after the first operand can be treated as user-defined +metadata. For example the ``llvm.vectorizer.unroll`` metadata is understood +by the loop vectorizer to indicate how many times to unroll the loop: + +.. code-block:: llvm + + br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !0 + ... + !0 = metadata !{ metadata !0, metadata !1 } + !1 = metadata !{ metadata !"llvm.vectorizer.unroll", i32 2 } + +'``llvm.mem``' +^^^^^^^^^^^^^^^ + +Metadata types used to annotate memory accesses with information helpful +for optimizations are prefixed with ``llvm.mem``. + +'``llvm.mem.parallel_loop_access``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For a loop to be parallel, in addition to using +the ``llvm.loop`` metadata to mark the loop latch branch instruction, +also all of the memory accessing instructions in the loop body need to be +marked with the ``llvm.mem.parallel_loop_access`` metadata. If there +is at least one memory accessing instruction not marked with the metadata, +the loop must be considered a sequential loop. This causes parallel loops to be +converted to sequential loops due to optimization passes that are unaware of +the parallel semantics and that insert new memory instructions to the loop +body. + +Example of a loop that is considered parallel due to its correct use of +both ``llvm.loop`` and ``llvm.mem.parallel_loop_access`` +metadata types that refer to the same loop identifier metadata. + +.. code-block:: llvm + + for.body: + ... + %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 + ... + store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 + ... + br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0 + + for.end: + ... + !0 = metadata !{ metadata !0 } + +It is also possible to have nested parallel loops. In that case the +memory accesses refer to a list of loop identifier metadata nodes instead of +the loop identifier metadata node directly: + +.. code-block:: llvm + + outer.for.body: + ... + + inner.for.body: + ... + %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 + ... + store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 + ... + br i1 %exitcond, label %inner.for.end, label %inner.for.body, !llvm.loop !1 + + inner.for.end: + ... + %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 + ... + store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 + ... + br i1 %exitcond, label %outer.for.end, label %outer.for.body, !llvm.loop !2 + + outer.for.end: ; preds = %for.body + ... + !0 = metadata !{ metadata !1, metadata !2 } ; a list of loop identifiers + !1 = metadata !{ metadata !1 } ; an identifier for the inner loop + !2 = metadata !{ metadata !2 } ; an identifier for the outer loop + +'``llvm.vectorizer``' +^^^^^^^^^^^^^^^^^^^^^ + +Metadata prefixed with ``llvm.vectorizer`` is used to control per-loop +vectorization parameters such as vectorization factor and unroll factor. + +``llvm.vectorizer`` metadata should be used in conjunction with ``llvm.loop`` +loop identification metadata. + +'``llvm.vectorizer.unroll``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This metadata instructs the loop vectorizer to unroll the specified +loop exactly ``N`` times. + +The first operand is the string ``llvm.vectorizer.unroll`` and the second +operand is an integer specifying the unroll factor. For example: + +.. code-block:: llvm + + !0 = metadata !{ metadata !"llvm.vectorizer.unroll", i32 4 } + +Note that setting ``llvm.vectorizer.unroll`` to 1 disables unrolling of the +loop. + +If ``llvm.vectorizer.unroll`` is set to 0 then the amount of unrolling will be +determined automatically. + +'``llvm.vectorizer.width``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This metadata sets the target width of the vectorizer to ``N``. Without +this metadata, the vectorizer will choose a width automatically. +Regardless of this metadata, the vectorizer will only vectorize loops if +it believes it is valid to do so. + +The first operand is the string ``llvm.vectorizer.width`` and the second +operand is an integer specifying the width. For example: + +.. code-block:: llvm + + !0 = metadata !{ metadata !"llvm.vectorizer.width", i32 4 } + +Note that setting ``llvm.vectorizer.width`` to 1 disables vectorization of the +loop. + +If ``llvm.vectorizer.width`` is set to 0 then the width will be determined +automatically. + +Module Flags Metadata +===================== + +Information about the module as a whole is difficult to convey to LLVM's +subsystems. The LLVM IR isn't sufficient to transmit this information. +The ``llvm.module.flags`` named metadata exists in order to facilitate +this. These flags are in the form of key / value pairs --- much like a +dictionary --- making it easy for any subsystem who cares about a flag to +look it up. + +The ``llvm.module.flags`` metadata contains a list of metadata triplets. +Each triplet has the following form: + +- The first element is a *behavior* flag, which specifies the behavior + when two (or more) modules are merged together, and it encounters two + (or more) metadata with the same ID. The supported behaviors are + described below. +- The second element is a metadata string that is a unique ID for the + metadata. Each module may only have one flag entry for each unique ID (not + including entries with the **Require** behavior). +- The third element is the value of the flag. + +When two (or more) modules are merged together, the resulting +``llvm.module.flags`` metadata is the union of the modules' flags. That is, for +each unique metadata ID string, there will be exactly one entry in the merged +modules ``llvm.module.flags`` metadata table, and the value for that entry will +be determined by the merge behavior flag, as described below. The only exception +is that entries with the *Require* behavior are always preserved. + +The following behaviors are supported: + +.. list-table:: + :header-rows: 1 + :widths: 10 90 + + * - Value + - Behavior + + * - 1 + - **Error** + Emits an error if two values disagree, otherwise the resulting value + is that of the operands. + + * - 2 + - **Warning** + Emits a warning if two values disagree. The result value will be the + operand for the flag from the first module being linked. + + * - 3 + - **Require** + Adds a requirement that another module flag be present and have a + specified value after linking is performed. The value must be a + metadata pair, where the first element of the pair is the ID of the + module flag to be restricted, and the second element of the pair is + the value the module flag should be restricted to. This behavior can + be used to restrict the allowable results (via triggering of an + error) of linking IDs with the **Override** behavior. + + * - 4 + - **Override** + Uses the specified value, regardless of the behavior or value of the + other module. If both modules specify **Override**, but the values + differ, an error will be emitted. + + * - 5 + - **Append** + Appends the two values, which are required to be metadata nodes. + + * - 6 + - **AppendUnique** + Appends the two values, which are required to be metadata + nodes. However, duplicate entries in the second list are dropped + during the append operation. + +It is an error for a particular unique flag ID to have multiple behaviors, +except in the case of **Require** (which adds restrictions on another metadata +value) or **Override**. + +An example of module flags: + +.. code-block:: llvm + + !0 = metadata !{ i32 1, metadata !"foo", i32 1 } + !1 = metadata !{ i32 4, metadata !"bar", i32 37 } + !2 = metadata !{ i32 2, metadata !"qux", i32 42 } + !3 = metadata !{ i32 3, metadata !"qux", + metadata !{ + metadata !"foo", i32 1 + } + } + !llvm.module.flags = !{ !0, !1, !2, !3 } + +- Metadata ``!0`` has the ID ``!"foo"`` and the value '1'. The behavior + if two or more ``!"foo"`` flags are seen is to emit an error if their + values are not equal. + +- Metadata ``!1`` has the ID ``!"bar"`` and the value '37'. The + behavior if two or more ``!"bar"`` flags are seen is to use the value + '37'. + +- Metadata ``!2`` has the ID ``!"qux"`` and the value '42'. The + behavior if two or more ``!"qux"`` flags are seen is to emit a + warning if their values are not equal. + +- Metadata ``!3`` has the ID ``!"qux"`` and the value: + + :: + + metadata !{ metadata !"foo", i32 1 } + + The behavior is to emit an error if the ``llvm.module.flags`` does not + contain a flag with the ID ``!"foo"`` that has the value '1' after linking is + performed. + +Objective-C Garbage Collection Module Flags Metadata +---------------------------------------------------- + +On the Mach-O platform, Objective-C stores metadata about garbage +collection in a special section called "image info". The metadata +consists of a version number and a bitmask specifying what types of +garbage collection are supported (if any) by the file. If two or more +modules are linked together their garbage collection metadata needs to +be merged rather than appended together. + +The Objective-C garbage collection module flags metadata consists of the +following key-value pairs: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Key + - Value + + * - ``Objective-C Version`` + - **[Required]** --- The Objective-C ABI version. Valid values are 1 and 2. + + * - ``Objective-C Image Info Version`` + - **[Required]** --- The version of the image info section. Currently + always 0. + + * - ``Objective-C Image Info Section`` + - **[Required]** --- The section to place the metadata. Valid values are + ``"__OBJC, __image_info, regular"`` for Objective-C ABI version 1, and + ``"__DATA,__objc_imageinfo, regular, no_dead_strip"`` for + Objective-C ABI version 2. + + * - ``Objective-C Garbage Collection`` + - **[Required]** --- Specifies whether garbage collection is supported or + not. Valid values are 0, for no garbage collection, and 2, for garbage + collection supported. + + * - ``Objective-C GC Only`` + - **[Optional]** --- Specifies that only garbage collection is supported. + If present, its value must be 6. This flag requires that the + ``Objective-C Garbage Collection`` flag have the value 2. + +Some important flag interactions: + +- If a module with ``Objective-C Garbage Collection`` set to 0 is + merged with a module with ``Objective-C Garbage Collection`` set to + 2, then the resulting module has the + ``Objective-C Garbage Collection`` flag set to 0. +- A module with ``Objective-C Garbage Collection`` set to 0 cannot be + merged with a module with ``Objective-C GC Only`` set to 6. + +Automatic Linker Flags Module Flags Metadata +-------------------------------------------- + +Some targets support embedding flags to the linker inside individual object +files. Typically this is used in conjunction with language extensions which +allow source files to explicitly declare the libraries they depend on, and have +these automatically be transmitted to the linker via object files. + +These flags are encoded in the IR using metadata in the module flags section, +using the ``Linker Options`` key. The merge behavior for this flag is required +to be ``AppendUnique``, and the value for the key is expected to be a metadata +node which should be a list of other metadata nodes, each of which should be a +list of metadata strings defining linker options. + +For example, the following metadata section specifies two separate sets of +linker options, presumably to link against ``libz`` and the ``Cocoa`` +framework:: + + !0 = metadata !{ i32 6, metadata !"Linker Options", + metadata !{ + metadata !{ metadata !"-lz" }, + metadata !{ metadata !"-framework", metadata !"Cocoa" } } } + !llvm.module.flags = !{ !0 } + +The metadata encoding as lists of lists of options, as opposed to a collapsed +list of options, is chosen so that the IR encoding can use multiple option +strings to specify e.g., a single library, while still having that specifier be +preserved as an atomic element that can be recognized by a target specific +assembly writer or object file emitter. + +Each individual option is required to be either a valid option for the target's +linker, or an option that is reserved by the target specific assembly writer or +object file emitter. No other aspect of these options is defined by the IR. + +.. _intrinsicglobalvariables: + +Intrinsic Global Variables +========================== + +LLVM has a number of "magic" global variables that contain data that +affect code generation or other IR semantics. These are documented here. +All globals of this sort should have a section specified as +"``llvm.metadata``". This section and all globals that start with +"``llvm.``" are reserved for use by LLVM. + +.. _gv_llvmused: + +The '``llvm.used``' Global Variable +----------------------------------- + +The ``@llvm.used`` global is an array which has +:ref:`appending linkage `. This array contains a list of +pointers to named global variables, functions and aliases which may optionally +have a pointer cast formed of bitcast or getelementptr. For example, a legal +use of it is: + +.. code-block:: llvm + + @X = global i8 4 + @Y = global i32 123 + + @llvm.used = appending global [2 x i8*] [ + i8* @X, + i8* bitcast (i32* @Y to i8*) + ], section "llvm.metadata" + +If a symbol appears in the ``@llvm.used`` list, then the compiler, assembler, +and linker are required to treat the symbol as if there is a reference to the +symbol that it cannot see (which is why they have to be named). For example, if +a variable has internal linkage and no references other than that from the +``@llvm.used`` list, it cannot be deleted. This is commonly used to represent +references from inline asms and other things the compiler cannot "see", and +corresponds to "``attribute((used))``" in GNU C. + +On some targets, the code generator must emit a directive to the +assembler or object file to prevent the assembler and linker from +molesting the symbol. + +.. _gv_llvmcompilerused: + +The '``llvm.compiler.used``' Global Variable +-------------------------------------------- + +The ``@llvm.compiler.used`` directive is the same as the ``@llvm.used`` +directive, except that it only prevents the compiler from touching the +symbol. On targets that support it, this allows an intelligent linker to +optimize references to the symbol without being impeded as it would be +by ``@llvm.used``. + +This is a rare construct that should only be used in rare circumstances, +and should not be exposed to source languages. + +.. _gv_llvmglobalctors: + +The '``llvm.global_ctors``' Global Variable +------------------------------------------- + +.. code-block:: llvm + + %0 = type { i32, void ()* } + @llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @ctor }] + +The ``@llvm.global_ctors`` array contains a list of constructor +functions and associated priorities. The functions referenced by this +array will be called in ascending order of priority (i.e. lowest first) +when the module is loaded. The order of functions with the same priority +is not defined. + +.. _llvmglobaldtors: + +The '``llvm.global_dtors``' Global Variable +------------------------------------------- + +.. code-block:: llvm + + %0 = type { i32, void ()* } + @llvm.global_dtors = appending global [1 x %0] [%0 { i32 65535, void ()* @dtor }] + +The ``@llvm.global_dtors`` array contains a list of destructor functions +and associated priorities. The functions referenced by this array will +be called in descending order of priority (i.e. highest first) when the +module is loaded. The order of functions with the same priority is not +defined. + +Instruction Reference +===================== + +The LLVM instruction set consists of several different classifications +of instructions: :ref:`terminator instructions `, :ref:`binary +instructions `, :ref:`bitwise binary +instructions `, :ref:`memory instructions `, and +:ref:`other instructions `. + +.. _terminators: + +Terminator Instructions +----------------------- + +As mentioned :ref:`previously `, every basic block in a +program ends with a "Terminator" instruction, which indicates which +block should be executed after the current block is finished. These +terminator instructions typically yield a '``void``' value: they produce +control flow, not values (the one exception being the +':ref:`invoke `' instruction). + +The terminator instructions are: ':ref:`ret `', +':ref:`br `', ':ref:`switch `', +':ref:`indirectbr `', ':ref:`invoke `', +':ref:`resume `', and ':ref:`unreachable `'. + +.. _i_ret: + +'``ret``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + ret ; Return a value from a non-void function + ret void ; Return from void function + +Overview: +""""""""" + +The '``ret``' instruction is used to return control flow (and optionally +a value) from a function back to the caller. + +There are two forms of the '``ret``' instruction: one that returns a +value and then causes control flow, and one that just causes control +flow to occur. + +Arguments: +"""""""""" + +The '``ret``' instruction optionally accepts a single argument, the +return value. The type of the return value must be a ':ref:`first +class `' type. + +A function is not :ref:`well formed ` if it it has a non-void +return type and contains a '``ret``' instruction with no return value or +a return value with a type that does not match its type, or if it has a +void return type and contains a '``ret``' instruction with a return +value. + +Semantics: +"""""""""" + +When the '``ret``' instruction is executed, control flow returns back to +the calling function's context. If the caller is a +":ref:`call `" instruction, execution continues at the +instruction after the call. If the caller was an +":ref:`invoke `" instruction, execution continues at the +beginning of the "normal" destination block. If the instruction returns +a value, that value shall set the call or invoke instruction's return +value. + +Example: +"""""""" + +.. code-block:: llvm + + ret i32 5 ; Return an integer value of 5 + ret void ; Return from a void function + ret { i32, i8 } { i32 4, i8 2 } ; Return a struct of values 4 and 2 + +.. _i_br: + +'``br``' Instruction +^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + br i1 , label , label + br label ; Unconditional branch + +Overview: +""""""""" + +The '``br``' instruction is used to cause control flow to transfer to a +different basic block in the current function. There are two forms of +this instruction, corresponding to a conditional branch and an +unconditional branch. + +Arguments: +"""""""""" + +The conditional branch form of the '``br``' instruction takes a single +'``i1``' value and two '``label``' values. The unconditional form of the +'``br``' instruction takes a single '``label``' value as a target. + +Semantics: +"""""""""" + +Upon execution of a conditional '``br``' instruction, the '``i1``' +argument is evaluated. If the value is ``true``, control flows to the +'``iftrue``' ``label`` argument. If "cond" is ``false``, control flows +to the '``iffalse``' ``label`` argument. + +Example: +"""""""" + +.. code-block:: llvm + + Test: + %cond = icmp eq i32 %a, %b + br i1 %cond, label %IfEqual, label %IfUnequal + IfEqual: + ret i32 1 + IfUnequal: + ret i32 0 + +.. _i_switch: + +'``switch``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + switch , label [ , label ... ] + +Overview: +""""""""" + +The '``switch``' instruction is used to transfer control flow to one of +several different places. It is a generalization of the '``br``' +instruction, allowing a branch to occur to one of many possible +destinations. + +Arguments: +"""""""""" + +The '``switch``' instruction uses three parameters: an integer +comparison value '``value``', a default '``label``' destination, and an +array of pairs of comparison value constants and '``label``'s. The table +is not allowed to contain duplicate constant entries. + +Semantics: +"""""""""" + +The ``switch`` instruction specifies a table of values and destinations. +When the '``switch``' instruction is executed, this table is searched +for the given value. If the value is found, control flow is transferred +to the corresponding destination; otherwise, control flow is transferred +to the default destination. + +Implementation: +""""""""""""""" + +Depending on properties of the target machine and the particular +``switch`` instruction, this instruction may be code generated in +different ways. For example, it could be generated as a series of +chained conditional branches or with a lookup table. + +Example: +"""""""" + +.. code-block:: llvm + + ; Emulate a conditional br instruction + %Val = zext i1 %value to i32 + switch i32 %Val, label %truedest [ i32 0, label %falsedest ] + + ; Emulate an unconditional br instruction + switch i32 0, label %dest [ ] + + ; Implement a jump table: + switch i32 %val, label %otherwise [ i32 0, label %onzero + i32 1, label %onone + i32 2, label %ontwo ] + +.. _i_indirectbr: + +'``indirectbr``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + indirectbr *
, [ label , label , ... ] + +Overview: +""""""""" + +The '``indirectbr``' instruction implements an indirect branch to a +label within the current function, whose address is specified by +"``address``". Address must be derived from a +:ref:`blockaddress ` constant. + +Arguments: +"""""""""" + +The '``address``' argument is the address of the label to jump to. The +rest of the arguments indicate the full set of possible destinations +that the address may point to. Blocks are allowed to occur multiple +times in the destination list, though this isn't particularly useful. + +This destination list is required so that dataflow analysis has an +accurate understanding of the CFG. + +Semantics: +"""""""""" + +Control transfers to the block specified in the address argument. All +possible destination blocks must be listed in the label list, otherwise +this instruction has undefined behavior. This implies that jumps to +labels defined in other functions have undefined behavior as well. + +Implementation: +""""""""""""""" + +This is typically implemented with a jump through a register. + +Example: +"""""""" + +.. code-block:: llvm + + indirectbr i8* %Addr, [ label %bb1, label %bb2, label %bb3 ] + +.. _i_invoke: + +'``invoke``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = invoke [cconv] [ret attrs] () [fn attrs] + to label unwind label + +Overview: +""""""""" + +The '``invoke``' instruction causes control to transfer to a specified +function, with the possibility of control flow transfer to either the +'``normal``' label or the '``exception``' label. If the callee function +returns with the "``ret``" instruction, control flow will return to the +"normal" label. If the callee (or any indirect callees) returns via the +":ref:`resume `" instruction or other exception handling +mechanism, control is interrupted and continued at the dynamically +nearest "exception" label. + +The '``exception``' label is a `landing +pad `_ for the exception. As such, +'``exception``' label is required to have the +":ref:`landingpad `" instruction, which contains the +information about the behavior of the program after unwinding happens, +as its first non-PHI instruction. The restrictions on the +"``landingpad``" instruction's tightly couples it to the "``invoke``" +instruction, so that the important information contained within the +"``landingpad``" instruction can't be lost through normal code motion. + +Arguments: +"""""""""" + +This instruction requires several arguments: + +#. The optional "cconv" marker indicates which :ref:`calling + convention ` the call should use. If none is + specified, the call defaults to using C calling conventions. +#. The optional :ref:`Parameter Attributes ` list for return + values. Only '``zeroext``', '``signext``', and '``inreg``' attributes + are valid here. +#. '``ptr to function ty``': shall be the signature of the pointer to + function value being invoked. In most cases, this is a direct + function invocation, but indirect ``invoke``'s are just as possible, + branching off an arbitrary pointer to function value. +#. '``function ptr val``': An LLVM value containing a pointer to a + function to be invoked. +#. '``function args``': argument list whose types match the function + signature argument types and parameter attributes. All arguments must + be of :ref:`first class ` type. If the function signature + indicates the function accepts a variable number of arguments, the + extra arguments can be specified. +#. '``normal label``': the label reached when the called function + executes a '``ret``' instruction. +#. '``exception label``': the label reached when a callee returns via + the :ref:`resume ` instruction or other exception handling + mechanism. +#. The optional :ref:`function attributes ` list. Only + '``noreturn``', '``nounwind``', '``readonly``' and '``readnone``' + attributes are valid here. + +Semantics: +"""""""""" + +This instruction is designed to operate as a standard '``call``' +instruction in most regards. The primary difference is that it +establishes an association with a label, which is used by the runtime +library to unwind the stack. + +This instruction is used in languages with destructors to ensure that +proper cleanup is performed in the case of either a ``longjmp`` or a +thrown exception. Additionally, this is important for implementation of +'``catch``' clauses in high-level languages that support them. + +For the purposes of the SSA form, the definition of the value returned +by the '``invoke``' instruction is deemed to occur on the edge from the +current block to the "normal" label. If the callee unwinds then no +return value is available. + +Example: +"""""""" + +.. code-block:: llvm + + %retval = invoke i32 @Test(i32 15) to label %Continue + unwind label %TestCleanup ; {i32}:retval set + %retval = invoke coldcc i32 %Testfnptr(i32 15) to label %Continue + unwind label %TestCleanup ; {i32}:retval set + +.. _i_resume: + +'``resume``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + resume + +Overview: +""""""""" + +The '``resume``' instruction is a terminator instruction that has no +successors. + +Arguments: +"""""""""" + +The '``resume``' instruction requires one argument, which must have the +same type as the result of any '``landingpad``' instruction in the same +function. + +Semantics: +"""""""""" + +The '``resume``' instruction resumes propagation of an existing +(in-flight) exception whose unwinding was interrupted with a +:ref:`landingpad ` instruction. + +Example: +"""""""" + +.. code-block:: llvm + + resume { i8*, i32 } %exn + +.. _i_unreachable: + +'``unreachable``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + unreachable + +Overview: +""""""""" + +The '``unreachable``' instruction has no defined semantics. This +instruction is used to inform the optimizer that a particular portion of +the code is not reachable. This can be used to indicate that the code +after a no-return function cannot be reached, and other facts. + +Semantics: +"""""""""" + +The '``unreachable``' instruction has no defined semantics. + +.. _binaryops: + +Binary Operations +----------------- + +Binary operators are used to do most of the computation in a program. +They require two operands of the same type, execute an operation on +them, and produce a single value. The operands might represent multiple +data, as is the case with the :ref:`vector ` data type. The +result value has the same type as its operands. + +There are several different binary operators: + +.. _i_add: + +'``add``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = add , ; yields {ty}:result + = add nuw , ; yields {ty}:result + = add nsw , ; yields {ty}:result + = add nuw nsw , ; yields {ty}:result + +Overview: +""""""""" + +The '``add``' instruction returns the sum of its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``add``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the integer sum of the two operands. + +If the sum has unsigned overflow, the result returned is the +mathematical result modulo 2\ :sup:`n`\ , where n is the bit width of +the result. + +Because LLVM integers use a two's complement representation, this +instruction is appropriate for both signed and unsigned integers. + +``nuw`` and ``nsw`` stand for "No Unsigned Wrap" and "No Signed Wrap", +respectively. If the ``nuw`` and/or ``nsw`` keywords are present, the +result value of the ``add`` is a :ref:`poison value ` if +unsigned and/or signed overflow, respectively, occurs. + +Example: +"""""""" + +.. code-block:: llvm + + = add i32 4, %var ; yields {i32}:result = 4 + %var + +.. _i_fadd: + +'``fadd``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fadd [fast-math flags]* , ; yields {ty}:result + +Overview: +""""""""" + +The '``fadd``' instruction returns the sum of its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``fadd``' instruction must be :ref:`floating +point ` or :ref:`vector ` of floating point values. +Both arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the floating point sum of the two operands. This +instruction can also take any number of :ref:`fast-math flags `, +which are optimization hints to enable otherwise unsafe floating point +optimizations: + +Example: +"""""""" + +.. code-block:: llvm + + = fadd float 4.0, %var ; yields {float}:result = 4.0 + %var + +'``sub``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = sub , ; yields {ty}:result + = sub nuw , ; yields {ty}:result + = sub nsw , ; yields {ty}:result + = sub nuw nsw , ; yields {ty}:result + +Overview: +""""""""" + +The '``sub``' instruction returns the difference of its two operands. + +Note that the '``sub``' instruction is used to represent the '``neg``' +instruction present in most other intermediate representations. + +Arguments: +"""""""""" + +The two arguments to the '``sub``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the integer difference of the two operands. + +If the difference has unsigned overflow, the result returned is the +mathematical result modulo 2\ :sup:`n`\ , where n is the bit width of +the result. + +Because LLVM integers use a two's complement representation, this +instruction is appropriate for both signed and unsigned integers. + +``nuw`` and ``nsw`` stand for "No Unsigned Wrap" and "No Signed Wrap", +respectively. If the ``nuw`` and/or ``nsw`` keywords are present, the +result value of the ``sub`` is a :ref:`poison value ` if +unsigned and/or signed overflow, respectively, occurs. + +Example: +"""""""" + +.. code-block:: llvm + + = sub i32 4, %var ; yields {i32}:result = 4 - %var + = sub i32 0, %val ; yields {i32}:result = -%var + +.. _i_fsub: + +'``fsub``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fsub [fast-math flags]* , ; yields {ty}:result + +Overview: +""""""""" + +The '``fsub``' instruction returns the difference of its two operands. + +Note that the '``fsub``' instruction is used to represent the '``fneg``' +instruction present in most other intermediate representations. + +Arguments: +"""""""""" + +The two arguments to the '``fsub``' instruction must be :ref:`floating +point ` or :ref:`vector ` of floating point values. +Both arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the floating point difference of the two operands. +This instruction can also take any number of :ref:`fast-math +flags `, which are optimization hints to enable otherwise +unsafe floating point optimizations: + +Example: +"""""""" + +.. code-block:: llvm + + = fsub float 4.0, %var ; yields {float}:result = 4.0 - %var + = fsub float -0.0, %val ; yields {float}:result = -%var + +'``mul``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = mul , ; yields {ty}:result + = mul nuw , ; yields {ty}:result + = mul nsw , ; yields {ty}:result + = mul nuw nsw , ; yields {ty}:result + +Overview: +""""""""" + +The '``mul``' instruction returns the product of its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``mul``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the integer product of the two operands. + +If the result of the multiplication has unsigned overflow, the result +returned is the mathematical result modulo 2\ :sup:`n`\ , where n is the +bit width of the result. + +Because LLVM integers use a two's complement representation, and the +result is the same width as the operands, this instruction returns the +correct result for both signed and unsigned integers. If a full product +(e.g. ``i32`` * ``i32`` -> ``i64``) is needed, the operands should be +sign-extended or zero-extended as appropriate to the width of the full +product. + +``nuw`` and ``nsw`` stand for "No Unsigned Wrap" and "No Signed Wrap", +respectively. If the ``nuw`` and/or ``nsw`` keywords are present, the +result value of the ``mul`` is a :ref:`poison value ` if +unsigned and/or signed overflow, respectively, occurs. + +Example: +"""""""" + +.. code-block:: llvm + + = mul i32 4, %var ; yields {i32}:result = 4 * %var + +.. _i_fmul: + +'``fmul``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fmul [fast-math flags]* , ; yields {ty}:result + +Overview: +""""""""" + +The '``fmul``' instruction returns the product of its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``fmul``' instruction must be :ref:`floating +point ` or :ref:`vector ` of floating point values. +Both arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the floating point product of the two operands. +This instruction can also take any number of :ref:`fast-math +flags `, which are optimization hints to enable otherwise +unsafe floating point optimizations: + +Example: +"""""""" + +.. code-block:: llvm + + = fmul float 4.0, %var ; yields {float}:result = 4.0 * %var + +'``udiv``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = udiv , ; yields {ty}:result + = udiv exact , ; yields {ty}:result + +Overview: +""""""""" + +The '``udiv``' instruction returns the quotient of its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``udiv``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the unsigned integer quotient of the two operands. + +Note that unsigned integer division and signed integer division are +distinct operations; for signed integer division, use '``sdiv``'. + +Division by zero leads to undefined behavior. + +If the ``exact`` keyword is present, the result value of the ``udiv`` is +a :ref:`poison value ` if %op1 is not a multiple of %op2 (as +such, "((a udiv exact b) mul b) == a"). + +Example: +"""""""" + +.. code-block:: llvm + + = udiv i32 4, %var ; yields {i32}:result = 4 / %var + +'``sdiv``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = sdiv , ; yields {ty}:result + = sdiv exact , ; yields {ty}:result + +Overview: +""""""""" + +The '``sdiv``' instruction returns the quotient of its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``sdiv``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the signed integer quotient of the two operands +rounded towards zero. + +Note that signed integer division and unsigned integer division are +distinct operations; for unsigned integer division, use '``udiv``'. + +Division by zero leads to undefined behavior. Overflow also leads to +undefined behavior; this is a rare case, but can occur, for example, by +doing a 32-bit division of -2147483648 by -1. + +If the ``exact`` keyword is present, the result value of the ``sdiv`` is +a :ref:`poison value ` if the result would be rounded. + +Example: +"""""""" + +.. code-block:: llvm + + = sdiv i32 4, %var ; yields {i32}:result = 4 / %var + +.. _i_fdiv: + +'``fdiv``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fdiv [fast-math flags]* , ; yields {ty}:result + +Overview: +""""""""" + +The '``fdiv``' instruction returns the quotient of its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``fdiv``' instruction must be :ref:`floating +point ` or :ref:`vector ` of floating point values. +Both arguments must have identical types. + +Semantics: +"""""""""" + +The value produced is the floating point quotient of the two operands. +This instruction can also take any number of :ref:`fast-math +flags `, which are optimization hints to enable otherwise +unsafe floating point optimizations: + +Example: +"""""""" + +.. code-block:: llvm + + = fdiv float 4.0, %var ; yields {float}:result = 4.0 / %var + +'``urem``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = urem , ; yields {ty}:result + +Overview: +""""""""" + +The '``urem``' instruction returns the remainder from the unsigned +division of its two arguments. + +Arguments: +"""""""""" + +The two arguments to the '``urem``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +This instruction returns the unsigned integer *remainder* of a division. +This instruction always performs an unsigned division to get the +remainder. + +Note that unsigned integer remainder and signed integer remainder are +distinct operations; for signed integer remainder, use '``srem``'. + +Taking the remainder of a division by zero leads to undefined behavior. + +Example: +"""""""" + +.. code-block:: llvm + + = urem i32 4, %var ; yields {i32}:result = 4 % %var + +'``srem``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = srem , ; yields {ty}:result + +Overview: +""""""""" + +The '``srem``' instruction returns the remainder from the signed +division of its two operands. This instruction can also take +:ref:`vector ` versions of the values in which case the elements +must be integers. + +Arguments: +"""""""""" + +The two arguments to the '``srem``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +This instruction returns the *remainder* of a division (where the result +is either zero or has the same sign as the dividend, ``op1``), not the +*modulo* operator (where the result is either zero or has the same sign +as the divisor, ``op2``) of a value. For more information about the +difference, see `The Math +Forum `_. For a +table of how this is implemented in various languages, please see +`Wikipedia: modulo +operation `_. + +Note that signed integer remainder and unsigned integer remainder are +distinct operations; for unsigned integer remainder, use '``urem``'. + +Taking the remainder of a division by zero leads to undefined behavior. +Overflow also leads to undefined behavior; this is a rare case, but can +occur, for example, by taking the remainder of a 32-bit division of +-2147483648 by -1. (The remainder doesn't actually overflow, but this +rule lets srem be implemented using instructions that return both the +result of the division and the remainder.) + +Example: +"""""""" + +.. code-block:: llvm + + = srem i32 4, %var ; yields {i32}:result = 4 % %var + +.. _i_frem: + +'``frem``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = frem [fast-math flags]* , ; yields {ty}:result + +Overview: +""""""""" + +The '``frem``' instruction returns the remainder from the division of +its two operands. + +Arguments: +"""""""""" + +The two arguments to the '``frem``' instruction must be :ref:`floating +point ` or :ref:`vector ` of floating point values. +Both arguments must have identical types. + +Semantics: +"""""""""" + +This instruction returns the *remainder* of a division. The remainder +has the same sign as the dividend. This instruction can also take any +number of :ref:`fast-math flags `, which are optimization hints +to enable otherwise unsafe floating point optimizations: + +Example: +"""""""" + +.. code-block:: llvm + + = frem float 4.0, %var ; yields {float}:result = 4.0 % %var + +.. _bitwiseops: + +Bitwise Binary Operations +------------------------- + +Bitwise binary operators are used to do various forms of bit-twiddling +in a program. They are generally very efficient instructions and can +commonly be strength reduced from other instructions. They require two +operands of the same type, execute an operation on them, and produce a +single value. The resulting value is the same type as its operands. + +'``shl``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = shl , ; yields {ty}:result + = shl nuw , ; yields {ty}:result + = shl nsw , ; yields {ty}:result + = shl nuw nsw , ; yields {ty}:result + +Overview: +""""""""" + +The '``shl``' instruction returns the first operand shifted to the left +a specified number of bits. + +Arguments: +"""""""""" + +Both arguments to the '``shl``' instruction must be the same +:ref:`integer ` or :ref:`vector ` of integer type. +'``op2``' is treated as an unsigned value. + +Semantics: +"""""""""" + +The value produced is ``op1`` \* 2\ :sup:`op2` mod 2\ :sup:`n`, +where ``n`` is the width of the result. If ``op2`` is (statically or +dynamically) negative or equal to or larger than the number of bits in +``op1``, the result is undefined. If the arguments are vectors, each +vector element of ``op1`` is shifted by the corresponding shift amount +in ``op2``. + +If the ``nuw`` keyword is present, then the shift produces a :ref:`poison +value ` if it shifts out any non-zero bits. If the +``nsw`` keyword is present, then the shift produces a :ref:`poison +value ` if it shifts out any bits that disagree with the +resultant sign bit. As such, NUW/NSW have the same semantics as they +would if the shift were expressed as a mul instruction with the same +nsw/nuw bits in (mul %op1, (shl 1, %op2)). + +Example: +"""""""" + +.. code-block:: llvm + + = shl i32 4, %var ; yields {i32}: 4 << %var + = shl i32 4, 2 ; yields {i32}: 16 + = shl i32 1, 10 ; yields {i32}: 1024 + = shl i32 1, 32 ; undefined + = shl <2 x i32> < i32 1, i32 1>, < i32 1, i32 2> ; yields: result=<2 x i32> < i32 2, i32 4> + +'``lshr``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = lshr , ; yields {ty}:result + = lshr exact , ; yields {ty}:result + +Overview: +""""""""" + +The '``lshr``' instruction (logical shift right) returns the first +operand shifted to the right a specified number of bits with zero fill. + +Arguments: +"""""""""" + +Both arguments to the '``lshr``' instruction must be the same +:ref:`integer ` or :ref:`vector ` of integer type. +'``op2``' is treated as an unsigned value. + +Semantics: +"""""""""" + +This instruction always performs a logical shift right operation. The +most significant bits of the result will be filled with zero bits after +the shift. If ``op2`` is (statically or dynamically) equal to or larger +than the number of bits in ``op1``, the result is undefined. If the +arguments are vectors, each vector element of ``op1`` is shifted by the +corresponding shift amount in ``op2``. + +If the ``exact`` keyword is present, the result value of the ``lshr`` is +a :ref:`poison value ` if any of the bits shifted out are +non-zero. + +Example: +"""""""" + +.. code-block:: llvm + + = lshr i32 4, 1 ; yields {i32}:result = 2 + = lshr i32 4, 2 ; yields {i32}:result = 1 + = lshr i8 4, 3 ; yields {i8}:result = 0 + = lshr i8 -2, 1 ; yields {i8}:result = 0x7F + = lshr i32 1, 32 ; undefined + = lshr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 2> ; yields: result=<2 x i32> < i32 0x7FFFFFFF, i32 1> + +'``ashr``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = ashr , ; yields {ty}:result + = ashr exact , ; yields {ty}:result + +Overview: +""""""""" + +The '``ashr``' instruction (arithmetic shift right) returns the first +operand shifted to the right a specified number of bits with sign +extension. + +Arguments: +"""""""""" + +Both arguments to the '``ashr``' instruction must be the same +:ref:`integer ` or :ref:`vector ` of integer type. +'``op2``' is treated as an unsigned value. + +Semantics: +"""""""""" + +This instruction always performs an arithmetic shift right operation, +The most significant bits of the result will be filled with the sign bit +of ``op1``. If ``op2`` is (statically or dynamically) equal to or larger +than the number of bits in ``op1``, the result is undefined. If the +arguments are vectors, each vector element of ``op1`` is shifted by the +corresponding shift amount in ``op2``. + +If the ``exact`` keyword is present, the result value of the ``ashr`` is +a :ref:`poison value ` if any of the bits shifted out are +non-zero. + +Example: +"""""""" + +.. code-block:: llvm + + = ashr i32 4, 1 ; yields {i32}:result = 2 + = ashr i32 4, 2 ; yields {i32}:result = 1 + = ashr i8 4, 3 ; yields {i8}:result = 0 + = ashr i8 -2, 1 ; yields {i8}:result = -1 + = ashr i32 1, 32 ; undefined + = ashr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 3> ; yields: result=<2 x i32> < i32 -1, i32 0> + +'``and``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = and , ; yields {ty}:result + +Overview: +""""""""" + +The '``and``' instruction returns the bitwise logical and of its two +operands. + +Arguments: +"""""""""" + +The two arguments to the '``and``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The truth table used for the '``and``' instruction is: + ++-----+-----+-----+ +| In0 | In1 | Out | ++-----+-----+-----+ +| 0 | 0 | 0 | ++-----+-----+-----+ +| 0 | 1 | 0 | ++-----+-----+-----+ +| 1 | 0 | 0 | ++-----+-----+-----+ +| 1 | 1 | 1 | ++-----+-----+-----+ + +Example: +"""""""" + +.. code-block:: llvm + + = and i32 4, %var ; yields {i32}:result = 4 & %var + = and i32 15, 40 ; yields {i32}:result = 8 + = and i32 4, 8 ; yields {i32}:result = 0 + +'``or``' Instruction +^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = or , ; yields {ty}:result + +Overview: +""""""""" + +The '``or``' instruction returns the bitwise logical inclusive or of its +two operands. + +Arguments: +"""""""""" + +The two arguments to the '``or``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The truth table used for the '``or``' instruction is: + ++-----+-----+-----+ +| In0 | In1 | Out | ++-----+-----+-----+ +| 0 | 0 | 0 | ++-----+-----+-----+ +| 0 | 1 | 1 | ++-----+-----+-----+ +| 1 | 0 | 1 | ++-----+-----+-----+ +| 1 | 1 | 1 | ++-----+-----+-----+ + +Example: +"""""""" + +:: + + = or i32 4, %var ; yields {i32}:result = 4 | %var + = or i32 15, 40 ; yields {i32}:result = 47 + = or i32 4, 8 ; yields {i32}:result = 12 + +'``xor``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = xor , ; yields {ty}:result + +Overview: +""""""""" + +The '``xor``' instruction returns the bitwise logical exclusive or of +its two operands. The ``xor`` is used to implement the "one's +complement" operation, which is the "~" operator in C. + +Arguments: +"""""""""" + +The two arguments to the '``xor``' instruction must be +:ref:`integer ` or :ref:`vector ` of integer values. Both +arguments must have identical types. + +Semantics: +"""""""""" + +The truth table used for the '``xor``' instruction is: + ++-----+-----+-----+ +| In0 | In1 | Out | ++-----+-----+-----+ +| 0 | 0 | 0 | ++-----+-----+-----+ +| 0 | 1 | 1 | ++-----+-----+-----+ +| 1 | 0 | 1 | ++-----+-----+-----+ +| 1 | 1 | 0 | ++-----+-----+-----+ + +Example: +"""""""" + +.. code-block:: llvm + + = xor i32 4, %var ; yields {i32}:result = 4 ^ %var + = xor i32 15, 40 ; yields {i32}:result = 39 + = xor i32 4, 8 ; yields {i32}:result = 12 + = xor i32 %V, -1 ; yields {i32}:result = ~%V + +Vector Operations +----------------- + +LLVM supports several instructions to represent vector operations in a +target-independent manner. These instructions cover the element-access +and vector-specific operations needed to process vectors effectively. +While LLVM does directly support these vector operations, many +sophisticated algorithms will want to use target-specific intrinsics to +take full advantage of a specific target. + +.. _i_extractelement: + +'``extractelement``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = extractelement > , i32 ; yields + +Overview: +""""""""" + +The '``extractelement``' instruction extracts a single scalar element +from a vector at a specified index. + +Arguments: +"""""""""" + +The first operand of an '``extractelement``' instruction is a value of +:ref:`vector ` type. The second operand is an index indicating +the position from which to extract the element. The index may be a +variable. + +Semantics: +"""""""""" + +The result is a scalar of the same type as the element type of ``val``. +Its value is the value at position ``idx`` of ``val``. If ``idx`` +exceeds the length of ``val``, the results are undefined. + +Example: +"""""""" + +.. code-block:: llvm + + = extractelement <4 x i32> %vec, i32 0 ; yields i32 + +.. _i_insertelement: + +'``insertelement``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = insertelement > , , i32 ; yields > + +Overview: +""""""""" + +The '``insertelement``' instruction inserts a scalar element into a +vector at a specified index. + +Arguments: +"""""""""" + +The first operand of an '``insertelement``' instruction is a value of +:ref:`vector ` type. The second operand is a scalar value whose +type must equal the element type of the first operand. The third operand +is an index indicating the position at which to insert the value. The +index may be a variable. + +Semantics: +"""""""""" + +The result is a vector of the same type as ``val``. Its element values +are those of ``val`` except at position ``idx``, where it gets the value +``elt``. If ``idx`` exceeds the length of ``val``, the results are +undefined. + +Example: +"""""""" + +.. code-block:: llvm + + = insertelement <4 x i32> %vec, i32 1, i32 0 ; yields <4 x i32> + +.. _i_shufflevector: + +'``shufflevector``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = shufflevector > , > , ; yields > + +Overview: +""""""""" + +The '``shufflevector``' instruction constructs a permutation of elements +from two input vectors, returning a vector with the same element type as +the input and length that is the same as the shuffle mask. + +Arguments: +"""""""""" + +The first two operands of a '``shufflevector``' instruction are vectors +with the same type. The third argument is a shuffle mask whose element +type is always 'i32'. The result of the instruction is a vector whose +length is the same as the shuffle mask and whose element type is the +same as the element type of the first two operands. + +The shuffle mask operand is required to be a constant vector with either +constant integer or undef values. + +Semantics: +"""""""""" + +The elements of the two input vectors are numbered from left to right +across both of the vectors. The shuffle mask operand specifies, for each +element of the result vector, which element of the two input vectors the +result element gets. The element selector may be undef (meaning "don't +care") and the second operand may be undef if performing a shuffle from +only one vector. + +Example: +"""""""" + +.. code-block:: llvm + + = shufflevector <4 x i32> %v1, <4 x i32> %v2, + <4 x i32> ; yields <4 x i32> + = shufflevector <4 x i32> %v1, <4 x i32> undef, + <4 x i32> ; yields <4 x i32> - Identity shuffle. + = shufflevector <8 x i32> %v1, <8 x i32> undef, + <4 x i32> ; yields <4 x i32> + = shufflevector <4 x i32> %v1, <4 x i32> %v2, + <8 x i32> ; yields <8 x i32> + +Aggregate Operations +-------------------- + +LLVM supports several instructions for working with +:ref:`aggregate ` values. + +.. _i_extractvalue: + +'``extractvalue``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = extractvalue , {, }* + +Overview: +""""""""" + +The '``extractvalue``' instruction extracts the value of a member field +from an :ref:`aggregate ` value. + +Arguments: +"""""""""" + +The first operand of an '``extractvalue``' instruction is a value of +:ref:`struct ` or :ref:`array ` type. The operands are +constant indices to specify which value to extract in a similar manner +as indices in a '``getelementptr``' instruction. + +The major differences to ``getelementptr`` indexing are: + +- Since the value being indexed is not a pointer, the first index is + omitted and assumed to be zero. +- At least one index must be specified. +- Not only struct indices but also array indices must be in bounds. + +Semantics: +"""""""""" + +The result is the value at the position in the aggregate specified by +the index operands. + +Example: +"""""""" + +.. code-block:: llvm + + = extractvalue {i32, float} %agg, 0 ; yields i32 + +.. _i_insertvalue: + +'``insertvalue``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = insertvalue , , {, }* ; yields + +Overview: +""""""""" + +The '``insertvalue``' instruction inserts a value into a member field in +an :ref:`aggregate ` value. + +Arguments: +"""""""""" + +The first operand of an '``insertvalue``' instruction is a value of +:ref:`struct ` or :ref:`array ` type. The second operand is +a first-class value to insert. The following operands are constant +indices indicating the position at which to insert the value in a +similar manner as indices in a '``extractvalue``' instruction. The value +to insert must have the same type as the value identified by the +indices. + +Semantics: +"""""""""" + +The result is an aggregate of the same type as ``val``. Its value is +that of ``val`` except that the value at the position specified by the +indices is that of ``elt``. + +Example: +"""""""" + +.. code-block:: llvm + + %agg1 = insertvalue {i32, float} undef, i32 1, 0 ; yields {i32 1, float undef} + %agg2 = insertvalue {i32, float} %agg1, float %val, 1 ; yields {i32 1, float %val} + %agg3 = insertvalue {i32, {float}} %agg1, float %val, 1, 0 ; yields {i32 1, float %val} + +.. _memoryops: + +Memory Access and Addressing Operations +--------------------------------------- + +A key design point of an SSA-based representation is how it represents +memory. In LLVM, no memory locations are in SSA form, which makes things +very simple. This section describes how to read, write, and allocate +memory in LLVM. + +.. _i_alloca: + +'``alloca``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = alloca [, ][, align ] ; yields {type*}:result + +Overview: +""""""""" + +The '``alloca``' instruction allocates memory on the stack frame of the +currently executing function, to be automatically released when this +function returns to its caller. The object is always allocated in the +generic address space (address space zero). + +Arguments: +"""""""""" + +The '``alloca``' instruction allocates ``sizeof()*NumElements`` +bytes of memory on the runtime stack, returning a pointer of the +appropriate type to the program. If "NumElements" is specified, it is +the number of elements allocated, otherwise "NumElements" is defaulted +to be one. If a constant alignment is specified, the value result of the +allocation is guaranteed to be aligned to at least that boundary. If not +specified, or if zero, the target can choose to align the allocation on +any convenient boundary compatible with the type. + +'``type``' may be any sized type. + +Semantics: +"""""""""" + +Memory is allocated; a pointer is returned. The operation is undefined +if there is insufficient stack space for the allocation. '``alloca``'d +memory is automatically released when the function returns. The +'``alloca``' instruction is commonly used to represent automatic +variables that must have an address available. When the function returns +(either with the ``ret`` or ``resume`` instructions), the memory is +reclaimed. Allocating zero bytes is legal, but the result is undefined. +The order in which memory is allocated (ie., which way the stack grows) +is not specified. + +Example: +"""""""" + +.. code-block:: llvm + + %ptr = alloca i32 ; yields {i32*}:ptr + %ptr = alloca i32, i32 4 ; yields {i32*}:ptr + %ptr = alloca i32, i32 4, align 1024 ; yields {i32*}:ptr + %ptr = alloca i32, align 1024 ; yields {i32*}:ptr + +.. _i_load: + +'``load``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = load [volatile] * [, align ][, !nontemporal !][, !invariant.load !] + = load atomic [volatile] * [singlethread] , align + ! = !{ i32 1 } + +Overview: +""""""""" + +The '``load``' instruction is used to read from memory. + +Arguments: +"""""""""" + +The argument to the ``load`` instruction specifies the memory address +from which to load. The pointer must point to a :ref:`first +class ` type. If the ``load`` is marked as ``volatile``, +then the optimizer is not allowed to modify the number or order of +execution of this ``load`` with other :ref:`volatile +operations `. + +If the ``load`` is marked as ``atomic``, it takes an extra +:ref:`ordering ` and optional ``singlethread`` argument. The +``release`` and ``acq_rel`` orderings are not valid on ``load`` +instructions. Atomic loads produce :ref:`defined ` results +when they may see multiple atomic stores. The type of the pointee must +be an integer type whose bit width is a power of two greater than or +equal to eight and less than or equal to a target-specific size limit. +``align`` must be explicitly specified on atomic loads, and the load has +undefined behavior if the alignment is not set to a value which is at +least the size in bytes of the pointee. ``!nontemporal`` does not have +any defined semantics for atomic loads. + +The optional constant ``align`` argument specifies the alignment of the +operation (that is, the alignment of the memory address). A value of 0 +or an omitted ``align`` argument means that the operation has the ABI +alignment for the target. It is the responsibility of the code emitter +to ensure that the alignment information is correct. Overestimating the +alignment results in undefined behavior. Underestimating the alignment +may produce less efficient code. An alignment of 1 is always safe. + +The optional ``!nontemporal`` metadata must reference a single +metadata name ```` corresponding to a metadata node with one +``i32`` entry of value 1. The existence of the ``!nontemporal`` +metadata on the instruction tells the optimizer and code generator +that this load is not expected to be reused in the cache. The code +generator may select special instructions to save cache bandwidth, such +as the ``MOVNT`` instruction on x86. + +The optional ``!invariant.load`` metadata must reference a single +metadata name ```` corresponding to a metadata node with no +entries. The existence of the ``!invariant.load`` metadata on the +instruction tells the optimizer and code generator that this load +address points to memory which does not change value during program +execution. The optimizer may then move this load around, for example, by +hoisting it out of loops using loop invariant code motion. + +Semantics: +"""""""""" + +The location of memory pointed to is loaded. If the value being loaded +is of scalar type then the number of bytes read does not exceed the +minimum number of bytes needed to hold all bits of the type. For +example, loading an ``i24`` reads at most three bytes. When loading a +value of a type like ``i20`` with a size that is not an integral number +of bytes, the result is undefined if the value was not originally +written using a store of the same type. + +Examples: +""""""""" + +.. code-block:: llvm + + %ptr = alloca i32 ; yields {i32*}:ptr + store i32 3, i32* %ptr ; yields {void} + %val = load i32* %ptr ; yields {i32}:val = i32 3 + +.. _i_store: + +'``store``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + store [volatile] , * [, align ][, !nontemporal !] ; yields {void} + store atomic [volatile] , * [singlethread] , align ; yields {void} + +Overview: +""""""""" + +The '``store``' instruction is used to write to memory. + +Arguments: +"""""""""" + +There are two arguments to the ``store`` instruction: a value to store +and an address at which to store it. The type of the ```` +operand must be a pointer to the :ref:`first class ` type of +the ```` operand. If the ``store`` is marked as ``volatile``, +then the optimizer is not allowed to modify the number or order of +execution of this ``store`` with other :ref:`volatile +operations `. + +If the ``store`` is marked as ``atomic``, it takes an extra +:ref:`ordering ` and optional ``singlethread`` argument. The +``acquire`` and ``acq_rel`` orderings aren't valid on ``store`` +instructions. Atomic loads produce :ref:`defined ` results +when they may see multiple atomic stores. The type of the pointee must +be an integer type whose bit width is a power of two greater than or +equal to eight and less than or equal to a target-specific size limit. +``align`` must be explicitly specified on atomic stores, and the store +has undefined behavior if the alignment is not set to a value which is +at least the size in bytes of the pointee. ``!nontemporal`` does not +have any defined semantics for atomic stores. + +The optional constant ``align`` argument specifies the alignment of the +operation (that is, the alignment of the memory address). A value of 0 +or an omitted ``align`` argument means that the operation has the ABI +alignment for the target. It is the responsibility of the code emitter +to ensure that the alignment information is correct. Overestimating the +alignment results in undefined behavior. Underestimating the +alignment may produce less efficient code. An alignment of 1 is always +safe. + +The optional ``!nontemporal`` metadata must reference a single metadata +name ```` corresponding to a metadata node with one ``i32`` entry of +value 1. The existence of the ``!nontemporal`` metadata on the instruction +tells the optimizer and code generator that this load is not expected to +be reused in the cache. The code generator may select special +instructions to save cache bandwidth, such as the MOVNT instruction on +x86. + +Semantics: +"""""""""" + +The contents of memory are updated to contain ```` at the +location specified by the ```` operand. If ```` is +of scalar type then the number of bytes written does not exceed the +minimum number of bytes needed to hold all bits of the type. For +example, storing an ``i24`` writes at most three bytes. When writing a +value of a type like ``i20`` with a size that is not an integral number +of bytes, it is unspecified what happens to the extra bits that do not +belong to the type, but they will typically be overwritten. + +Example: +"""""""" + +.. code-block:: llvm + + %ptr = alloca i32 ; yields {i32*}:ptr + store i32 3, i32* %ptr ; yields {void} + %val = load i32* %ptr ; yields {i32}:val = i32 3 + +.. _i_fence: + +'``fence``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + fence [singlethread] ; yields {void} + +Overview: +""""""""" + +The '``fence``' instruction is used to introduce happens-before edges +between operations. + +Arguments: +"""""""""" + +'``fence``' instructions take an :ref:`ordering ` argument which +defines what *synchronizes-with* edges they add. They can only be given +``acquire``, ``release``, ``acq_rel``, and ``seq_cst`` orderings. + +Semantics: +"""""""""" + +A fence A which has (at least) ``release`` ordering semantics +*synchronizes with* a fence B with (at least) ``acquire`` ordering +semantics if and only if there exist atomic operations X and Y, both +operating on some atomic object M, such that A is sequenced before X, X +modifies M (either directly or through some side effect of a sequence +headed by X), Y is sequenced before B, and Y observes M. This provides a +*happens-before* dependency between A and B. Rather than an explicit +``fence``, one (but not both) of the atomic operations X or Y might +provide a ``release`` or ``acquire`` (resp.) ordering constraint and +still *synchronize-with* the explicit ``fence`` and establish the +*happens-before* edge. + +A ``fence`` which has ``seq_cst`` ordering, in addition to having both +``acquire`` and ``release`` semantics specified above, participates in +the global program order of other ``seq_cst`` operations and/or fences. + +The optional ":ref:`singlethread `" argument specifies +that the fence only synchronizes with other fences in the same thread. +(This is useful for interacting with signal handlers.) + +Example: +"""""""" + +.. code-block:: llvm + + fence acquire ; yields {void} + fence singlethread seq_cst ; yields {void} + +.. _i_cmpxchg: + +'``cmpxchg``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + cmpxchg [volatile] * , , [singlethread] ; yields {ty} + +Overview: +""""""""" + +The '``cmpxchg``' instruction is used to atomically modify memory. It +loads a value in memory and compares it to a given value. If they are +equal, it stores a new value into the memory. + +Arguments: +"""""""""" + +There are three arguments to the '``cmpxchg``' instruction: an address +to operate on, a value to compare to the value currently be at that +address, and a new value to place at that address if the compared values +are equal. The type of '' must be an integer type whose bit width +is a power of two greater than or equal to eight and less than or equal +to a target-specific size limit. '' and '' must have the same +type, and the type of '' must be a pointer to that type. If the +``cmpxchg`` is marked as ``volatile``, then the optimizer is not allowed +to modify the number or order of execution of this ``cmpxchg`` with +other :ref:`volatile operations `. + +The :ref:`ordering ` argument specifies how this ``cmpxchg`` +synchronizes with other atomic operations. + +The optional "``singlethread``" argument declares that the ``cmpxchg`` +is only atomic with respect to code (usually signal handlers) running in +the same thread as the ``cmpxchg``. Otherwise the cmpxchg is atomic with +respect to all other code in the system. + +The pointer passed into cmpxchg must have alignment greater than or +equal to the size in memory of the operand. + +Semantics: +"""""""""" + +The contents of memory at the location specified by the '````' +operand is read and compared to '````'; if the read value is the +equal, '````' is written. The original value at the location is +returned. + +A successful ``cmpxchg`` is a read-modify-write instruction for the purpose +of identifying release sequences. A failed ``cmpxchg`` is equivalent to an +atomic load with an ordering parameter determined by dropping any +``release`` part of the ``cmpxchg``'s ordering. + +Example: +"""""""" + +.. code-block:: llvm + + entry: + %orig = atomic load i32* %ptr unordered ; yields {i32} + br label %loop + + loop: + %cmp = phi i32 [ %orig, %entry ], [%old, %loop] + %squared = mul i32 %cmp, %cmp + %old = cmpxchg i32* %ptr, i32 %cmp, i32 %squared ; yields {i32} + %success = icmp eq i32 %cmp, %old + br i1 %success, label %done, label %loop + + done: + ... + +.. _i_atomicrmw: + +'``atomicrmw``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + atomicrmw [volatile] * , [singlethread] ; yields {ty} + +Overview: +""""""""" + +The '``atomicrmw``' instruction is used to atomically modify memory. + +Arguments: +"""""""""" + +There are three arguments to the '``atomicrmw``' instruction: an +operation to apply, an address whose value to modify, an argument to the +operation. The operation must be one of the following keywords: + +- xchg +- add +- sub +- and +- nand +- or +- xor +- max +- min +- umax +- umin + +The type of '' must be an integer type whose bit width is a power +of two greater than or equal to eight and less than or equal to a +target-specific size limit. The type of the '````' operand must +be a pointer to that type. If the ``atomicrmw`` is marked as +``volatile``, then the optimizer is not allowed to modify the number or +order of execution of this ``atomicrmw`` with other :ref:`volatile +operations `. + +Semantics: +"""""""""" + +The contents of memory at the location specified by the '````' +operand are atomically read, modified, and written back. The original +value at the location is returned. The modification is specified by the +operation argument: + +- xchg: ``*ptr = val`` +- add: ``*ptr = *ptr + val`` +- sub: ``*ptr = *ptr - val`` +- and: ``*ptr = *ptr & val`` +- nand: ``*ptr = ~(*ptr & val)`` +- or: ``*ptr = *ptr | val`` +- xor: ``*ptr = *ptr ^ val`` +- max: ``*ptr = *ptr > val ? *ptr : val`` (using a signed comparison) +- min: ``*ptr = *ptr < val ? *ptr : val`` (using a signed comparison) +- umax: ``*ptr = *ptr > val ? *ptr : val`` (using an unsigned + comparison) +- umin: ``*ptr = *ptr < val ? *ptr : val`` (using an unsigned + comparison) + +Example: +"""""""" + +.. code-block:: llvm + + %old = atomicrmw add i32* %ptr, i32 1 acquire ; yields {i32} + +.. _i_getelementptr: + +'``getelementptr``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = getelementptr * {, }* + = getelementptr inbounds * {, }* + = getelementptr ptrval, idx + +Overview: +""""""""" + +The '``getelementptr``' instruction is used to get the address of a +subelement of an :ref:`aggregate ` data structure. It performs +address calculation only and does not access memory. + +Arguments: +"""""""""" + +The first argument is always a pointer or a vector of pointers, and +forms the basis of the calculation. The remaining arguments are indices +that indicate which of the elements of the aggregate object are indexed. +The interpretation of each index is dependent on the type being indexed +into. The first index always indexes the pointer value given as the +first argument, the second index indexes a value of the type pointed to +(not necessarily the value directly pointed to, since the first index +can be non-zero), etc. The first type indexed into must be a pointer +value, subsequent types can be arrays, vectors, and structs. Note that +subsequent types being indexed into can never be pointers, since that +would require loading the pointer before continuing calculation. + +The type of each index argument depends on the type it is indexing into. +When indexing into a (optionally packed) structure, only ``i32`` integer +**constants** are allowed (when using a vector of indices they must all +be the **same** ``i32`` integer constant). When indexing into an array, +pointer or vector, integers of any width are allowed, and they are not +required to be constant. These integers are treated as signed values +where relevant. + +For example, let's consider a C code fragment and how it gets compiled +to LLVM: + +.. code-block:: c + + struct RT { + char A; + int B[10][20]; + char C; + }; + struct ST { + int X; + double Y; + struct RT Z; + }; + + int *foo(struct ST *s) { + return &s[1].Z.B[5][13]; + } + +The LLVM code generated by Clang is: + +.. code-block:: llvm + + %struct.RT = type { i8, [10 x [20 x i32]], i8 } + %struct.ST = type { i32, double, %struct.RT } + + define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp { + entry: + %arrayidx = getelementptr inbounds %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13 + ret i32* %arrayidx + } + +Semantics: +"""""""""" + +In the example above, the first index is indexing into the +'``%struct.ST*``' type, which is a pointer, yielding a '``%struct.ST``' += '``{ i32, double, %struct.RT }``' type, a structure. The second index +indexes into the third element of the structure, yielding a +'``%struct.RT``' = '``{ i8 , [10 x [20 x i32]], i8 }``' type, another +structure. The third index indexes into the second element of the +structure, yielding a '``[10 x [20 x i32]]``' type, an array. The two +dimensions of the array are subscripted into, yielding an '``i32``' +type. The '``getelementptr``' instruction returns a pointer to this +element, thus computing a value of '``i32*``' type. + +Note that it is perfectly legal to index partially through a structure, +returning a pointer to an inner element. Because of this, the LLVM code +for the given testcase is equivalent to: + +.. code-block:: llvm + + define i32* @foo(%struct.ST* %s) { + %t1 = getelementptr %struct.ST* %s, i32 1 ; yields %struct.ST*:%t1 + %t2 = getelementptr %struct.ST* %t1, i32 0, i32 2 ; yields %struct.RT*:%t2 + %t3 = getelementptr %struct.RT* %t2, i32 0, i32 1 ; yields [10 x [20 x i32]]*:%t3 + %t4 = getelementptr [10 x [20 x i32]]* %t3, i32 0, i32 5 ; yields [20 x i32]*:%t4 + %t5 = getelementptr [20 x i32]* %t4, i32 0, i32 13 ; yields i32*:%t5 + ret i32* %t5 + } + +If the ``inbounds`` keyword is present, the result value of the +``getelementptr`` is a :ref:`poison value ` if the base +pointer is not an *in bounds* address of an allocated object, or if any +of the addresses that would be formed by successive addition of the +offsets implied by the indices to the base address with infinitely +precise signed arithmetic are not an *in bounds* address of that +allocated object. The *in bounds* addresses for an allocated object are +all the addresses that point into the object, plus the address one byte +past the end. In cases where the base is a vector of pointers the +``inbounds`` keyword applies to each of the computations element-wise. + +If the ``inbounds`` keyword is not present, the offsets are added to the +base address with silently-wrapping two's complement arithmetic. If the +offsets have a different width from the pointer, they are sign-extended +or truncated to the width of the pointer. The result value of the +``getelementptr`` may be outside the object pointed to by the base +pointer. The result value may not necessarily be used to access memory +though, even if it happens to point into allocated storage. See the +:ref:`Pointer Aliasing Rules ` section for more +information. + +The getelementptr instruction is often confusing. For some more insight +into how it works, see :doc:`the getelementptr FAQ `. + +Example: +"""""""" + +.. code-block:: llvm + + ; yields [12 x i8]*:aptr + %aptr = getelementptr {i32, [12 x i8]}* %saptr, i64 0, i32 1 + ; yields i8*:vptr + %vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 1, i32 1 + ; yields i8*:eptr + %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1 + ; yields i32*:iptr + %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0 + +In cases where the pointer argument is a vector of pointers, each index +must be a vector with the same number of elements. For example: + +.. code-block:: llvm + + %A = getelementptr <4 x i8*> %ptrs, <4 x i64> %offsets, + +Conversion Operations +--------------------- + +The instructions in this category are the conversion instructions +(casting) which all take a single operand and a type. They perform +various bit conversions on the operand. + +'``trunc .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = trunc to ; yields ty2 + +Overview: +""""""""" + +The '``trunc``' instruction truncates its operand to the type ``ty2``. + +Arguments: +"""""""""" + +The '``trunc``' instruction takes a value to trunc, and a type to trunc +it to. Both types must be of :ref:`integer ` types, or vectors +of the same number of integers. The bit size of the ``value`` must be +larger than the bit size of the destination type, ``ty2``. Equal sized +types are not allowed. + +Semantics: +"""""""""" + +The '``trunc``' instruction truncates the high order bits in ``value`` +and converts the remaining bits to ``ty2``. Since the source size must +be larger than the destination size, ``trunc`` cannot be a *no-op cast*. +It will always truncate bits. + +Example: +"""""""" + +.. code-block:: llvm + + %X = trunc i32 257 to i8 ; yields i8:1 + %Y = trunc i32 123 to i1 ; yields i1:true + %Z = trunc i32 122 to i1 ; yields i1:false + %W = trunc <2 x i16> to <2 x i8> ; yields + +'``zext .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = zext to ; yields ty2 + +Overview: +""""""""" + +The '``zext``' instruction zero extends its operand to type ``ty2``. + +Arguments: +"""""""""" + +The '``zext``' instruction takes a value to cast, and a type to cast it +to. Both types must be of :ref:`integer ` types, or vectors of +the same number of integers. The bit size of the ``value`` must be +smaller than the bit size of the destination type, ``ty2``. + +Semantics: +"""""""""" + +The ``zext`` fills the high order bits of the ``value`` with zero bits +until it reaches the size of the destination type, ``ty2``. + +When zero extending from i1, the result will always be either 0 or 1. + +Example: +"""""""" + +.. code-block:: llvm + + %X = zext i32 257 to i64 ; yields i64:257 + %Y = zext i1 true to i32 ; yields i32:1 + %Z = zext <2 x i16> to <2 x i32> ; yields + +'``sext .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = sext to ; yields ty2 + +Overview: +""""""""" + +The '``sext``' sign extends ``value`` to the type ``ty2``. + +Arguments: +"""""""""" + +The '``sext``' instruction takes a value to cast, and a type to cast it +to. Both types must be of :ref:`integer ` types, or vectors of +the same number of integers. The bit size of the ``value`` must be +smaller than the bit size of the destination type, ``ty2``. + +Semantics: +"""""""""" + +The '``sext``' instruction performs a sign extension by copying the sign +bit (highest order bit) of the ``value`` until it reaches the bit size +of the type ``ty2``. + +When sign extending from i1, the extension always results in -1 or 0. + +Example: +"""""""" + +.. code-block:: llvm + + %X = sext i8 -1 to i16 ; yields i16 :65535 + %Y = sext i1 true to i32 ; yields i32:-1 + %Z = sext <2 x i16> to <2 x i32> ; yields + +'``fptrunc .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fptrunc to ; yields ty2 + +Overview: +""""""""" + +The '``fptrunc``' instruction truncates ``value`` to type ``ty2``. + +Arguments: +"""""""""" + +The '``fptrunc``' instruction takes a :ref:`floating point ` +value to cast and a :ref:`floating point ` type to cast it to. +The size of ``value`` must be larger than the size of ``ty2``. This +implies that ``fptrunc`` cannot be used to make a *no-op cast*. + +Semantics: +"""""""""" + +The '``fptrunc``' instruction truncates a ``value`` from a larger +:ref:`floating point ` type to a smaller :ref:`floating +point ` type. If the value cannot fit within the +destination type, ``ty2``, then the results are undefined. + +Example: +"""""""" + +.. code-block:: llvm + + %X = fptrunc double 123.0 to float ; yields float:123.0 + %Y = fptrunc double 1.0E+300 to float ; yields undefined + +'``fpext .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fpext to ; yields ty2 + +Overview: +""""""""" + +The '``fpext``' extends a floating point ``value`` to a larger floating +point value. + +Arguments: +"""""""""" + +The '``fpext``' instruction takes a :ref:`floating point ` +``value`` to cast, and a :ref:`floating point ` type to cast it +to. The source type must be smaller than the destination type. + +Semantics: +"""""""""" + +The '``fpext``' instruction extends the ``value`` from a smaller +:ref:`floating point ` type to a larger :ref:`floating +point ` type. The ``fpext`` cannot be used to make a +*no-op cast* because it always changes bits. Use ``bitcast`` to make a +*no-op cast* for a floating point cast. + +Example: +"""""""" + +.. code-block:: llvm + + %X = fpext float 3.125 to double ; yields double:3.125000e+00 + %Y = fpext double %X to fp128 ; yields fp128:0xL00000000000000004000900000000000 + +'``fptoui .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fptoui to ; yields ty2 + +Overview: +""""""""" + +The '``fptoui``' converts a floating point ``value`` to its unsigned +integer equivalent of type ``ty2``. + +Arguments: +"""""""""" + +The '``fptoui``' instruction takes a value to cast, which must be a +scalar or vector :ref:`floating point ` value, and a type to +cast it to ``ty2``, which must be an :ref:`integer ` type. If +``ty`` is a vector floating point type, ``ty2`` must be a vector integer +type with the same number of elements as ``ty`` + +Semantics: +"""""""""" + +The '``fptoui``' instruction converts its :ref:`floating +point ` operand into the nearest (rounding towards zero) +unsigned integer value. If the value cannot fit in ``ty2``, the results +are undefined. + +Example: +"""""""" + +.. code-block:: llvm + + %X = fptoui double 123.0 to i32 ; yields i32:123 + %Y = fptoui float 1.0E+300 to i1 ; yields undefined:1 + %Z = fptoui float 1.04E+17 to i8 ; yields undefined:1 + +'``fptosi .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fptosi to ; yields ty2 + +Overview: +""""""""" + +The '``fptosi``' instruction converts :ref:`floating point ` +``value`` to type ``ty2``. + +Arguments: +"""""""""" + +The '``fptosi``' instruction takes a value to cast, which must be a +scalar or vector :ref:`floating point ` value, and a type to +cast it to ``ty2``, which must be an :ref:`integer ` type. If +``ty`` is a vector floating point type, ``ty2`` must be a vector integer +type with the same number of elements as ``ty`` + +Semantics: +"""""""""" + +The '``fptosi``' instruction converts its :ref:`floating +point ` operand into the nearest (rounding towards zero) +signed integer value. If the value cannot fit in ``ty2``, the results +are undefined. + +Example: +"""""""" + +.. code-block:: llvm + + %X = fptosi double -123.0 to i32 ; yields i32:-123 + %Y = fptosi float 1.0E-247 to i1 ; yields undefined:1 + %Z = fptosi float 1.04E+17 to i8 ; yields undefined:1 + +'``uitofp .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = uitofp to ; yields ty2 + +Overview: +""""""""" + +The '``uitofp``' instruction regards ``value`` as an unsigned integer +and converts that value to the ``ty2`` type. + +Arguments: +"""""""""" + +The '``uitofp``' instruction takes a value to cast, which must be a +scalar or vector :ref:`integer ` value, and a type to cast it to +``ty2``, which must be an :ref:`floating point ` type. If +``ty`` is a vector integer type, ``ty2`` must be a vector floating point +type with the same number of elements as ``ty`` + +Semantics: +"""""""""" + +The '``uitofp``' instruction interprets its operand as an unsigned +integer quantity and converts it to the corresponding floating point +value. If the value cannot fit in the floating point value, the results +are undefined. + +Example: +"""""""" + +.. code-block:: llvm + + %X = uitofp i32 257 to float ; yields float:257.0 + %Y = uitofp i8 -1 to double ; yields double:255.0 + +'``sitofp .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = sitofp to ; yields ty2 + +Overview: +""""""""" + +The '``sitofp``' instruction regards ``value`` as a signed integer and +converts that value to the ``ty2`` type. + +Arguments: +"""""""""" + +The '``sitofp``' instruction takes a value to cast, which must be a +scalar or vector :ref:`integer ` value, and a type to cast it to +``ty2``, which must be an :ref:`floating point ` type. If +``ty`` is a vector integer type, ``ty2`` must be a vector floating point +type with the same number of elements as ``ty`` + +Semantics: +"""""""""" + +The '``sitofp``' instruction interprets its operand as a signed integer +quantity and converts it to the corresponding floating point value. If +the value cannot fit in the floating point value, the results are +undefined. + +Example: +"""""""" + +.. code-block:: llvm + + %X = sitofp i32 257 to float ; yields float:257.0 + %Y = sitofp i8 -1 to double ; yields double:-1.0 + +.. _i_ptrtoint: + +'``ptrtoint .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = ptrtoint to ; yields ty2 + +Overview: +""""""""" + +The '``ptrtoint``' instruction converts the pointer or a vector of +pointers ``value`` to the integer (or vector of integers) type ``ty2``. + +Arguments: +"""""""""" + +The '``ptrtoint``' instruction takes a ``value`` to cast, which must be +a a value of type :ref:`pointer ` or a vector of pointers, and a +type to cast it to ``ty2``, which must be an :ref:`integer ` or +a vector of integers type. + +Semantics: +"""""""""" + +The '``ptrtoint``' instruction converts ``value`` to integer type +``ty2`` by interpreting the pointer value as an integer and either +truncating or zero extending that value to the size of the integer type. +If ``value`` is smaller than ``ty2`` then a zero extension is done. If +``value`` is larger than ``ty2`` then a truncation is done. If they are +the same size, then nothing is done (*no-op cast*) other than a type +change. + +Example: +"""""""" + +.. code-block:: llvm + + %X = ptrtoint i32* %P to i8 ; yields truncation on 32-bit architecture + %Y = ptrtoint i32* %P to i64 ; yields zero extension on 32-bit architecture + %Z = ptrtoint <4 x i32*> %P to <4 x i64>; yields vector zero extension for a vector of addresses on 32-bit architecture + +.. _i_inttoptr: + +'``inttoptr .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = inttoptr to ; yields ty2 + +Overview: +""""""""" + +The '``inttoptr``' instruction converts an integer ``value`` to a +pointer type, ``ty2``. + +Arguments: +"""""""""" + +The '``inttoptr``' instruction takes an :ref:`integer ` value to +cast, and a type to cast it to, which must be a :ref:`pointer ` +type. + +Semantics: +"""""""""" + +The '``inttoptr``' instruction converts ``value`` to type ``ty2`` by +applying either a zero extension or a truncation depending on the size +of the integer ``value``. If ``value`` is larger than the size of a +pointer then a truncation is done. If ``value`` is smaller than the size +of a pointer then a zero extension is done. If they are the same size, +nothing is done (*no-op cast*). + +Example: +"""""""" + +.. code-block:: llvm + + %X = inttoptr i32 255 to i32* ; yields zero extension on 64-bit architecture + %Y = inttoptr i32 255 to i32* ; yields no-op on 32-bit architecture + %Z = inttoptr i64 0 to i32* ; yields truncation on 32-bit architecture + %Z = inttoptr <4 x i32> %G to <4 x i8*>; yields truncation of vector G to four pointers + +.. _i_bitcast: + +'``bitcast .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = bitcast to ; yields ty2 + +Overview: +""""""""" + +The '``bitcast``' instruction converts ``value`` to type ``ty2`` without +changing any bits. + +Arguments: +"""""""""" + +The '``bitcast``' instruction takes a value to cast, which must be a +non-aggregate first class value, and a type to cast it to, which must +also be a non-aggregate :ref:`first class ` type. The +bit sizes of ``value`` and the destination type, ``ty2``, must be +identical. If the source type is a pointer, the destination type must +also be a pointer of the same size. This instruction supports bitwise +conversion of vectors to integers and to vectors of other types (as +long as they have the same size). + +Semantics: +"""""""""" + +The '``bitcast``' instruction converts ``value`` to type ``ty2``. It +is always a *no-op cast* because no bits change with this +conversion. The conversion is done as if the ``value`` had been stored +to memory and read back as type ``ty2``. Pointer (or vector of +pointers) types may only be converted to other pointer (or vector of +pointers) types with the same address space through this instruction. +To convert pointers to other types, use the :ref:`inttoptr ` +or :ref:`ptrtoint ` instructions first. + +Example: +"""""""" + +.. code-block:: llvm + + %X = bitcast i8 255 to i8 ; yields i8 :-1 + %Y = bitcast i32* %x to sint* ; yields sint*:%x + %Z = bitcast <2 x int> %V to i64; ; yields i64: %V + %Z = bitcast <2 x i32*> %V to <2 x i64*> ; yields <2 x i64*> + +.. _i_addrspacecast: + +'``addrspacecast .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = addrspacecast to ; yields pty2 + +Overview: +""""""""" + +The '``addrspacecast``' instruction converts ``ptrval`` from ``pty`` in +address space ``n`` to type ``pty2`` in address space ``m``. + +Arguments: +"""""""""" + +The '``addrspacecast``' instruction takes a pointer or vector of pointer value +to cast and a pointer type to cast it to, which must have a different +address space. + +Semantics: +"""""""""" + +The '``addrspacecast``' instruction converts the pointer value +``ptrval`` to type ``pty2``. It can be a *no-op cast* or a complex +value modification, depending on the target and the address space +pair. Pointer conversions within the same address space must be +performed with the ``bitcast`` instruction. Note that if the address space +conversion is legal then both result and operand refer to the same memory +location. + +Example: +"""""""" + +.. code-block:: llvm + + %X = addrspacecast i32* %x to i32 addrspace(1)* ; yields i32 addrspace(1)*:%x + %Y = addrspacecast i32 addrspace(1)* %y to i64 addrspace(2)* ; yields i64 addrspace(2)*:%y + %Z = addrspacecast <4 x i32*> %z to <4 x float addrspace(3)*> ; yields <4 x float addrspace(3)*>:%z + +.. _otherops: + +Other Operations +---------------- + +The instructions in this category are the "miscellaneous" instructions, +which defy better classification. + +.. _i_icmp: + +'``icmp``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = icmp , ; yields {i1} or {}:result + +Overview: +""""""""" + +The '``icmp``' instruction returns a boolean value or a vector of +boolean values based on comparison of its two integer, integer vector, +pointer, or pointer vector operands. + +Arguments: +"""""""""" + +The '``icmp``' instruction takes three operands. The first operand is +the condition code indicating the kind of comparison to perform. It is +not a value, just a keyword. The possible condition code are: + +#. ``eq``: equal +#. ``ne``: not equal +#. ``ugt``: unsigned greater than +#. ``uge``: unsigned greater or equal +#. ``ult``: unsigned less than +#. ``ule``: unsigned less or equal +#. ``sgt``: signed greater than +#. ``sge``: signed greater or equal +#. ``slt``: signed less than +#. ``sle``: signed less or equal + +The remaining two arguments must be :ref:`integer ` or +:ref:`pointer ` or integer :ref:`vector ` typed. They +must also be identical types. + +Semantics: +"""""""""" + +The '``icmp``' compares ``op1`` and ``op2`` according to the condition +code given as ``cond``. The comparison performed always yields either an +:ref:`i1 ` or vector of ``i1`` result, as follows: + +#. ``eq``: yields ``true`` if the operands are equal, ``false`` + otherwise. No sign interpretation is necessary or performed. +#. ``ne``: yields ``true`` if the operands are unequal, ``false`` + otherwise. No sign interpretation is necessary or performed. +#. ``ugt``: interprets the operands as unsigned values and yields + ``true`` if ``op1`` is greater than ``op2``. +#. ``uge``: interprets the operands as unsigned values and yields + ``true`` if ``op1`` is greater than or equal to ``op2``. +#. ``ult``: interprets the operands as unsigned values and yields + ``true`` if ``op1`` is less than ``op2``. +#. ``ule``: interprets the operands as unsigned values and yields + ``true`` if ``op1`` is less than or equal to ``op2``. +#. ``sgt``: interprets the operands as signed values and yields ``true`` + if ``op1`` is greater than ``op2``. +#. ``sge``: interprets the operands as signed values and yields ``true`` + if ``op1`` is greater than or equal to ``op2``. +#. ``slt``: interprets the operands as signed values and yields ``true`` + if ``op1`` is less than ``op2``. +#. ``sle``: interprets the operands as signed values and yields ``true`` + if ``op1`` is less than or equal to ``op2``. + +If the operands are :ref:`pointer ` typed, the pointer values +are compared as if they were integers. + +If the operands are integer vectors, then they are compared element by +element. The result is an ``i1`` vector with the same number of elements +as the values being compared. Otherwise, the result is an ``i1``. + +Example: +"""""""" + +.. code-block:: llvm + + = icmp eq i32 4, 5 ; yields: result=false + = icmp ne float* %X, %X ; yields: result=false + = icmp ult i16 4, 5 ; yields: result=true + = icmp sgt i16 4, 5 ; yields: result=false + = icmp ule i16 -4, 5 ; yields: result=false + = icmp sge i16 4, 5 ; yields: result=false + +Note that the code generator does not yet support vector types with the +``icmp`` instruction. + +.. _i_fcmp: + +'``fcmp``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = fcmp , ; yields {i1} or {}:result + +Overview: +""""""""" + +The '``fcmp``' instruction returns a boolean value or vector of boolean +values based on comparison of its operands. + +If the operands are floating point scalars, then the result type is a +boolean (:ref:`i1 `). + +If the operands are floating point vectors, then the result type is a +vector of boolean with the same number of elements as the operands being +compared. + +Arguments: +"""""""""" + +The '``fcmp``' instruction takes three operands. The first operand is +the condition code indicating the kind of comparison to perform. It is +not a value, just a keyword. The possible condition code are: + +#. ``false``: no comparison, always returns false +#. ``oeq``: ordered and equal +#. ``ogt``: ordered and greater than +#. ``oge``: ordered and greater than or equal +#. ``olt``: ordered and less than +#. ``ole``: ordered and less than or equal +#. ``one``: ordered and not equal +#. ``ord``: ordered (no nans) +#. ``ueq``: unordered or equal +#. ``ugt``: unordered or greater than +#. ``uge``: unordered or greater than or equal +#. ``ult``: unordered or less than +#. ``ule``: unordered or less than or equal +#. ``une``: unordered or not equal +#. ``uno``: unordered (either nans) +#. ``true``: no comparison, always returns true + +*Ordered* means that neither operand is a QNAN while *unordered* means +that either operand may be a QNAN. + +Each of ``val1`` and ``val2`` arguments must be either a :ref:`floating +point ` type or a :ref:`vector ` of floating point +type. They must have identical types. + +Semantics: +"""""""""" + +The '``fcmp``' instruction compares ``op1`` and ``op2`` according to the +condition code given as ``cond``. If the operands are vectors, then the +vectors are compared element by element. Each comparison performed +always yields an :ref:`i1 ` result, as follows: + +#. ``false``: always yields ``false``, regardless of operands. +#. ``oeq``: yields ``true`` if both operands are not a QNAN and ``op1`` + is equal to ``op2``. +#. ``ogt``: yields ``true`` if both operands are not a QNAN and ``op1`` + is greater than ``op2``. +#. ``oge``: yields ``true`` if both operands are not a QNAN and ``op1`` + is greater than or equal to ``op2``. +#. ``olt``: yields ``true`` if both operands are not a QNAN and ``op1`` + is less than ``op2``. +#. ``ole``: yields ``true`` if both operands are not a QNAN and ``op1`` + is less than or equal to ``op2``. +#. ``one``: yields ``true`` if both operands are not a QNAN and ``op1`` + is not equal to ``op2``. +#. ``ord``: yields ``true`` if both operands are not a QNAN. +#. ``ueq``: yields ``true`` if either operand is a QNAN or ``op1`` is + equal to ``op2``. +#. ``ugt``: yields ``true`` if either operand is a QNAN or ``op1`` is + greater than ``op2``. +#. ``uge``: yields ``true`` if either operand is a QNAN or ``op1`` is + greater than or equal to ``op2``. +#. ``ult``: yields ``true`` if either operand is a QNAN or ``op1`` is + less than ``op2``. +#. ``ule``: yields ``true`` if either operand is a QNAN or ``op1`` is + less than or equal to ``op2``. +#. ``une``: yields ``true`` if either operand is a QNAN or ``op1`` is + not equal to ``op2``. +#. ``uno``: yields ``true`` if either operand is a QNAN. +#. ``true``: always yields ``true``, regardless of operands. + +Example: +"""""""" + +.. code-block:: llvm + + = fcmp oeq float 4.0, 5.0 ; yields: result=false + = fcmp one float 4.0, 5.0 ; yields: result=true + = fcmp olt float 4.0, 5.0 ; yields: result=true + = fcmp ueq double 1.0, 2.0 ; yields: result=false + +Note that the code generator does not yet support vector types with the +``fcmp`` instruction. + +.. _i_phi: + +'``phi``' Instruction +^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = phi [ , ], ... + +Overview: +""""""""" + +The '``phi``' instruction is used to implement the φ node in the SSA +graph representing the function. + +Arguments: +"""""""""" + +The type of the incoming values is specified with the first type field. +After this, the '``phi``' instruction takes a list of pairs as +arguments, with one pair for each predecessor basic block of the current +block. Only values of :ref:`first class ` type may be used as +the value arguments to the PHI node. Only labels may be used as the +label arguments. + +There must be no non-phi instructions between the start of a basic block +and the PHI instructions: i.e. PHI instructions must be first in a basic +block. + +For the purposes of the SSA form, the use of each incoming value is +deemed to occur on the edge from the corresponding predecessor block to +the current block (but after any definition of an '``invoke``' +instruction's return value on the same edge). + +Semantics: +"""""""""" + +At runtime, the '``phi``' instruction logically takes on the value +specified by the pair corresponding to the predecessor basic block that +executed just prior to the current block. + +Example: +"""""""" + +.. code-block:: llvm + + Loop: ; Infinite loop that counts from 0 on up... + %indvar = phi i32 [ 0, %LoopHeader ], [ %nextindvar, %Loop ] + %nextindvar = add i32 %indvar, 1 + br label %Loop + +.. _i_select: + +'``select``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = select selty , , ; yields ty + + selty is either i1 or {} + +Overview: +""""""""" + +The '``select``' instruction is used to choose one value based on a +condition, without branching. + +Arguments: +"""""""""" + +The '``select``' instruction requires an 'i1' value or a vector of 'i1' +values indicating the condition, and two values of the same :ref:`first +class ` type. If the val1/val2 are vectors and the +condition is a scalar, then entire vectors are selected, not individual +elements. + +Semantics: +"""""""""" + +If the condition is an i1 and it evaluates to 1, the instruction returns +the first value argument; otherwise, it returns the second value +argument. + +If the condition is a vector of i1, then the value arguments must be +vectors of the same size, and the selection is done element by element. + +Example: +"""""""" + +.. code-block:: llvm + + %X = select i1 true, i8 17, i8 42 ; yields i8:17 + +.. _i_call: + +'``call``' Instruction +^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = [tail] call [cconv] [ret attrs] [*] () [fn attrs] + +Overview: +""""""""" + +The '``call``' instruction represents a simple function call. + +Arguments: +"""""""""" + +This instruction requires several arguments: + +#. The optional "tail" marker indicates that the callee function does + not access any allocas or varargs in the caller. Note that calls may + be marked "tail" even if they do not occur before a + :ref:`ret ` instruction. If the "tail" marker is present, the + function call is eligible for tail call optimization, but `might not + in fact be optimized into a jump `_. + The code generator may optimize calls marked "tail" with either 1) + automatic `sibling call + optimization `_ when the caller and + callee have matching signatures, or 2) forced tail call optimization + when the following extra requirements are met: + + - Caller and callee both have the calling convention ``fastcc``. + - The call is in tail position (ret immediately follows call and ret + uses value of call or is void). + - Option ``-tailcallopt`` is enabled, or + ``llvm::GuaranteedTailCallOpt`` is ``true``. + - `Platform specific constraints are + met. `_ + +#. The optional "cconv" marker indicates which :ref:`calling + convention ` the call should use. If none is + specified, the call defaults to using C calling conventions. The + calling convention of the call must match the calling convention of + the target function, or else the behavior is undefined. +#. The optional :ref:`Parameter Attributes ` list for return + values. Only '``zeroext``', '``signext``', and '``inreg``' attributes + are valid here. +#. '``ty``': the type of the call instruction itself which is also the + type of the return value. Functions that return no value are marked + ``void``. +#. '``fnty``': shall be the signature of the pointer to function value + being invoked. The argument types must match the types implied by + this signature. This type can be omitted if the function is not + varargs and if the function type does not return a pointer to a + function. +#. '``fnptrval``': An LLVM value containing a pointer to a function to + be invoked. In most cases, this is a direct function invocation, but + indirect ``call``'s are just as possible, calling an arbitrary pointer + to function value. +#. '``function args``': argument list whose types match the function + signature argument types and parameter attributes. All arguments must + be of :ref:`first class ` type. If the function signature + indicates the function accepts a variable number of arguments, the + extra arguments can be specified. +#. The optional :ref:`function attributes ` list. Only + '``noreturn``', '``nounwind``', '``readonly``' and '``readnone``' + attributes are valid here. + +Semantics: +"""""""""" + +The '``call``' instruction is used to cause control flow to transfer to +a specified function, with its incoming arguments bound to the specified +values. Upon a '``ret``' instruction in the called function, control +flow continues with the instruction after the function call, and the +return value of the function is bound to the result argument. + +Example: +"""""""" + +.. code-block:: llvm + + %retval = call i32 @test(i32 %argc) + call i32 (i8*, ...)* @printf(i8* %msg, i32 12, i8 42) ; yields i32 + %X = tail call i32 @foo() ; yields i32 + %Y = tail call fastcc i32 @foo() ; yields i32 + call void %foo(i8 97 signext) + + %struct.A = type { i32, i8 } + %r = call %struct.A @foo() ; yields { 32, i8 } + %gr = extractvalue %struct.A %r, 0 ; yields i32 + %gr1 = extractvalue %struct.A %r, 1 ; yields i8 + %Z = call void @foo() noreturn ; indicates that %foo never returns normally + %ZZ = call zeroext i32 @bar() ; Return value is %zero extended + +llvm treats calls to some functions with names and arguments that match +the standard C99 library as being the C99 library functions, and may +perform optimizations or generate code for them under that assumption. +This is something we'd like to change in the future to provide better +support for freestanding environments and non-C-based languages. + +.. _i_va_arg: + +'``va_arg``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = va_arg , + +Overview: +""""""""" + +The '``va_arg``' instruction is used to access arguments passed through +the "variable argument" area of a function call. It is used to implement +the ``va_arg`` macro in C. + +Arguments: +"""""""""" + +This instruction takes a ``va_list*`` value and the type of the +argument. It returns a value of the specified argument type and +increments the ``va_list`` to point to the next argument. The actual +type of ``va_list`` is target specific. + +Semantics: +"""""""""" + +The '``va_arg``' instruction loads an argument of the specified type +from the specified ``va_list`` and causes the ``va_list`` to point to +the next argument. For more information, see the variable argument +handling :ref:`Intrinsic Functions `. + +It is legal for this instruction to be called in a function which does +not take a variable number of arguments, for example, the ``vfprintf`` +function. + +``va_arg`` is an LLVM instruction instead of an :ref:`intrinsic +function ` because it takes a type as an argument. + +Example: +"""""""" + +See the :ref:`variable argument processing ` section. + +Note that the code generator does not yet fully support va\_arg on many +targets. Also, it does not currently support va\_arg with aggregate +types on any target. + +.. _i_landingpad: + +'``landingpad``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = landingpad personality + + = landingpad personality cleanup * + + := catch + := filter + +Overview: +""""""""" + +The '``landingpad``' instruction is used by `LLVM's exception handling +system `_ to specify that a basic block +is a landing pad --- one where the exception lands, and corresponds to the +code found in the ``catch`` portion of a ``try``/``catch`` sequence. It +defines values supplied by the personality function (``pers_fn``) upon +re-entry to the function. The ``resultval`` has the type ``resultty``. + +Arguments: +"""""""""" + +This instruction takes a ``pers_fn`` value. This is the personality +function associated with the unwinding mechanism. The optional +``cleanup`` flag indicates that the landing pad block is a cleanup. + +A ``clause`` begins with the clause type --- ``catch`` or ``filter`` --- and +contains the global variable representing the "type" that may be caught +or filtered respectively. Unlike the ``catch`` clause, the ``filter`` +clause takes an array constant as its argument. Use +"``[0 x i8**] undef``" for a filter which cannot throw. The +'``landingpad``' instruction must contain *at least* one ``clause`` or +the ``cleanup`` flag. + +Semantics: +"""""""""" + +The '``landingpad``' instruction defines the values which are set by the +personality function (``pers_fn``) upon re-entry to the function, and +therefore the "result type" of the ``landingpad`` instruction. As with +calling conventions, how the personality function results are +represented in LLVM IR is target specific. + +The clauses are applied in order from top to bottom. If two +``landingpad`` instructions are merged together through inlining, the +clauses from the calling function are appended to the list of clauses. +When the call stack is being unwound due to an exception being thrown, +the exception is compared against each ``clause`` in turn. If it doesn't +match any of the clauses, and the ``cleanup`` flag is not set, then +unwinding continues further up the call stack. + +The ``landingpad`` instruction has several restrictions: + +- A landing pad block is a basic block which is the unwind destination + of an '``invoke``' instruction. +- A landing pad block must have a '``landingpad``' instruction as its + first non-PHI instruction. +- There can be only one '``landingpad``' instruction within the landing + pad block. +- A basic block that is not a landing pad block may not include a + '``landingpad``' instruction. +- All '``landingpad``' instructions in a function must have the same + personality function. + +Example: +"""""""" + +.. code-block:: llvm + + ;; A landing pad which can catch an integer. + %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + catch i8** @_ZTIi + ;; A landing pad that is a cleanup. + %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + cleanup + ;; A landing pad which can catch an integer and can only throw a double. + %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + catch i8** @_ZTIi + filter [1 x i8**] [@_ZTId] + +.. _intrinsics: + +Intrinsic Functions +=================== + +LLVM supports the notion of an "intrinsic function". These functions +have well known names and semantics and are required to follow certain +restrictions. Overall, these intrinsics represent an extension mechanism +for the LLVM language that does not require changing all of the +transformations in LLVM when adding to the language (or the bitcode +reader/writer, the parser, etc...). + +Intrinsic function names must all start with an "``llvm.``" prefix. This +prefix is reserved in LLVM for intrinsic names; thus, function names may +not begin with this prefix. Intrinsic functions must always be external +functions: you cannot define the body of intrinsic functions. Intrinsic +functions may only be used in call or invoke instructions: it is illegal +to take the address of an intrinsic function. Additionally, because +intrinsic functions are part of the LLVM language, it is required if any +are added that they be documented here. + +Some intrinsic functions can be overloaded, i.e., the intrinsic +represents a family of functions that perform the same operation but on +different data types. Because LLVM can represent over 8 million +different integer types, overloading is used commonly to allow an +intrinsic function to operate on any integer type. One or more of the +argument types or the result type can be overloaded to accept any +integer type. Argument types may also be defined as exactly matching a +previous argument's type or the result type. This allows an intrinsic +function which accepts multiple arguments, but needs all of them to be +of the same type, to only be overloaded with respect to a single +argument or the result. + +Overloaded intrinsics will have the names of its overloaded argument +types encoded into its function name, each preceded by a period. Only +those types which are overloaded result in a name suffix. Arguments +whose type is matched against another type do not. For example, the +``llvm.ctpop`` function can take an integer of any width and returns an +integer of exactly the same integer width. This leads to a family of +functions such as ``i8 @llvm.ctpop.i8(i8 %val)`` and +``i29 @llvm.ctpop.i29(i29 %val)``. Only one type, the return type, is +overloaded, and only one type suffix is required. Because the argument's +type is matched against the return type, it does not require its own +name suffix. + +To learn how to add an intrinsic function, please see the `Extending +LLVM Guide `_. + +.. _int_varargs: + +Variable Argument Handling Intrinsics +------------------------------------- + +Variable argument support is defined in LLVM with the +:ref:`va_arg ` instruction and these three intrinsic +functions. These functions are related to the similarly named macros +defined in the ```` header file. + +All of these functions operate on arguments that use a target-specific +value type "``va_list``". The LLVM assembly language reference manual +does not define what this type is, so all transformations should be +prepared to handle these functions regardless of the type used. + +This example shows how the :ref:`va_arg ` instruction and the +variable argument handling intrinsic functions are used. + +.. code-block:: llvm + + define i32 @test(i32 %X, ...) { + ; Initialize variable argument processing + %ap = alloca i8* + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + ; Read a single integer argument + %tmp = va_arg i8** %ap, i32 + + ; Demonstrate usage of llvm.va_copy and llvm.va_end + %aq = alloca i8* + %aq2 = bitcast i8** %aq to i8* + call void @llvm.va_copy(i8* %aq2, i8* %ap2) + call void @llvm.va_end(i8* %aq2) + + ; Stop processing of arguments. + call void @llvm.va_end(i8* %ap2) + ret i32 %tmp + } + + declare void @llvm.va_start(i8*) + declare void @llvm.va_copy(i8*, i8*) + declare void @llvm.va_end(i8*) + +.. _int_va_start: + +'``llvm.va_start``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.va_start(i8* ) + +Overview: +""""""""" + +The '``llvm.va_start``' intrinsic initializes ``*`` for +subsequent use by ``va_arg``. + +Arguments: +"""""""""" + +The argument is a pointer to a ``va_list`` element to initialize. + +Semantics: +"""""""""" + +The '``llvm.va_start``' intrinsic works just like the ``va_start`` macro +available in C. In a target-dependent way, it initializes the +``va_list`` element to which the argument points, so that the next call +to ``va_arg`` will produce the first variable argument passed to the +function. Unlike the C ``va_start`` macro, this intrinsic does not need +to know the last argument of the function as the compiler can figure +that out. + +'``llvm.va_end``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.va_end(i8* ) + +Overview: +""""""""" + +The '``llvm.va_end``' intrinsic destroys ``*``, which has been +initialized previously with ``llvm.va_start`` or ``llvm.va_copy``. + +Arguments: +"""""""""" + +The argument is a pointer to a ``va_list`` to destroy. + +Semantics: +"""""""""" + +The '``llvm.va_end``' intrinsic works just like the ``va_end`` macro +available in C. In a target-dependent way, it destroys the ``va_list`` +element to which the argument points. Calls to +:ref:`llvm.va_start ` and +:ref:`llvm.va_copy ` must be matched exactly with calls to +``llvm.va_end``. + +.. _int_va_copy: + +'``llvm.va_copy``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.va_copy(i8* , i8* ) + +Overview: +""""""""" + +The '``llvm.va_copy``' intrinsic copies the current argument position +from the source argument list to the destination argument list. + +Arguments: +"""""""""" + +The first argument is a pointer to a ``va_list`` element to initialize. +The second argument is a pointer to a ``va_list`` element to copy from. + +Semantics: +"""""""""" + +The '``llvm.va_copy``' intrinsic works just like the ``va_copy`` macro +available in C. In a target-dependent way, it copies the source +``va_list`` element into the destination ``va_list`` element. This +intrinsic is necessary because the `` llvm.va_start`` intrinsic may be +arbitrarily complex and require, for example, memory allocation. + +Accurate Garbage Collection Intrinsics +-------------------------------------- + +LLVM support for `Accurate Garbage Collection `_ +(GC) requires the implementation and generation of these intrinsics. +These intrinsics allow identification of :ref:`GC roots on the +stack `, as well as garbage collector implementations that +require :ref:`read ` and :ref:`write ` barriers. +Front-ends for type-safe garbage collected languages should generate +these intrinsics to make use of the LLVM garbage collectors. For more +details, see `Accurate Garbage Collection with +LLVM `_. + +The garbage collection intrinsics only operate on objects in the generic +address space (address space zero). + +.. _int_gcroot: + +'``llvm.gcroot``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.gcroot(i8** %ptrloc, i8* %metadata) + +Overview: +""""""""" + +The '``llvm.gcroot``' intrinsic declares the existence of a GC root to +the code generator, and allows some metadata to be associated with it. + +Arguments: +"""""""""" + +The first argument specifies the address of a stack object that contains +the root pointer. The second pointer (which must be either a constant or +a global value address) contains the meta-data to be associated with the +root. + +Semantics: +"""""""""" + +At runtime, a call to this intrinsic stores a null pointer into the +"ptrloc" location. At compile-time, the code generator generates +information to allow the runtime to find the pointer at GC safe points. +The '``llvm.gcroot``' intrinsic may only be used in a function which +:ref:`specifies a GC algorithm `. + +.. _int_gcread: + +'``llvm.gcread``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i8* @llvm.gcread(i8* %ObjPtr, i8** %Ptr) + +Overview: +""""""""" + +The '``llvm.gcread``' intrinsic identifies reads of references from heap +locations, allowing garbage collector implementations that require read +barriers. + +Arguments: +"""""""""" + +The second argument is the address to read from, which should be an +address allocated from the garbage collector. The first object is a +pointer to the start of the referenced object, if needed by the language +runtime (otherwise null). + +Semantics: +"""""""""" + +The '``llvm.gcread``' intrinsic has the same semantics as a load +instruction, but may be replaced with substantially more complex code by +the garbage collector runtime, as needed. The '``llvm.gcread``' +intrinsic may only be used in a function which :ref:`specifies a GC +algorithm `. + +.. _int_gcwrite: + +'``llvm.gcwrite``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.gcwrite(i8* %P1, i8* %Obj, i8** %P2) + +Overview: +""""""""" + +The '``llvm.gcwrite``' intrinsic identifies writes of references to heap +locations, allowing garbage collector implementations that require write +barriers (such as generational or reference counting collectors). + +Arguments: +"""""""""" + +The first argument is the reference to store, the second is the start of +the object to store it to, and the third is the address of the field of +Obj to store to. If the runtime does not require a pointer to the +object, Obj may be null. + +Semantics: +"""""""""" + +The '``llvm.gcwrite``' intrinsic has the same semantics as a store +instruction, but may be replaced with substantially more complex code by +the garbage collector runtime, as needed. The '``llvm.gcwrite``' +intrinsic may only be used in a function which :ref:`specifies a GC +algorithm `. + +Code Generator Intrinsics +------------------------- + +These intrinsics are provided by LLVM to expose special features that +may only be implemented with code generator support. + +'``llvm.returnaddress``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i8 *@llvm.returnaddress(i32 ) + +Overview: +""""""""" + +The '``llvm.returnaddress``' intrinsic attempts to compute a +target-specific value indicating the return address of the current +function or one of its callers. + +Arguments: +"""""""""" + +The argument to this intrinsic indicates which function to return the +address for. Zero indicates the calling function, one indicates its +caller, etc. The argument is **required** to be a constant integer +value. + +Semantics: +"""""""""" + +The '``llvm.returnaddress``' intrinsic either returns a pointer +indicating the return address of the specified call frame, or zero if it +cannot be identified. The value returned by this intrinsic is likely to +be incorrect or 0 for arguments other than zero, so it should only be +used for debugging purposes. + +Note that calling this intrinsic does not prevent function inlining or +other aggressive transformations, so the value returned may not be that +of the obvious source-language caller. + +'``llvm.frameaddress``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i8* @llvm.frameaddress(i32 ) + +Overview: +""""""""" + +The '``llvm.frameaddress``' intrinsic attempts to return the +target-specific frame pointer value for the specified stack frame. + +Arguments: +"""""""""" + +The argument to this intrinsic indicates which function to return the +frame pointer for. Zero indicates the calling function, one indicates +its caller, etc. The argument is **required** to be a constant integer +value. + +Semantics: +"""""""""" + +The '``llvm.frameaddress``' intrinsic either returns a pointer +indicating the frame address of the specified call frame, or zero if it +cannot be identified. The value returned by this intrinsic is likely to +be incorrect or 0 for arguments other than zero, so it should only be +used for debugging purposes. + +Note that calling this intrinsic does not prevent function inlining or +other aggressive transformations, so the value returned may not be that +of the obvious source-language caller. + +.. _int_stacksave: + +'``llvm.stacksave``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i8* @llvm.stacksave() + +Overview: +""""""""" + +The '``llvm.stacksave``' intrinsic is used to remember the current state +of the function stack, for use with +:ref:`llvm.stackrestore `. This is useful for +implementing language features like scoped automatic variable sized +arrays in C99. + +Semantics: +"""""""""" + +This intrinsic returns a opaque pointer value that can be passed to +:ref:`llvm.stackrestore `. When an +``llvm.stackrestore`` intrinsic is executed with a value saved from +``llvm.stacksave``, it effectively restores the state of the stack to +the state it was in when the ``llvm.stacksave`` intrinsic executed. In +practice, this pops any :ref:`alloca ` blocks from the stack that +were allocated after the ``llvm.stacksave`` was executed. + +.. _int_stackrestore: + +'``llvm.stackrestore``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.stackrestore(i8* %ptr) + +Overview: +""""""""" + +The '``llvm.stackrestore``' intrinsic is used to restore the state of +the function stack to the state it was in when the corresponding +:ref:`llvm.stacksave ` intrinsic executed. This is +useful for implementing language features like scoped automatic variable +sized arrays in C99. + +Semantics: +"""""""""" + +See the description for :ref:`llvm.stacksave `. + +'``llvm.prefetch``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.prefetch(i8*
, i32 , i32 , i32 ) + +Overview: +""""""""" + +The '``llvm.prefetch``' intrinsic is a hint to the code generator to +insert a prefetch instruction if supported; otherwise, it is a noop. +Prefetches have no effect on the behavior of the program but can change +its performance characteristics. + +Arguments: +"""""""""" + +``address`` is the address to be prefetched, ``rw`` is the specifier +determining if the fetch should be for a read (0) or write (1), and +``locality`` is a temporal locality specifier ranging from (0) - no +locality, to (3) - extremely local keep in cache. The ``cache type`` +specifies whether the prefetch is performed on the data (1) or +instruction (0) cache. The ``rw``, ``locality`` and ``cache type`` +arguments must be constant integers. + +Semantics: +"""""""""" + +This intrinsic does not modify the behavior of the program. In +particular, prefetches cannot trap and do not produce a value. On +targets that support this intrinsic, the prefetch can provide hints to +the processor cache for better performance. + +'``llvm.pcmarker``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.pcmarker(i32 ) + +Overview: +""""""""" + +The '``llvm.pcmarker``' intrinsic is a method to export a Program +Counter (PC) in a region of code to simulators and other tools. The +method is target specific, but it is expected that the marker will use +exported symbols to transmit the PC of the marker. The marker makes no +guarantees that it will remain with any specific instruction after +optimizations. It is possible that the presence of a marker will inhibit +optimizations. The intended use is to be inserted after optimizations to +allow correlations of simulation runs. + +Arguments: +"""""""""" + +``id`` is a numerical id identifying the marker. + +Semantics: +"""""""""" + +This intrinsic does not modify the behavior of the program. Backends +that do not support this intrinsic may ignore it. + +'``llvm.readcyclecounter``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i64 @llvm.readcyclecounter() + +Overview: +""""""""" + +The '``llvm.readcyclecounter``' intrinsic provides access to the cycle +counter register (or similar low latency, high accuracy clocks) on those +targets that support it. On X86, it should map to RDTSC. On Alpha, it +should map to RPCC. As the backing counters overflow quickly (on the +order of 9 seconds on alpha), this should only be used for small +timings. + +Semantics: +"""""""""" + +When directly supported, reading the cycle counter should not modify any +memory. Implementations are allowed to either return a application +specific value or a system wide value. On backends without support, this +is lowered to a constant 0. + +Note that runtime support may be conditional on the privilege-level code is +running at and the host platform. + +Standard C Library Intrinsics +----------------------------- + +LLVM provides intrinsics for a few important standard C library +functions. These intrinsics allow source-language front-ends to pass +information about the alignment of the pointer arguments to the code +generator, providing opportunity for more efficient code generation. + +.. _int_memcpy: + +'``llvm.memcpy``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.memcpy`` on any +integer bit width and for different address spaces. Not all targets +support all bit widths however. + +:: + + declare void @llvm.memcpy.p0i8.p0i8.i32(i8* , i8* , + i32 , i32 , i1 ) + declare void @llvm.memcpy.p0i8.p0i8.i64(i8* , i8* , + i64 , i32 , i1 ) + +Overview: +""""""""" + +The '``llvm.memcpy.*``' intrinsics copy a block of memory from the +source location to the destination location. + +Note that, unlike the standard libc function, the ``llvm.memcpy.*`` +intrinsics do not return a value, takes extra alignment/isvolatile +arguments and the pointers can be in specified address spaces. + +Arguments: +"""""""""" + +The first argument is a pointer to the destination, the second is a +pointer to the source. The third argument is an integer argument +specifying the number of bytes to copy, the fourth argument is the +alignment of the source and destination locations, and the fifth is a +boolean indicating a volatile access. + +If the call to this intrinsic has an alignment value that is not 0 or 1, +then the caller guarantees that both the source and destination pointers +are aligned to that boundary. + +If the ``isvolatile`` parameter is ``true``, the ``llvm.memcpy`` call is +a :ref:`volatile operation `. The detailed access behavior is not +very cleanly specified and it is unwise to depend on it. + +Semantics: +"""""""""" + +The '``llvm.memcpy.*``' intrinsics copy a block of memory from the +source location to the destination location, which are not allowed to +overlap. It copies "len" bytes of memory over. If the argument is known +to be aligned to some boundary, this can be specified as the fourth +argument, otherwise it should be set to 0 or 1 (both meaning no alignment). + +'``llvm.memmove``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use llvm.memmove on any integer +bit width and for different address space. Not all targets support all +bit widths however. + +:: + + declare void @llvm.memmove.p0i8.p0i8.i32(i8* , i8* , + i32 , i32 , i1 ) + declare void @llvm.memmove.p0i8.p0i8.i64(i8* , i8* , + i64 , i32 , i1 ) + +Overview: +""""""""" + +The '``llvm.memmove.*``' intrinsics move a block of memory from the +source location to the destination location. It is similar to the +'``llvm.memcpy``' intrinsic but allows the two memory locations to +overlap. + +Note that, unlike the standard libc function, the ``llvm.memmove.*`` +intrinsics do not return a value, takes extra alignment/isvolatile +arguments and the pointers can be in specified address spaces. + +Arguments: +"""""""""" + +The first argument is a pointer to the destination, the second is a +pointer to the source. The third argument is an integer argument +specifying the number of bytes to copy, the fourth argument is the +alignment of the source and destination locations, and the fifth is a +boolean indicating a volatile access. + +If the call to this intrinsic has an alignment value that is not 0 or 1, +then the caller guarantees that the source and destination pointers are +aligned to that boundary. + +If the ``isvolatile`` parameter is ``true``, the ``llvm.memmove`` call +is a :ref:`volatile operation `. The detailed access behavior is +not very cleanly specified and it is unwise to depend on it. + +Semantics: +"""""""""" + +The '``llvm.memmove.*``' intrinsics copy a block of memory from the +source location to the destination location, which may overlap. It +copies "len" bytes of memory over. If the argument is known to be +aligned to some boundary, this can be specified as the fourth argument, +otherwise it should be set to 0 or 1 (both meaning no alignment). + +'``llvm.memset.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use llvm.memset on any integer +bit width and for different address spaces. However, not all targets +support all bit widths. + +:: + + declare void @llvm.memset.p0i8.i32(i8* , i8 , + i32 , i32 , i1 ) + declare void @llvm.memset.p0i8.i64(i8* , i8 , + i64 , i32 , i1 ) + +Overview: +""""""""" + +The '``llvm.memset.*``' intrinsics fill a block of memory with a +particular byte value. + +Note that, unlike the standard libc function, the ``llvm.memset`` +intrinsic does not return a value and takes extra alignment/volatile +arguments. Also, the destination can be in an arbitrary address space. + +Arguments: +"""""""""" + +The first argument is a pointer to the destination to fill, the second +is the byte value with which to fill it, the third argument is an +integer argument specifying the number of bytes to fill, and the fourth +argument is the known alignment of the destination location. + +If the call to this intrinsic has an alignment value that is not 0 or 1, +then the caller guarantees that the destination pointer is aligned to +that boundary. + +If the ``isvolatile`` parameter is ``true``, the ``llvm.memset`` call is +a :ref:`volatile operation `. The detailed access behavior is not +very cleanly specified and it is unwise to depend on it. + +Semantics: +"""""""""" + +The '``llvm.memset.*``' intrinsics fill "len" bytes of memory starting +at the destination location. If the argument is known to be aligned to +some boundary, this can be specified as the fourth argument, otherwise +it should be set to 0 or 1 (both meaning no alignment). + +'``llvm.sqrt.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.sqrt`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.sqrt.f32(float %Val) + declare double @llvm.sqrt.f64(double %Val) + declare x86_fp80 @llvm.sqrt.f80(x86_fp80 %Val) + declare fp128 @llvm.sqrt.f128(fp128 %Val) + declare ppc_fp128 @llvm.sqrt.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.sqrt``' intrinsics return the sqrt of the specified operand, +returning the same value as the libm '``sqrt``' functions would. Unlike +``sqrt`` in libm, however, ``llvm.sqrt`` has undefined behavior for +negative numbers other than -0.0 (which allows for better optimization, +because there is no need to worry about errno being set). +``llvm.sqrt(-0.0)`` is defined to return -0.0 like IEEE sqrt. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the sqrt of the specified operand if it is a +nonnegative floating point number. + +'``llvm.powi.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.powi`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.powi.f32(float %Val, i32 %power) + declare double @llvm.powi.f64(double %Val, i32 %power) + declare x86_fp80 @llvm.powi.f80(x86_fp80 %Val, i32 %power) + declare fp128 @llvm.powi.f128(fp128 %Val, i32 %power) + declare ppc_fp128 @llvm.powi.ppcf128(ppc_fp128 %Val, i32 %power) + +Overview: +""""""""" + +The '``llvm.powi.*``' intrinsics return the first operand raised to the +specified (positive or negative) power. The order of evaluation of +multiplications is not defined. When a vector of floating point type is +used, the second argument remains a scalar integer value. + +Arguments: +"""""""""" + +The second argument is an integer power, and the first is a value to +raise to that power. + +Semantics: +"""""""""" + +This function returns the first value raised to the second power with an +unspecified sequence of rounding operations. + +'``llvm.sin.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.sin`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.sin.f32(float %Val) + declare double @llvm.sin.f64(double %Val) + declare x86_fp80 @llvm.sin.f80(x86_fp80 %Val) + declare fp128 @llvm.sin.f128(fp128 %Val) + declare ppc_fp128 @llvm.sin.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.sin.*``' intrinsics return the sine of the operand. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the sine of the specified operand, returning the +same values as the libm ``sin`` functions would, and handles error +conditions in the same way. + +'``llvm.cos.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.cos`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.cos.f32(float %Val) + declare double @llvm.cos.f64(double %Val) + declare x86_fp80 @llvm.cos.f80(x86_fp80 %Val) + declare fp128 @llvm.cos.f128(fp128 %Val) + declare ppc_fp128 @llvm.cos.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.cos.*``' intrinsics return the cosine of the operand. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the cosine of the specified operand, returning the +same values as the libm ``cos`` functions would, and handles error +conditions in the same way. + +'``llvm.pow.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.pow`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.pow.f32(float %Val, float %Power) + declare double @llvm.pow.f64(double %Val, double %Power) + declare x86_fp80 @llvm.pow.f80(x86_fp80 %Val, x86_fp80 %Power) + declare fp128 @llvm.pow.f128(fp128 %Val, fp128 %Power) + declare ppc_fp128 @llvm.pow.ppcf128(ppc_fp128 %Val, ppc_fp128 Power) + +Overview: +""""""""" + +The '``llvm.pow.*``' intrinsics return the first operand raised to the +specified (positive or negative) power. + +Arguments: +"""""""""" + +The second argument is a floating point power, and the first is a value +to raise to that power. + +Semantics: +"""""""""" + +This function returns the first value raised to the second power, +returning the same values as the libm ``pow`` functions would, and +handles error conditions in the same way. + +'``llvm.exp.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.exp`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.exp.f32(float %Val) + declare double @llvm.exp.f64(double %Val) + declare x86_fp80 @llvm.exp.f80(x86_fp80 %Val) + declare fp128 @llvm.exp.f128(fp128 %Val) + declare ppc_fp128 @llvm.exp.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.exp.*``' intrinsics perform the exp function. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``exp`` functions +would, and handles error conditions in the same way. + +'``llvm.exp2.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.exp2`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.exp2.f32(float %Val) + declare double @llvm.exp2.f64(double %Val) + declare x86_fp80 @llvm.exp2.f80(x86_fp80 %Val) + declare fp128 @llvm.exp2.f128(fp128 %Val) + declare ppc_fp128 @llvm.exp2.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.exp2.*``' intrinsics perform the exp2 function. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``exp2`` functions +would, and handles error conditions in the same way. + +'``llvm.log.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.log`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.log.f32(float %Val) + declare double @llvm.log.f64(double %Val) + declare x86_fp80 @llvm.log.f80(x86_fp80 %Val) + declare fp128 @llvm.log.f128(fp128 %Val) + declare ppc_fp128 @llvm.log.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.log.*``' intrinsics perform the log function. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``log`` functions +would, and handles error conditions in the same way. + +'``llvm.log10.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.log10`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.log10.f32(float %Val) + declare double @llvm.log10.f64(double %Val) + declare x86_fp80 @llvm.log10.f80(x86_fp80 %Val) + declare fp128 @llvm.log10.f128(fp128 %Val) + declare ppc_fp128 @llvm.log10.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.log10.*``' intrinsics perform the log10 function. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``log10`` functions +would, and handles error conditions in the same way. + +'``llvm.log2.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.log2`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.log2.f32(float %Val) + declare double @llvm.log2.f64(double %Val) + declare x86_fp80 @llvm.log2.f80(x86_fp80 %Val) + declare fp128 @llvm.log2.f128(fp128 %Val) + declare ppc_fp128 @llvm.log2.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.log2.*``' intrinsics perform the log2 function. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``log2`` functions +would, and handles error conditions in the same way. + +'``llvm.fma.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.fma`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.fma.f32(float %a, float %b, float %c) + declare double @llvm.fma.f64(double %a, double %b, double %c) + declare x86_fp80 @llvm.fma.f80(x86_fp80 %a, x86_fp80 %b, x86_fp80 %c) + declare fp128 @llvm.fma.f128(fp128 %a, fp128 %b, fp128 %c) + declare ppc_fp128 @llvm.fma.ppcf128(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c) + +Overview: +""""""""" + +The '``llvm.fma.*``' intrinsics perform the fused multiply-add +operation. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``fma`` functions +would. + +'``llvm.fabs.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.fabs`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.fabs.f32(float %Val) + declare double @llvm.fabs.f64(double %Val) + declare x86_fp80 @llvm.fabs.f80(x86_fp80 %Val) + declare fp128 @llvm.fabs.f128(fp128 %Val) + declare ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.fabs.*``' intrinsics return the absolute value of the +operand. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``fabs`` functions +would, and handles error conditions in the same way. + +'``llvm.copysign.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.copysign`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.copysign.f32(float %Mag, float %Sgn) + declare double @llvm.copysign.f64(double %Mag, double %Sgn) + declare x86_fp80 @llvm.copysign.f80(x86_fp80 %Mag, x86_fp80 %Sgn) + declare fp128 @llvm.copysign.f128(fp128 %Mag, fp128 %Sgn) + declare ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 %Mag, ppc_fp128 %Sgn) + +Overview: +""""""""" + +The '``llvm.copysign.*``' intrinsics return a value with the magnitude of the +first operand and the sign of the second operand. + +Arguments: +"""""""""" + +The arguments and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``copysign`` +functions would, and handles error conditions in the same way. + +'``llvm.floor.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.floor`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.floor.f32(float %Val) + declare double @llvm.floor.f64(double %Val) + declare x86_fp80 @llvm.floor.f80(x86_fp80 %Val) + declare fp128 @llvm.floor.f128(fp128 %Val) + declare ppc_fp128 @llvm.floor.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.floor.*``' intrinsics return the floor of the operand. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``floor`` functions +would, and handles error conditions in the same way. + +'``llvm.ceil.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.ceil`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.ceil.f32(float %Val) + declare double @llvm.ceil.f64(double %Val) + declare x86_fp80 @llvm.ceil.f80(x86_fp80 %Val) + declare fp128 @llvm.ceil.f128(fp128 %Val) + declare ppc_fp128 @llvm.ceil.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.ceil.*``' intrinsics return the ceiling of the operand. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``ceil`` functions +would, and handles error conditions in the same way. + +'``llvm.trunc.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.trunc`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.trunc.f32(float %Val) + declare double @llvm.trunc.f64(double %Val) + declare x86_fp80 @llvm.trunc.f80(x86_fp80 %Val) + declare fp128 @llvm.trunc.f128(fp128 %Val) + declare ppc_fp128 @llvm.trunc.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.trunc.*``' intrinsics returns the operand rounded to the +nearest integer not larger in magnitude than the operand. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``trunc`` functions +would, and handles error conditions in the same way. + +'``llvm.rint.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.rint`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.rint.f32(float %Val) + declare double @llvm.rint.f64(double %Val) + declare x86_fp80 @llvm.rint.f80(x86_fp80 %Val) + declare fp128 @llvm.rint.f128(fp128 %Val) + declare ppc_fp128 @llvm.rint.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.rint.*``' intrinsics returns the operand rounded to the +nearest integer. It may raise an inexact floating-point exception if the +operand isn't an integer. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``rint`` functions +would, and handles error conditions in the same way. + +'``llvm.nearbyint.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.nearbyint`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.nearbyint.f32(float %Val) + declare double @llvm.nearbyint.f64(double %Val) + declare x86_fp80 @llvm.nearbyint.f80(x86_fp80 %Val) + declare fp128 @llvm.nearbyint.f128(fp128 %Val) + declare ppc_fp128 @llvm.nearbyint.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.nearbyint.*``' intrinsics returns the operand rounded to the +nearest integer. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``nearbyint`` +functions would, and handles error conditions in the same way. + +'``llvm.round.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.round`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.round.f32(float %Val) + declare double @llvm.round.f64(double %Val) + declare x86_fp80 @llvm.round.f80(x86_fp80 %Val) + declare fp128 @llvm.round.f128(fp128 %Val) + declare ppc_fp128 @llvm.round.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.round.*``' intrinsics returns the operand rounded to the +nearest integer. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``round`` +functions would, and handles error conditions in the same way. + +Bit Manipulation Intrinsics +--------------------------- + +LLVM provides intrinsics for a few important bit manipulation +operations. These allow efficient code generation for some algorithms. + +'``llvm.bswap.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic function. You can use bswap on any +integer type that is an even number of bytes (i.e. BitWidth % 16 == 0). + +:: + + declare i16 @llvm.bswap.i16(i16 ) + declare i32 @llvm.bswap.i32(i32 ) + declare i64 @llvm.bswap.i64(i64 ) + +Overview: +""""""""" + +The '``llvm.bswap``' family of intrinsics is used to byte swap integer +values with an even number of bytes (positive multiple of 16 bits). +These are useful for performing operations on data that is not in the +target's native byte order. + +Semantics: +"""""""""" + +The ``llvm.bswap.i16`` intrinsic returns an i16 value that has the high +and low byte of the input i16 swapped. Similarly, the ``llvm.bswap.i32`` +intrinsic returns an i32 value that has the four bytes of the input i32 +swapped, so that if the input bytes are numbered 0, 1, 2, 3 then the +returned i32 will have its bytes in 3, 2, 1, 0 order. The +``llvm.bswap.i48``, ``llvm.bswap.i64`` and other intrinsics extend this +concept to additional even-byte lengths (6 bytes, 8 bytes and more, +respectively). + +'``llvm.ctpop.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use llvm.ctpop on any integer +bit width, or on any vector with integer elements. Not all targets +support all bit widths or vector types, however. + +:: + + declare i8 @llvm.ctpop.i8(i8 ) + declare i16 @llvm.ctpop.i16(i16 ) + declare i32 @llvm.ctpop.i32(i32 ) + declare i64 @llvm.ctpop.i64(i64 ) + declare i256 @llvm.ctpop.i256(i256 ) + declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32> ) + +Overview: +""""""""" + +The '``llvm.ctpop``' family of intrinsics counts the number of bits set +in a value. + +Arguments: +"""""""""" + +The only argument is the value to be counted. The argument may be of any +integer type, or a vector with integer elements. The return type must +match the argument type. + +Semantics: +"""""""""" + +The '``llvm.ctpop``' intrinsic counts the 1's in a variable, or within +each element of a vector. + +'``llvm.ctlz.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.ctlz`` on any +integer bit width, or any vector whose elements are integers. Not all +targets support all bit widths or vector types, however. + +:: + + declare i8 @llvm.ctlz.i8 (i8 , i1 ) + declare i16 @llvm.ctlz.i16 (i16 , i1 ) + declare i32 @llvm.ctlz.i32 (i32 , i1 ) + declare i64 @llvm.ctlz.i64 (i64 , i1 ) + declare i256 @llvm.ctlz.i256(i256 , i1 ) + declase <2 x i32> @llvm.ctlz.v2i32(<2 x i32> , i1 ) + +Overview: +""""""""" + +The '``llvm.ctlz``' family of intrinsic functions counts the number of +leading zeros in a variable. + +Arguments: +"""""""""" + +The first argument is the value to be counted. This argument may be of +any integer type, or a vectory with integer element type. The return +type must match the first argument type. + +The second argument must be a constant and is a flag to indicate whether +the intrinsic should ensure that a zero as the first argument produces a +defined result. Historically some architectures did not provide a +defined result for zero values as efficiently, and many algorithms are +now predicated on avoiding zero-value inputs. + +Semantics: +"""""""""" + +The '``llvm.ctlz``' intrinsic counts the leading (most significant) +zeros in a variable, or within each element of the vector. If +``src == 0`` then the result is the size in bits of the type of ``src`` +if ``is_zero_undef == 0`` and ``undef`` otherwise. For example, +``llvm.ctlz(i32 2) = 30``. + +'``llvm.cttz.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.cttz`` on any +integer bit width, or any vector of integer elements. Not all targets +support all bit widths or vector types, however. + +:: + + declare i8 @llvm.cttz.i8 (i8 , i1 ) + declare i16 @llvm.cttz.i16 (i16 , i1 ) + declare i32 @llvm.cttz.i32 (i32 , i1 ) + declare i64 @llvm.cttz.i64 (i64 , i1 ) + declare i256 @llvm.cttz.i256(i256 , i1 ) + declase <2 x i32> @llvm.cttz.v2i32(<2 x i32> , i1 ) + +Overview: +""""""""" + +The '``llvm.cttz``' family of intrinsic functions counts the number of +trailing zeros. + +Arguments: +"""""""""" + +The first argument is the value to be counted. This argument may be of +any integer type, or a vectory with integer element type. The return +type must match the first argument type. + +The second argument must be a constant and is a flag to indicate whether +the intrinsic should ensure that a zero as the first argument produces a +defined result. Historically some architectures did not provide a +defined result for zero values as efficiently, and many algorithms are +now predicated on avoiding zero-value inputs. + +Semantics: +"""""""""" + +The '``llvm.cttz``' intrinsic counts the trailing (least significant) +zeros in a variable, or within each element of a vector. If ``src == 0`` +then the result is the size in bits of the type of ``src`` if +``is_zero_undef == 0`` and ``undef`` otherwise. For example, +``llvm.cttz(2) = 1``. + +Arithmetic with Overflow Intrinsics +----------------------------------- + +LLVM provides intrinsics for some arithmetic with overflow operations. + +'``llvm.sadd.with.overflow.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.sadd.with.overflow`` +on any integer bit width. + +:: + + declare {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b) + declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b) + declare {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b) + +Overview: +""""""""" + +The '``llvm.sadd.with.overflow``' family of intrinsic functions perform +a signed addition of the two arguments, and indicate whether an overflow +occurred during the signed summation. + +Arguments: +"""""""""" + +The arguments (%a and %b) and the first element of the result structure +may be of integer types of any bit width, but they must have the same +bit width. The second element of the result structure must be of type +``i1``. ``%a`` and ``%b`` are the two values that will undergo signed +addition. + +Semantics: +"""""""""" + +The '``llvm.sadd.with.overflow``' family of intrinsic functions perform +a signed addition of the two variables. They return a structure --- the +first element of which is the signed summation, and the second element +of which is a bit specifying if the signed summation resulted in an +overflow. + +Examples: +""""""""" + +.. code-block:: llvm + + %res = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b) + %sum = extractvalue {i32, i1} %res, 0 + %obit = extractvalue {i32, i1} %res, 1 + br i1 %obit, label %overflow, label %normal + +'``llvm.uadd.with.overflow.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.uadd.with.overflow`` +on any integer bit width. + +:: + + declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b) + declare {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b) + declare {i64, i1} @llvm.uadd.with.overflow.i64(i64 %a, i64 %b) + +Overview: +""""""""" + +The '``llvm.uadd.with.overflow``' family of intrinsic functions perform +an unsigned addition of the two arguments, and indicate whether a carry +occurred during the unsigned summation. + +Arguments: +"""""""""" + +The arguments (%a and %b) and the first element of the result structure +may be of integer types of any bit width, but they must have the same +bit width. The second element of the result structure must be of type +``i1``. ``%a`` and ``%b`` are the two values that will undergo unsigned +addition. + +Semantics: +"""""""""" + +The '``llvm.uadd.with.overflow``' family of intrinsic functions perform +an unsigned addition of the two arguments. They return a structure --- the +first element of which is the sum, and the second element of which is a +bit specifying if the unsigned summation resulted in a carry. + +Examples: +""""""""" + +.. code-block:: llvm + + %res = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b) + %sum = extractvalue {i32, i1} %res, 0 + %obit = extractvalue {i32, i1} %res, 1 + br i1 %obit, label %carry, label %normal + +'``llvm.ssub.with.overflow.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.ssub.with.overflow`` +on any integer bit width. + +:: + + declare {i16, i1} @llvm.ssub.with.overflow.i16(i16 %a, i16 %b) + declare {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b) + declare {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b) + +Overview: +""""""""" + +The '``llvm.ssub.with.overflow``' family of intrinsic functions perform +a signed subtraction of the two arguments, and indicate whether an +overflow occurred during the signed subtraction. + +Arguments: +"""""""""" + +The arguments (%a and %b) and the first element of the result structure +may be of integer types of any bit width, but they must have the same +bit width. The second element of the result structure must be of type +``i1``. ``%a`` and ``%b`` are the two values that will undergo signed +subtraction. + +Semantics: +"""""""""" + +The '``llvm.ssub.with.overflow``' family of intrinsic functions perform +a signed subtraction of the two arguments. They return a structure --- the +first element of which is the subtraction, and the second element of +which is a bit specifying if the signed subtraction resulted in an +overflow. + +Examples: +""""""""" + +.. code-block:: llvm + + %res = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b) + %sum = extractvalue {i32, i1} %res, 0 + %obit = extractvalue {i32, i1} %res, 1 + br i1 %obit, label %overflow, label %normal + +'``llvm.usub.with.overflow.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.usub.with.overflow`` +on any integer bit width. + +:: + + declare {i16, i1} @llvm.usub.with.overflow.i16(i16 %a, i16 %b) + declare {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b) + declare {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 %b) + +Overview: +""""""""" + +The '``llvm.usub.with.overflow``' family of intrinsic functions perform +an unsigned subtraction of the two arguments, and indicate whether an +overflow occurred during the unsigned subtraction. + +Arguments: +"""""""""" + +The arguments (%a and %b) and the first element of the result structure +may be of integer types of any bit width, but they must have the same +bit width. The second element of the result structure must be of type +``i1``. ``%a`` and ``%b`` are the two values that will undergo unsigned +subtraction. + +Semantics: +"""""""""" + +The '``llvm.usub.with.overflow``' family of intrinsic functions perform +an unsigned subtraction of the two arguments. They return a structure --- +the first element of which is the subtraction, and the second element of +which is a bit specifying if the unsigned subtraction resulted in an +overflow. + +Examples: +""""""""" + +.. code-block:: llvm + + %res = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b) + %sum = extractvalue {i32, i1} %res, 0 + %obit = extractvalue {i32, i1} %res, 1 + br i1 %obit, label %overflow, label %normal + +'``llvm.smul.with.overflow.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.smul.with.overflow`` +on any integer bit width. + +:: + + declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b) + declare {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b) + declare {i64, i1} @llvm.smul.with.overflow.i64(i64 %a, i64 %b) + +Overview: +""""""""" + +The '``llvm.smul.with.overflow``' family of intrinsic functions perform +a signed multiplication of the two arguments, and indicate whether an +overflow occurred during the signed multiplication. + +Arguments: +"""""""""" + +The arguments (%a and %b) and the first element of the result structure +may be of integer types of any bit width, but they must have the same +bit width. The second element of the result structure must be of type +``i1``. ``%a`` and ``%b`` are the two values that will undergo signed +multiplication. + +Semantics: +"""""""""" + +The '``llvm.smul.with.overflow``' family of intrinsic functions perform +a signed multiplication of the two arguments. They return a structure --- +the first element of which is the multiplication, and the second element +of which is a bit specifying if the signed multiplication resulted in an +overflow. + +Examples: +""""""""" + +.. code-block:: llvm + + %res = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b) + %sum = extractvalue {i32, i1} %res, 0 + %obit = extractvalue {i32, i1} %res, 1 + br i1 %obit, label %overflow, label %normal + +'``llvm.umul.with.overflow.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.umul.with.overflow`` +on any integer bit width. + +:: + + declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b) + declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b) + declare {i64, i1} @llvm.umul.with.overflow.i64(i64 %a, i64 %b) + +Overview: +""""""""" + +The '``llvm.umul.with.overflow``' family of intrinsic functions perform +a unsigned multiplication of the two arguments, and indicate whether an +overflow occurred during the unsigned multiplication. + +Arguments: +"""""""""" + +The arguments (%a and %b) and the first element of the result structure +may be of integer types of any bit width, but they must have the same +bit width. The second element of the result structure must be of type +``i1``. ``%a`` and ``%b`` are the two values that will undergo unsigned +multiplication. + +Semantics: +"""""""""" + +The '``llvm.umul.with.overflow``' family of intrinsic functions perform +an unsigned multiplication of the two arguments. They return a structure --- +the first element of which is the multiplication, and the second +element of which is a bit specifying if the unsigned multiplication +resulted in an overflow. + +Examples: +""""""""" + +.. code-block:: llvm + + %res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b) + %sum = extractvalue {i32, i1} %res, 0 + %obit = extractvalue {i32, i1} %res, 1 + br i1 %obit, label %overflow, label %normal + +Specialised Arithmetic Intrinsics +--------------------------------- + +'``llvm.fmuladd.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare float @llvm.fmuladd.f32(float %a, float %b, float %c) + declare double @llvm.fmuladd.f64(double %a, double %b, double %c) + +Overview: +""""""""" + +The '``llvm.fmuladd.*``' intrinsic functions represent multiply-add +expressions that can be fused if the code generator determines that (a) the +target instruction set has support for a fused operation, and (b) that the +fused operation is more efficient than the equivalent, separate pair of mul +and add instructions. + +Arguments: +"""""""""" + +The '``llvm.fmuladd.*``' intrinsics each take three arguments: two +multiplicands, a and b, and an addend c. + +Semantics: +"""""""""" + +The expression: + +:: + + %0 = call float @llvm.fmuladd.f32(%a, %b, %c) + +is equivalent to the expression a \* b + c, except that rounding will +not be performed between the multiplication and addition steps if the +code generator fuses the operations. Fusion is not guaranteed, even if +the target platform supports it. If a fused multiply-add is required the +corresponding llvm.fma.\* intrinsic function should be used instead. + +Examples: +""""""""" + +.. code-block:: llvm + + %r2 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) ; yields {float}:r2 = (a * b) + c + +Half Precision Floating Point Intrinsics +---------------------------------------- + +For most target platforms, half precision floating point is a +storage-only format. This means that it is a dense encoding (in memory) +but does not support computation in the format. + +This means that code must first load the half-precision floating point +value as an i16, then convert it to float with +:ref:`llvm.convert.from.fp16 `. Computation can +then be performed on the float value (including extending to double +etc). To store the value back to memory, it is first converted to float +if needed, then converted to i16 with +:ref:`llvm.convert.to.fp16 `, then storing as an +i16 value. + +.. _int_convert_to_fp16: + +'``llvm.convert.to.fp16``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i16 @llvm.convert.to.fp16(f32 %a) + +Overview: +""""""""" + +The '``llvm.convert.to.fp16``' intrinsic function performs a conversion +from single precision floating point format to half precision floating +point format. + +Arguments: +"""""""""" + +The intrinsic function contains single argument - the value to be +converted. + +Semantics: +"""""""""" + +The '``llvm.convert.to.fp16``' intrinsic function performs a conversion +from single precision floating point format to half precision floating +point format. The return value is an ``i16`` which contains the +converted number. + +Examples: +""""""""" + +.. code-block:: llvm + + %res = call i16 @llvm.convert.to.fp16(f32 %a) + store i16 %res, i16* @x, align 2 + +.. _int_convert_from_fp16: + +'``llvm.convert.from.fp16``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare f32 @llvm.convert.from.fp16(i16 %a) + +Overview: +""""""""" + +The '``llvm.convert.from.fp16``' intrinsic function performs a +conversion from half precision floating point format to single precision +floating point format. + +Arguments: +"""""""""" + +The intrinsic function contains single argument - the value to be +converted. + +Semantics: +"""""""""" + +The '``llvm.convert.from.fp16``' intrinsic function performs a +conversion from half single precision floating point format to single +precision floating point format. The input half-float value is +represented by an ``i16`` value. + +Examples: +""""""""" + +.. code-block:: llvm + + %a = load i16* @x, align 2 + %res = call f32 @llvm.convert.from.fp16(i16 %a) + +Debugger Intrinsics +------------------- + +The LLVM debugger intrinsics (which all start with ``llvm.dbg.`` +prefix), are described in the `LLVM Source Level +Debugging `_ +document. + +Exception Handling Intrinsics +----------------------------- + +The LLVM exception handling intrinsics (which all start with +``llvm.eh.`` prefix), are described in the `LLVM Exception +Handling `_ document. + +.. _int_trampoline: + +Trampoline Intrinsics +--------------------- + +These intrinsics make it possible to excise one parameter, marked with +the :ref:`nest ` attribute, from a function. The result is a +callable function pointer lacking the nest parameter - the caller does +not need to provide a value for it. Instead, the value to use is stored +in advance in a "trampoline", a block of memory usually allocated on the +stack, which also contains code to splice the nest value into the +argument list. This is used to implement the GCC nested function address +extension. + +For example, if the function is ``i32 f(i8* nest %c, i32 %x, i32 %y)`` +then the resulting function pointer has signature ``i32 (i32, i32)*``. +It can be created as follows: + +.. code-block:: llvm + + %tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86 + %tramp1 = getelementptr [10 x i8]* %tramp, i32 0, i32 0 + call i8* @llvm.init.trampoline(i8* %tramp1, i8* bitcast (i32 (i8*, i32, i32)* @f to i8*), i8* %nval) + %p = call i8* @llvm.adjust.trampoline(i8* %tramp1) + %fp = bitcast i8* %p to i32 (i32, i32)* + +The call ``%val = call i32 %fp(i32 %x, i32 %y)`` is then equivalent to +``%val = call i32 %f(i8* %nval, i32 %x, i32 %y)``. + +.. _int_it: + +'``llvm.init.trampoline``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.init.trampoline(i8* , i8* , i8* ) + +Overview: +""""""""" + +This fills the memory pointed to by ``tramp`` with executable code, +turning it into a trampoline. + +Arguments: +"""""""""" + +The ``llvm.init.trampoline`` intrinsic takes three arguments, all +pointers. The ``tramp`` argument must point to a sufficiently large and +sufficiently aligned block of memory; this memory is written to by the +intrinsic. Note that the size and the alignment are target-specific - +LLVM currently provides no portable way of determining them, so a +front-end that generates this intrinsic needs to have some +target-specific knowledge. The ``func`` argument must hold a function +bitcast to an ``i8*``. + +Semantics: +"""""""""" + +The block of memory pointed to by ``tramp`` is filled with target +dependent code, turning it into a function. Then ``tramp`` needs to be +passed to :ref:`llvm.adjust.trampoline ` to get a pointer which can +be :ref:`bitcast (to a new function) and called `. The new +function's signature is the same as that of ``func`` with any arguments +marked with the ``nest`` attribute removed. At most one such ``nest`` +argument is allowed, and it must be of pointer type. Calling the new +function is equivalent to calling ``func`` with the same argument list, +but with ``nval`` used for the missing ``nest`` argument. If, after +calling ``llvm.init.trampoline``, the memory pointed to by ``tramp`` is +modified, then the effect of any later call to the returned function +pointer is undefined. + +.. _int_at: + +'``llvm.adjust.trampoline``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i8* @llvm.adjust.trampoline(i8* ) + +Overview: +""""""""" + +This performs any required machine-specific adjustment to the address of +a trampoline (passed as ``tramp``). + +Arguments: +"""""""""" + +``tramp`` must point to a block of memory which already has trampoline +code filled in by a previous call to +:ref:`llvm.init.trampoline `. + +Semantics: +"""""""""" + +On some architectures the address of the code to be executed needs to be +different to the address where the trampoline is actually stored. This +intrinsic returns the executable address corresponding to ``tramp`` +after performing the required machine specific adjustments. The pointer +returned can then be :ref:`bitcast and executed `. + +Memory Use Markers +------------------ + +This class of intrinsics exists to information about the lifetime of +memory objects and ranges where variables are immutable. + +'``llvm.lifetime.start``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.lifetime.start(i64 , i8* nocapture ) + +Overview: +""""""""" + +The '``llvm.lifetime.start``' intrinsic specifies the start of a memory +object's lifetime. + +Arguments: +"""""""""" + +The first argument is a constant integer representing the size of the +object, or -1 if it is variable sized. The second argument is a pointer +to the object. + +Semantics: +"""""""""" + +This intrinsic indicates that before this point in the code, the value +of the memory pointed to by ``ptr`` is dead. This means that it is known +to never be used and has an undefined value. A load from the pointer +that precedes this intrinsic can be replaced with ``'undef'``. + +'``llvm.lifetime.end``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.lifetime.end(i64 , i8* nocapture ) + +Overview: +""""""""" + +The '``llvm.lifetime.end``' intrinsic specifies the end of a memory +object's lifetime. + +Arguments: +"""""""""" + +The first argument is a constant integer representing the size of the +object, or -1 if it is variable sized. The second argument is a pointer +to the object. + +Semantics: +"""""""""" + +This intrinsic indicates that after this point in the code, the value of +the memory pointed to by ``ptr`` is dead. This means that it is known to +never be used and has an undefined value. Any stores into the memory +object following this intrinsic may be removed as dead. + +'``llvm.invariant.start``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare {}* @llvm.invariant.start(i64 , i8* nocapture ) + +Overview: +""""""""" + +The '``llvm.invariant.start``' intrinsic specifies that the contents of +a memory object will not change. + +Arguments: +"""""""""" + +The first argument is a constant integer representing the size of the +object, or -1 if it is variable sized. The second argument is a pointer +to the object. + +Semantics: +"""""""""" + +This intrinsic indicates that until an ``llvm.invariant.end`` that uses +the return value, the referenced memory location is constant and +unchanging. + +'``llvm.invariant.end``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.invariant.end({}* , i64 , i8* nocapture ) + +Overview: +""""""""" + +The '``llvm.invariant.end``' intrinsic specifies that the contents of a +memory object are mutable. + +Arguments: +"""""""""" + +The first argument is the matching ``llvm.invariant.start`` intrinsic. +The second argument is a constant integer representing the size of the +object, or -1 if it is variable sized and the third argument is a +pointer to the object. + +Semantics: +"""""""""" + +This intrinsic indicates that the memory is mutable again. + +General Intrinsics +------------------ + +This class of intrinsics is designed to be generic and has no specific +purpose. + +'``llvm.var.annotation``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.var.annotation(i8* , i8* , i8* , i32 ) + +Overview: +""""""""" + +The '``llvm.var.annotation``' intrinsic. + +Arguments: +"""""""""" + +The first argument is a pointer to a value, the second is a pointer to a +global string, the third is a pointer to a global string which is the +source file name, and the last argument is the line number. + +Semantics: +"""""""""" + +This intrinsic allows annotation of local variables with arbitrary +strings. This can be useful for special purpose optimizations that want +to look for these annotations. These have no other defined use; they are +ignored by code generation and optimization. + +'``llvm.ptr.annotation.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use '``llvm.ptr.annotation``' on a +pointer to an integer of any width. *NOTE* you must specify an address space for +the pointer. The identifier for the default address space is the integer +'``0``'. + +:: + + declare i8* @llvm.ptr.annotation.p
i8(i8* , i8* , i8* , i32 ) + declare i16* @llvm.ptr.annotation.p
i16(i16* , i8* , i8* , i32 ) + declare i32* @llvm.ptr.annotation.p
i32(i32* , i8* , i8* , i32 ) + declare i64* @llvm.ptr.annotation.p
i64(i64* , i8* , i8* , i32 ) + declare i256* @llvm.ptr.annotation.p
i256(i256* , i8* , i8* , i32 ) + +Overview: +""""""""" + +The '``llvm.ptr.annotation``' intrinsic. + +Arguments: +"""""""""" + +The first argument is a pointer to an integer value of arbitrary bitwidth +(result of some expression), the second is a pointer to a global string, the +third is a pointer to a global string which is the source file name, and the +last argument is the line number. It returns the value of the first argument. + +Semantics: +"""""""""" + +This intrinsic allows annotation of a pointer to an integer with arbitrary +strings. This can be useful for special purpose optimizations that want to look +for these annotations. These have no other defined use; they are ignored by code +generation and optimization. + +'``llvm.annotation.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use '``llvm.annotation``' on +any integer bit width. + +:: + + declare i8 @llvm.annotation.i8(i8 , i8* , i8* , i32 ) + declare i16 @llvm.annotation.i16(i16 , i8* , i8* , i32 ) + declare i32 @llvm.annotation.i32(i32 , i8* , i8* , i32 ) + declare i64 @llvm.annotation.i64(i64 , i8* , i8* , i32 ) + declare i256 @llvm.annotation.i256(i256 , i8* , i8* , i32 ) + +Overview: +""""""""" + +The '``llvm.annotation``' intrinsic. + +Arguments: +"""""""""" + +The first argument is an integer value (result of some expression), the +second is a pointer to a global string, the third is a pointer to a +global string which is the source file name, and the last argument is +the line number. It returns the value of the first argument. + +Semantics: +"""""""""" + +This intrinsic allows annotations to be put on arbitrary expressions +with arbitrary strings. This can be useful for special purpose +optimizations that want to look for these annotations. These have no +other defined use; they are ignored by code generation and optimization. + +'``llvm.trap``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.trap() noreturn nounwind + +Overview: +""""""""" + +The '``llvm.trap``' intrinsic. + +Arguments: +"""""""""" + +None. + +Semantics: +"""""""""" + +This intrinsic is lowered to the target dependent trap instruction. If +the target does not have a trap instruction, this intrinsic will be +lowered to a call of the ``abort()`` function. + +'``llvm.debugtrap``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.debugtrap() nounwind + +Overview: +""""""""" + +The '``llvm.debugtrap``' intrinsic. + +Arguments: +"""""""""" + +None. + +Semantics: +"""""""""" + +This intrinsic is lowered to code which is intended to cause an +execution trap with the intention of requesting the attention of a +debugger. + +'``llvm.stackprotector``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.stackprotector(i8* , i8** ) + +Overview: +""""""""" + +The ``llvm.stackprotector`` intrinsic takes the ``guard`` and stores it +onto the stack at ``slot``. The stack slot is adjusted to ensure that it +is placed on the stack before local variables. + +Arguments: +"""""""""" + +The ``llvm.stackprotector`` intrinsic requires two pointer arguments. +The first argument is the value loaded from the stack guard +``@__stack_chk_guard``. The second variable is an ``alloca`` that has +enough space to hold the value of the guard. + +Semantics: +"""""""""" + +This intrinsic causes the prologue/epilogue inserter to force the position of +the ``AllocaInst`` stack slot to be before local variables on the stack. This is +to ensure that if a local variable on the stack is overwritten, it will destroy +the value of the guard. When the function exits, the guard on the stack is +checked against the original guard by ``llvm.stackprotectorcheck``. If they are +different, then ``llvm.stackprotectorcheck`` causes the program to abort by +calling the ``__stack_chk_fail()`` function. + +'``llvm.stackprotectorcheck``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.stackprotectorcheck(i8** ) + +Overview: +""""""""" + +The ``llvm.stackprotectorcheck`` intrinsic compares ``guard`` against an already +created stack protector and if they are not equal calls the +``__stack_chk_fail()`` function. + +Arguments: +"""""""""" + +The ``llvm.stackprotectorcheck`` intrinsic requires one pointer argument, the +the variable ``@__stack_chk_guard``. + +Semantics: +"""""""""" + +This intrinsic is provided to perform the stack protector check by comparing +``guard`` with the stack slot created by ``llvm.stackprotector`` and if the +values do not match call the ``__stack_chk_fail()`` function. + +The reason to provide this as an IR level intrinsic instead of implementing it +via other IR operations is that in order to perform this operation at the IR +level without an intrinsic, one would need to create additional basic blocks to +handle the success/failure cases. This makes it difficult to stop the stack +protector check from disrupting sibling tail calls in Codegen. With this +intrinsic, we are able to generate the stack protector basic blocks late in +codegen after the tail call decision has occurred. + +'``llvm.objectsize``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i32 @llvm.objectsize.i32(i8* , i1 ) + declare i64 @llvm.objectsize.i64(i8* , i1 ) + +Overview: +""""""""" + +The ``llvm.objectsize`` intrinsic is designed to provide information to +the optimizers to determine at compile time whether a) an operation +(like memcpy) will overflow a buffer that corresponds to an object, or +b) that a runtime check for overflow isn't necessary. An object in this +context means an allocation of a specific class, structure, array, or +other object. + +Arguments: +"""""""""" + +The ``llvm.objectsize`` intrinsic takes two arguments. The first +argument is a pointer to or into the ``object``. The second argument is +a boolean and determines whether ``llvm.objectsize`` returns 0 (if true) +or -1 (if false) when the object size is unknown. The second argument +only accepts constants. + +Semantics: +"""""""""" + +The ``llvm.objectsize`` intrinsic is lowered to a constant representing +the size of the object concerned. If the size cannot be determined at +compile time, ``llvm.objectsize`` returns ``i32/i64 -1 or 0`` (depending +on the ``min`` argument). + +'``llvm.expect``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i32 @llvm.expect.i32(i32 , i32 ) + declare i64 @llvm.expect.i64(i64 , i64 ) + +Overview: +""""""""" + +The ``llvm.expect`` intrinsic provides information about expected (the +most probable) value of ``val``, which can be used by optimizers. + +Arguments: +"""""""""" + +The ``llvm.expect`` intrinsic takes two arguments. The first argument is +a value. The second argument is an expected value, this needs to be a +constant value, variables are not allowed. + +Semantics: +"""""""""" + +This intrinsic is lowered to the ``val``. + +'``llvm.donothing``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.donothing() nounwind readnone + +Overview: +""""""""" + +The ``llvm.donothing`` intrinsic doesn't perform any operation. It's the +only intrinsic that can be called with an invoke instruction. + +Arguments: +"""""""""" + +None. + +Semantics: +"""""""""" + +This intrinsic does nothing, and it's removed by optimizers and ignored +by codegen. diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst new file mode 100644 index 00000000..11f1341f --- /dev/null +++ b/docs/Lexicon.rst @@ -0,0 +1,222 @@ +================ +The LLVM Lexicon +================ + +.. note:: + + This document is a work in progress! + +Definitions +=========== + +A +- + +**ADCE** + Aggressive Dead Code Elimination + +**AST** + Abstract Syntax Tree. + + Due to Clang's influence (mostly the fact that parsing and semantic + analysis are so intertwined for C and especially C++), the typical + working definition of AST in the LLVM community is roughly "the + compiler's first complete symbolic (as opposed to textual) + representation of an input program". + As such, an "AST" might be a more general graph instead of a "tree" + (consider the symbolic representation for the type of a typical "linked + list node"). This working definition is closer to what some authors + call an "annotated abstract syntax tree". + + Consult your favorite compiler book or search engine for more details. + +B +- + +.. _lexicon-bb-vectorization: + +**BB Vectorization** + Basic-Block Vectorization + +**BURS** + Bottom Up Rewriting System --- A method of instruction selection for code + generation. An example is the `BURG + `_ tool. + +C +- + +**CSE** + Common Subexpression Elimination. An optimization that removes common + subexpression compuation. For example ``(a+b)*(a+b)`` has two subexpressions + that are the same: ``(a+b)``. This optimization would perform the addition + only once and then perform the multiply (but only if it's compulationally + correct/safe). + +D +- + +**DAG** + Directed Acyclic Graph + +.. _derived pointer: +.. _derived pointers: + +**Derived Pointer** + A pointer to the interior of an object, such that a garbage collector is + unable to use the pointer for reachability analysis. While a derived pointer + is live, the corresponding object pointer must be kept in a root, otherwise + the collector might free the referenced object. With copying collectors, + derived pointers pose an additional hazard that they may be invalidated at + any `safe point`_. This term is used in opposition to `object pointer`_. + +**DSA** + Data Structure Analysis + +**DSE** + Dead Store Elimination + +F +- + +**FCA** + First Class Aggregate + +G +- + +**GC** + Garbage Collection. The practice of using reachability analysis instead of + explicit memory management to reclaim unused memory. + +H +- + +.. _heap: + +**Heap** + In garbage collection, the region of memory which is managed using + reachability analysis. + +I +- + +**IPA** + Inter-Procedural Analysis. Refers to any variety of code analysis that + occurs between procedures, functions or compilation units (modules). + +**IPO** + Inter-Procedural Optimization. Refers to any variety of code optimization + that occurs between procedures, functions or compilation units (modules). + +**ISel** + Instruction Selection + +L +- + +**LCSSA** + Loop-Closed Static Single Assignment Form + +**LICM** + Loop Invariant Code Motion + +**Load-VN** + Load Value Numbering + +**LTO** + Link-Time Optimization + +M +- + +**MC** + Machine Code + +O +- +.. _object pointer: +.. _object pointers: + +**Object Pointer** + A pointer to an object such that the garbage collector is able to trace + references contained within the object. This term is used in opposition to + `derived pointer`_. + +P +- + +**PRE** + Partial Redundancy Elimination + +R +- + +**RAUW** + + Replace All Uses With. The functions ``User::replaceUsesOfWith()``, + ``Value::replaceAllUsesWith()``, and + ``Constant::replaceUsesOfWithOnConstant()`` implement the replacement of one + Value with another by iterating over its def/use chain and fixing up all of + the pointers to point to the new value. See + also `def/use chains `_. + +**Reassociation** + Rearranging associative expressions to promote better redundancy elimination + and other optimization. For example, changing ``(A+B-A)`` into ``(B+A-A)``, + permitting it to be optimized into ``(B+0)`` then ``(B)``. + +.. _roots: +.. _stack roots: + +**Root** + In garbage collection, a pointer variable lying outside of the `heap`_ from + which the collector begins its reachability analysis. In the context of code + generation, "root" almost always refers to a "stack root" --- a local or + temporary variable within an executing function. + +**RPO** + Reverse postorder + +S +- + +.. _safe point: + +**Safe Point** + In garbage collection, it is necessary to identify `stack roots`_ so that + reachability analysis may proceed. It may be infeasible to provide this + information for every instruction, so instead the information may is + calculated only at designated safe points. With a copying collector, + `derived pointers`_ must not be retained across safe points and `object + pointers`_ must be reloaded from stack roots. + +**SDISel** + Selection DAG Instruction Selection. + +**SCC** + Strongly Connected Component + +**SCCP** + Sparse Conditional Constant Propagation + +**SLP** + Superword-Level Parallelism, same as :ref:`Basic-Block Vectorization + `. + +**SRoA** + Scalar Replacement of Aggregates + +**SSA** + Static Single Assignment + +**Stack Map** + In garbage collection, metadata emitted by the code generator which + identifies `roots`_ within the stack frame of an executing function. + +T +- + +**TBAA** + Type-Based Alias Analysis + diff --git a/docs/LinkTimeOptimization.rst b/docs/LinkTimeOptimization.rst new file mode 100644 index 00000000..c15abd32 --- /dev/null +++ b/docs/LinkTimeOptimization.rst @@ -0,0 +1,299 @@ +====================================================== +LLVM Link Time Optimization: Design and Implementation +====================================================== + +.. contents:: + :local: + +Description +=========== + +LLVM features powerful intermodular optimizations which can be used at link +time. Link Time Optimization (LTO) is another name for intermodular +optimization when performed during the link stage. This document describes the +interface and design between the LTO optimizer and the linker. + +Design Philosophy +================= + +The LLVM Link Time Optimizer provides complete transparency, while doing +intermodular optimization, in the compiler tool chain. Its main goal is to let +the developer take advantage of intermodular optimizations without making any +significant changes to the developer's makefiles or build system. This is +achieved through tight integration with the linker. In this model, the linker +treates LLVM bitcode files like native object files and allows mixing and +matching among them. The linker uses `libLTO`_, a shared object, to handle LLVM +bitcode files. This tight integration between the linker and LLVM optimizer +helps to do optimizations that are not possible in other models. The linker +input allows the optimizer to avoid relying on conservative escape analysis. + +.. _libLTO-example: + +Example of link time optimization +--------------------------------- + +The following example illustrates the advantages of LTO's integrated approach +and clean interface. This example requires a system linker which supports LTO +through the interface described in this document. Here, clang transparently +invokes system linker. + +* Input source file ``a.c`` is compiled into LLVM bitcode form. +* Input source file ``main.c`` is compiled into native object code. + +.. code-block:: c++ + + --- a.h --- + extern int foo1(void); + extern void foo2(void); + extern void foo4(void); + + --- a.c --- + #include "a.h" + + static signed int i = 0; + + void foo2(void) { + i = -1; + } + + static int foo3() { + foo4(); + return 10; + } + + int foo1(void) { + int data = 0; + + if (i < 0) + data = foo3(); + + data = data + 42; + return data; + } + + --- main.c --- + #include + #include "a.h" + + void foo4(void) { + printf("Hi\n"); + } + + int main() { + return foo1(); + } + +To compile, run: + +.. code-block:: console + + % clang -emit-llvm -c a.c -o a.o # <-- a.o is LLVM bitcode file + % clang -c main.c -o main.o # <-- main.o is native object file + % clang a.o main.o -o main # <-- standard link command without modifications + +* In this example, the linker recognizes that ``foo2()`` is an externally + visible symbol defined in LLVM bitcode file. The linker completes its usual + symbol resolution pass and finds that ``foo2()`` is not used + anywhere. This information is used by the LLVM optimizer and it + removes ``foo2()``. + +* As soon as ``foo2()`` is removed, the optimizer recognizes that condition ``i + < 0`` is always false, which means ``foo3()`` is never used. Hence, the + optimizer also removes ``foo3()``. + +* And this in turn, enables linker to remove ``foo4()``. + +This example illustrates the advantage of tight integration with the +linker. Here, the optimizer can not remove ``foo3()`` without the linker's +input. + +Alternative Approaches +---------------------- + +**Compiler driver invokes link time optimizer separately.** + In this model the link time optimizer is not able to take advantage of + information collected during the linker's normal symbol resolution phase. + In the above example, the optimizer can not remove ``foo2()`` without the + linker's input because it is externally visible. This in turn prohibits the + optimizer from removing ``foo3()``. + +**Use separate tool to collect symbol information from all object files.** + In this model, a new, separate, tool or library replicates the linker's + capability to collect information for link time optimization. Not only is + this code duplication difficult to justify, but it also has several other + disadvantages. For example, the linking semantics and the features provided + by the linker on various platform are not unique. This means, this new tool + needs to support all such features and platforms in one super tool or a + separate tool per platform is required. This increases maintenance cost for + link time optimizer significantly, which is not necessary. This approach + also requires staying synchronized with linker developements on various + platforms, which is not the main focus of the link time optimizer. Finally, + this approach increases end user's build time due to the duplication of work + done by this separate tool and the linker itself. + +Multi-phase communication between ``libLTO`` and linker +======================================================= + +The linker collects information about symbol defininitions and uses in various +link objects which is more accurate than any information collected by other +tools during typical build cycles. The linker collects this information by +looking at the definitions and uses of symbols in native .o files and using +symbol visibility information. The linker also uses user-supplied information, +such as a list of exported symbols. LLVM optimizer collects control flow +information, data flow information and knows much more about program structure +from the optimizer's point of view. Our goal is to take advantage of tight +integration between the linker and the optimizer by sharing this information +during various linking phases. + +Phase 1 : Read LLVM Bitcode Files +--------------------------------- + +The linker first reads all object files in natural order and collects symbol +information. This includes native object files as well as LLVM bitcode files. +To minimize the cost to the linker in the case that all .o files are native +object files, the linker only calls ``lto_module_create()`` when a supplied +object file is found to not be a native object file. If ``lto_module_create()`` +returns that the file is an LLVM bitcode file, the linker then iterates over the +module using ``lto_module_get_symbol_name()`` and +``lto_module_get_symbol_attribute()`` to get all symbols defined and referenced. +This information is added to the linker's global symbol table. + + +The lto* functions are all implemented in a shared object libLTO. This allows +the LLVM LTO code to be updated independently of the linker tool. On platforms +that support it, the shared object is lazily loaded. + +Phase 2 : Symbol Resolution +--------------------------- + +In this stage, the linker resolves symbols using global symbol table. It may +report undefined symbol errors, read archive members, replace weak symbols, etc. +The linker is able to do this seamlessly even though it does not know the exact +content of input LLVM bitcode files. If dead code stripping is enabled then the +linker collects the list of live symbols. + +Phase 3 : Optimize Bitcode Files +-------------------------------- + +After symbol resolution, the linker tells the LTO shared object which symbols +are needed by native object files. In the example above, the linker reports +that only ``foo1()`` is used by native object files using +``lto_codegen_add_must_preserve_symbol()``. Next the linker invokes the LLVM +optimizer and code generators using ``lto_codegen_compile()`` which returns a +native object file creating by merging the LLVM bitcode files and applying +various optimization passes. + +Phase 4 : Symbol Resolution after optimization +---------------------------------------------- + +In this phase, the linker reads optimized a native object file and updates the +internal global symbol table to reflect any changes. The linker also collects +information about any changes in use of external symbols by LLVM bitcode +files. In the example above, the linker notes that ``foo4()`` is not used any +more. If dead code stripping is enabled then the linker refreshes the live +symbol information appropriately and performs dead code stripping. + +After this phase, the linker continues linking as if it never saw LLVM bitcode +files. + +.. _libLTO: + +``libLTO`` +========== + +``libLTO`` is a shared object that is part of the LLVM tools, and is intended +for use by a linker. ``libLTO`` provides an abstract C interface to use the LLVM +interprocedural optimizer without exposing details of LLVM's internals. The +intention is to keep the interface as stable as possible even when the LLVM +optimizer continues to evolve. It should even be possible for a completely +different compilation technology to provide a different libLTO that works with +their object files and the standard linker tool. + +``lto_module_t`` +---------------- + +A non-native object file is handled via an ``lto_module_t``. The following +functions allow the linker to check if a file (on disk or in a memory buffer) is +a file which libLTO can process: + +.. code-block:: c + + lto_module_is_object_file(const char*) + lto_module_is_object_file_for_target(const char*, const char*) + lto_module_is_object_file_in_memory(const void*, size_t) + lto_module_is_object_file_in_memory_for_target(const void*, size_t, const char*) + +If the object file can be processed by ``libLTO``, the linker creates a +``lto_module_t`` by using one of: + +.. code-block:: c + + lto_module_create(const char*) + lto_module_create_from_memory(const void*, size_t) + +and when done, the handle is released via + +.. code-block:: c + + lto_module_dispose(lto_module_t) + + +The linker can introspect the non-native object file by getting the number of +symbols and getting the name and attributes of each symbol via: + +.. code-block:: c + + lto_module_get_num_symbols(lto_module_t) + lto_module_get_symbol_name(lto_module_t, unsigned int) + lto_module_get_symbol_attribute(lto_module_t, unsigned int) + +The attributes of a symbol include the alignment, visibility, and kind. + +``lto_code_gen_t`` +------------------ + +Once the linker has loaded each non-native object files into an +``lto_module_t``, it can request ``libLTO`` to process them all and generate a +native object file. This is done in a couple of steps. First, a code generator +is created with: + +.. code-block:: c + + lto_codegen_create() + +Then, each non-native object file is added to the code generator with: + +.. code-block:: c + + lto_codegen_add_module(lto_code_gen_t, lto_module_t) + +The linker then has the option of setting some codegen options. Whether or not +to generate DWARF debug info is set with: + +.. code-block:: c + + lto_codegen_set_debug_model(lto_code_gen_t) + +Which kind of position independence is set with: + +.. code-block:: c + + lto_codegen_set_pic_model(lto_code_gen_t) + +And each symbol that is referenced by a native object file or otherwise must not +be optimized away is set with: + +.. code-block:: c + + lto_codegen_add_must_preserve_symbol(lto_code_gen_t, const char*) + +After all these settings are done, the linker requests that a native object file +be created from the modules with the settings using: + +.. code-block:: c + + lto_codegen_compile(lto_code_gen_t, size*) + +which returns a pointer to a buffer containing the generated native object file. +The linker then parses that and links it with the rest of the native object +files. diff --git a/docs/MCJIT-creation.png b/docs/MCJIT-creation.png new file mode 100644 index 00000000..7abdb9df Binary files /dev/null and b/docs/MCJIT-creation.png differ diff --git a/docs/MCJIT-dyld-load.png b/docs/MCJIT-dyld-load.png new file mode 100644 index 00000000..15341903 Binary files /dev/null and b/docs/MCJIT-dyld-load.png differ diff --git a/docs/MCJIT-engine-builder.png b/docs/MCJIT-engine-builder.png new file mode 100644 index 00000000..8fdd7a94 Binary files /dev/null and b/docs/MCJIT-engine-builder.png differ diff --git a/docs/MCJIT-load-object.png b/docs/MCJIT-load-object.png new file mode 100644 index 00000000..533a52e1 Binary files /dev/null and b/docs/MCJIT-load-object.png differ diff --git a/docs/MCJIT-load.png b/docs/MCJIT-load.png new file mode 100644 index 00000000..9672a663 Binary files /dev/null and b/docs/MCJIT-load.png differ diff --git a/docs/MCJIT-resolve-relocations.png b/docs/MCJIT-resolve-relocations.png new file mode 100644 index 00000000..fedeacc4 Binary files /dev/null and b/docs/MCJIT-resolve-relocations.png differ diff --git a/docs/MCJITDesignAndImplementation.rst b/docs/MCJITDesignAndImplementation.rst new file mode 100644 index 00000000..2cb62964 --- /dev/null +++ b/docs/MCJITDesignAndImplementation.rst @@ -0,0 +1,180 @@ +=============================== +MCJIT Design and Implementation +=============================== + +Introduction +============ + +This document describes the internal workings of the MCJIT execution +engine and the RuntimeDyld component. It is intended as a high level +overview of the implementation, showing the flow and interactions of +objects throughout the code generation and dynamic loading process. + +Engine Creation +=============== + +In most cases, an EngineBuilder object is used to create an instance of +the MCJIT execution engine. The EngineBuilder takes an llvm::Module +object as an argument to its constructor. The client may then set various +options that we control the later be passed along to the MCJIT engine, +including the selection of MCJIT as the engine type to be created. +Of particular interest is the EngineBuilder::setMCJITMemoryManager +function. If the client does not explicitly create a memory manager at +this time, a default memory manager (specifically SectionMemoryManager) +will be created when the MCJIT engine is instantiated. + +Once the options have been set, a client calls EngineBuilder::create to +create an instance of the MCJIT engine. If the client does not use the +form of this function that takes a TargetMachine as a parameter, a new +TargetMachine will be created based on the target triple associated with +the Module that was used to create the EngineBuilder. + +.. image:: MCJIT-engine-builder.png + +EngineBuilder::create will call the static MCJIT::createJIT function, +passing in its pointers to the module, memory manager and target machine +objects, all of which will subsequently be owned by the MCJIT object. + +The MCJIT class has a member variable, Dyld, which contains an instance of +the RuntimeDyld wrapper class. This member will be used for +communications between MCJIT and the actual RuntimeDyldImpl object that +gets created when an object is loaded. + +.. image:: MCJIT-creation.png + +Upon creation, MCJIT holds a pointer to the Module object that it received +from EngineBuilder but it does not immediately generate code for this +module. Code generation is deferred until either the +MCJIT::finalizeObject method is called explicitly or a function such as +MCJIT::getPointerToFunction is called which requires the code to have been +generated. + +Code Generation +=============== + +When code generation is triggered, as described above, MCJIT will first +attempt to retrieve an object image from its ObjectCache member, if one +has been set. If a cached object image cannot be retrieved, MCJIT will +call its emitObject method. MCJIT::emitObject uses a local PassManager +instance and creates a new ObjectBufferStream instance, both of which it +passes to TargetManager::addPassesToEmitMC before calling PassManager::run +on the Module with which it was created. + +.. image:: MCJIT-load.png + +The PassManager::run call causes the MC code generation mechanisms to emit +a complete relocatable binary object image (either in either ELF or MachO +format, depending on the target) into the ObjectBufferStream object, which +is flushed to complete the process. If an ObjectCache is being used, the +image will be passed to the ObjectCache here. + +At this point, the ObjectBufferStream contains the raw object image. +Before the code can be executed, the code and data sections from this +image must be loaded into suitable memory, relocations must be applied and +memory permission and code cache invalidation (if required) must be completed. + +Object Loading +============== + +Once an object image has been obtained, either through code generation or +having been retrieved from an ObjectCache, it is passed to RuntimeDyld to +be loaded. The RuntimeDyld wrapper class examines the object to determine +its file format and creates an instance of either RuntimeDyldELF or +RuntimeDyldMachO (both of which derive from the RuntimeDyldImpl base +class) and calls the RuntimeDyldImpl::loadObject method to perform that +actual loading. + +.. image:: MCJIT-dyld-load.png + +RuntimeDyldImpl::loadObject begins by creating an ObjectImage instance +from the ObjectBuffer it received. ObjectImage, which wraps the +ObjectFile class, is a helper class which parses the binary object image +and provides access to the information contained in the format-specific +headers, including section, symbol and relocation information. + +RuntimeDyldImpl::loadObject then iterates through the symbols in the +image. Information about common symbols is collected for later use. For +each function or data symbol, the associated section is loaded into memory +and the symbol is stored in a symbol table map data structure. When the +iteration is complete, a section is emitted for the common symbols. + +Next, RuntimeDyldImpl::loadObject iterates through the sections in the +object image and for each section iterates through the relocations for +that sections. For each relocation, it calls the format-specific +processRelocationRef method, which will examine the relocation and store +it in one of two data structures, a section-based relocation list map and +an external symbol relocation map. + +.. image:: MCJIT-load-object.png + +When RuntimeDyldImpl::loadObject returns, all of the code and data +sections for the object will have been loaded into memory allocated by the +memory manager and relocation information will have been prepared, but the +relocations have not yet been applied and the generated code is still not +ready to be executed. + +[Currently (as of August 2013) the MCJIT engine will immediately apply +relocations when loadObject completes. However, this shouldn't be +happening. Because the code may have been generated for a remote target, +the client should be given a chance to re-map the section addresses before +relocations are applied. It is possible to apply relocations multiple +times, but in the case where addresses are to be re-mapped, this first +application is wasted effort.] + +Address Remapping +================= + +At any time after initial code has been generated and before +finalizeObject is called, the client can remap the address of sections in +the object. Typically this is done because the code was generated for an +external process and is being mapped into that process' address space. +The client remaps the section address by calling MCJIT::mapSectionAddress. +This should happen before the section memory is copied to its new +location. + +When MCJIT::mapSectionAddress is called, MCJIT passes the call on to +RuntimeDyldImpl (via its Dyld member). RuntimeDyldImpl stores the new +address in an internal data structure but does not update the code at this +time, since other sections are likely to change. + +When the client is finished remapping section addresses, it will call +MCJIT::finalizeObject to complete the remapping process. + +Final Preparations +================== + +When MCJIT::finalizeObject is called, MCJIT calls +RuntimeDyld::resolveRelocations. This function will attempt to locate any +external symbols and then apply all relocations for the object. + +External symbols are resolved by calling the memory manager's +getPointerToNamedFunction method. The memory manager will return the +address of the requested symbol in the target address space. (Note, this +may not be a valid pointer in the host process.) RuntimeDyld will then +iterate through the list of relocations it has stored which are associated +with this symbol and invoke the resolveRelocation method which, through an +format-specific implementation, will apply the relocation to the loaded +section memory. + +Next, RuntimeDyld::resolveRelocations iterates through the list of +sections and for each section iterates through a list of relocations that +have been saved which reference that symbol and call resolveRelocation for +each entry in this list. The relocation list here is a list of +relocations for which the symbol associated with the relocation is located +in the section associated with the list. Each of these locations will +have a target location at which the relocation will be applied that is +likely located in a different section. + +.. image:: MCJIT-resolve-relocations.png + +Once relocations have been applied as described above, MCJIT calls +RuntimeDyld::getEHFrameSection, and if a non-zero result is returned +passes the section data to the memory manager's registerEHFrames method. +This allows the memory manager to call any desired target-specific +functions, such as registering the EH frame information with a debugger. + +Finally, MCJIT calls the memory manager's finalizeMemory method. In this +method, the memory manager will invalidate the target code cache, if +necessary, and apply final permissions to the memory pages it has +allocated for code and data memory. + diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d973af58 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,128 @@ +##===- docs/Makefile ---------------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := .. +DIRS := + +ifdef BUILD_FOR_WEBSITE +PROJ_OBJ_DIR = . +DOXYGEN = doxygen + +$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in + cat $< | sed \ + -e 's/@abs_top_srcdir@/../g' \ + -e 's/@DOT@/dot/g' \ + -e 's/@PACKAGE_VERSION@/mainline/' \ + -e 's/@abs_top_builddir@/../g' \ + -e 's/@enable_searchengine@/NO/g' \ + -e 's/@searchengine_url@//g' \ + -e 's/@enable_server_based_search@/NO/g' \ + -e 's/@enable_external_search@/NO/g' \ + -e 's/@extra_search_mappings@//g' > $@ +endif + +include $(LEVEL)/Makefile.common + +HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) \ + $(wildcard $(PROJ_SRC_DIR)/*.css) +DOXYFILES := doxygen.cfg.in doxygen.css doxygen.footer doxygen.header \ + doxygen.intro +EXTRA_DIST := $(HTML) $(DOXYFILES) llvm.css CommandGuide + +.PHONY: install-html install-doxygen doxygen install-ocamldoc ocamldoc generated + +install_targets := install-html +ifeq ($(ENABLE_DOXYGEN),1) +install_targets += install-doxygen +endif +ifdef OCAMLDOC +ifneq (,$(filter ocaml,$(BINDINGS_TO_BUILD))) +install_targets += install-ocamldoc +endif +endif +install-local:: $(install_targets) + +generated_targets := doxygen +ifdef OCAMLDOC +generated_targets += ocamldoc +endif + +# Live documentation is generated for the web site using this target: +# 'make generated BUILD_FOR_WEBSITE=1' +generated:: $(generated_targets) + +install-html: $(PROJ_OBJ_DIR)/html.tar.gz + $(Echo) Installing HTML documentation + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html + $(Verb) $(DataInstall) $(HTML) $(DESTDIR)$(PROJ_docsdir)/html + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(DESTDIR)$(PROJ_docsdir) + +$(PROJ_OBJ_DIR)/html.tar.gz: $(HTML) + $(Echo) Packaging HTML documentation + $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/html.tar + $(Verb) cd $(PROJ_SRC_DIR) && \ + $(TAR) cf $(PROJ_OBJ_DIR)/html.tar *.html + $(Verb) $(GZIPBIN) $(PROJ_OBJ_DIR)/html.tar + +install-doxygen: doxygen + $(Echo) Installing doxygen documentation + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/doxygen + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(DESTDIR)$(PROJ_docsdir) + $(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \ + $(FIND) . -type f -exec \ + $(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/html/doxygen \; + +doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz + +regendoc: + $(Echo) Building doxygen documentation + $(Verb) $(RM) -rf $(PROJ_OBJ_DIR)/doxygen + $(Verb) $(DOXYGEN) $(PROJ_OBJ_DIR)/doxygen.cfg + +$(PROJ_OBJ_DIR)/doxygen.tar.gz: $(DOXYFILES) $(PROJ_OBJ_DIR)/doxygen.cfg + $(Echo) Packaging doxygen documentation + $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/doxygen.tar + $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/doxygen.tar doxygen + $(Verb) $(GZIPBIN) $(PROJ_OBJ_DIR)/doxygen.tar + $(Verb) $(CP) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_OBJ_DIR)/doxygen/html/ + +userloc: $(LLVM_SRC_ROOT)/docs/userloc.html + +$(LLVM_SRC_ROOT)/docs/userloc.html: + $(Echo) Making User LOC Table + $(Verb) cd $(LLVM_SRC_ROOT) ; ./utils/userloc.pl -details -recurse \ + -html lib include tools runtime utils examples autoconf test > docs/userloc.html + +install-ocamldoc: ocamldoc + $(Echo) Installing ocamldoc documentation + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/ocamldoc/html + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(DESTDIR)$(PROJ_docsdir) + $(Verb) cd $(PROJ_OBJ_DIR)/ocamldoc && \ + $(FIND) . -type f -exec \ + $(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/ocamldoc/html \; + +ocamldoc: regen-ocamldoc + $(Echo) Packaging ocamldoc documentation + $(Verb) $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc.tar* + $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/ocamldoc.tar ocamldoc + $(Verb) $(GZIPBIN) $(PROJ_OBJ_DIR)/ocamldoc.tar + $(Verb) $(CP) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_OBJ_DIR)/ocamldoc/html/ + +regen-ocamldoc: + $(Echo) Building ocamldoc documentation + $(Verb) $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc + $(Verb) $(MAKE) -C $(LEVEL)/bindings/ocaml ocamldoc + $(Verb) $(MKDIR) $(PROJ_OBJ_DIR)/ocamldoc/html + $(Verb) \ + $(OCAMLDOC) -d $(PROJ_OBJ_DIR)/ocamldoc/html -sort -colorize-code -html \ + `$(FIND) $(LEVEL)/bindings/ocaml -name "*.odoc" -exec echo -load '{}' ';'` + +uninstall-local:: + $(Echo) Uninstalling Documentation + $(Verb) $(RM) -rf $(DESTDIR)$(PROJ_docsdir) diff --git a/docs/Makefile.sphinx b/docs/Makefile.sphinx new file mode 100644 index 00000000..21f66488 --- /dev/null +++ b/docs/Makefile.sphinx @@ -0,0 +1,155 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +all: html + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/llvm.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/llvm.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/llvm" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/llvm" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/MakefileGuide.rst b/docs/MakefileGuide.rst new file mode 100644 index 00000000..120c108d --- /dev/null +++ b/docs/MakefileGuide.rst @@ -0,0 +1,918 @@ +=================== +LLVM Makefile Guide +=================== + +.. contents:: + :local: + +Introduction +============ + +This document provides *usage* information about the LLVM makefile system. While +loosely patterned after the BSD makefile system, LLVM has taken a departure from +BSD in order to implement additional features needed by LLVM. Although makefile +systems, such as ``automake``, were attempted at one point, it has become clear +that the features needed by LLVM and the ``Makefile`` norm are too great to use +a more limited tool. Consequently, LLVM requires simply GNU Make 3.79, a widely +portable makefile processor. LLVM unabashedly makes heavy use of the features of +GNU Make so the dependency on GNU Make is firm. If you're not familiar with +``make``, it is recommended that you read the `GNU Makefile Manual +`_. + +While this document is rightly part of the `LLVM Programmer's +Manual `_, it is treated separately here because of the +volume of content and because it is often an early source of bewilderment for +new developers. + +General Concepts +================ + +The LLVM Makefile System is the component of LLVM that is responsible for +building the software, testing it, generating distributions, checking those +distributions, installing and uninstalling, etc. It consists of a several files +throughout the source tree. These files and other general concepts are described +in this section. + +Projects +-------- + +The LLVM Makefile System is quite generous. It not only builds its own software, +but it can build yours too. Built into the system is knowledge of the +``llvm/projects`` directory. Any directory under ``projects`` that has both a +``configure`` script and a ``Makefile`` is assumed to be a project that uses the +LLVM Makefile system. Building software that uses LLVM does not require the +LLVM Makefile System nor even placement in the ``llvm/projects`` +directory. However, doing so will allow your project to get up and running +quickly by utilizing the built-in features that are used to compile LLVM. LLVM +compiles itself using the same features of the makefile system as used for +projects. + +For complete details on setting up your projects configuration, simply mimic the +``llvm/projects/sample`` project. Or for further details, consult the +`Projects `_ page. + +Variable Values +--------------- + +To use the makefile system, you simply create a file named ``Makefile`` in your +directory and declare values for certain variables. The variables and values +that you select determine what the makefile system will do. These variables +enable rules and processing in the makefile system that automatically Do The +Right Thing (C). + +Including Makefiles +------------------- + +Setting variables alone is not enough. You must include into your Makefile +additional files that provide the rules of the LLVM Makefile system. The various +files involved are described in the sections that follow. + +``Makefile`` +^^^^^^^^^^^^ + +Each directory to participate in the build needs to have a file named +``Makefile``. This is the file first read by ``make``. It has three +sections: + +#. Settable Variables --- Required that must be set first. +#. ``include $(LEVEL)/Makefile.common`` --- include the LLVM Makefile system. +#. Override Variables --- Override variables set by the LLVM Makefile system. + +.. _$(LEVEL)/Makefile.common: + +``Makefile.common`` +^^^^^^^^^^^^^^^^^^^ + +Every project must have a ``Makefile.common`` file at its top source +directory. This file serves three purposes: + +#. It includes the project's configuration makefile to obtain values determined + by the ``configure`` script. This is done by including the + `$(LEVEL)/Makefile.config`_ file. + +#. It specifies any other (static) values that are needed throughout the + project. Only values that are used in all or a large proportion of the + project's directories should be placed here. + +#. It includes the standard rules for the LLVM Makefile system, + `$(LLVM_SRC_ROOT)/Makefile.rules`_. This file is the *guts* of the LLVM + ``Makefile`` system. + +.. _$(LEVEL)/Makefile.config: + +``Makefile.config`` +^^^^^^^^^^^^^^^^^^^ + +Every project must have a ``Makefile.config`` at the top of its *build* +directory. This file is **generated** by the ``configure`` script from the +pattern provided by the ``Makefile.config.in`` file located at the top of the +project's *source* directory. The contents of this file depend largely on what +configuration items the project uses, however most projects can get what they +need by just relying on LLVM's configuration found in +``$(LLVM_OBJ_ROOT)/Makefile.config``. + +.. _$(LLVM_SRC_ROOT)/Makefile.rules: + +``Makefile.rules`` +^^^^^^^^^^^^^^^^^^ + +This file, located at ``$(LLVM_SRC_ROOT)/Makefile.rules`` is the heart of the +LLVM Makefile System. It provides all the logic, dependencies, and rules for +building the targets supported by the system. What it does largely depends on +the values of ``make`` `variables`_ that have been set *before* +``Makefile.rules`` is included. + +Comments +^^^^^^^^ + +User ``Makefile``\s need not have comments in them unless the construction is +unusual or it does not strictly follow the rules and patterns of the LLVM +makefile system. Makefile comments are invoked with the pound (``#``) character. +The ``#`` character and any text following it, to the end of the line, are +ignored by ``make``. + +Tutorial +======== + +This section provides some examples of the different kinds of modules you can +build with the LLVM makefile system. In general, each directory you provide will +build a single object although that object may be composed of additionally +compiled components. + +Libraries +--------- + +Only a few variable definitions are needed to build a regular library. +Normally, the makefile system will build all the software into a single +``libname.o`` (pre-linked) object. This means the library is not searchable and +that the distinction between compilation units has been dissolved. Optionally, +you can ask for a shared library (.so) or archive library (.a) built. Archive +libraries are the default. For example: + +.. code-block:: makefile + + LIBRARYNAME = mylib + SHARED_LIBRARY = 1 + BUILD_ARCHIVE = 1 + +says to build a library named ``mylib`` with both a shared library +(``mylib.so``) and an archive library (``mylib.a``) version. The contents of all +the libraries produced will be the same, they are just constructed differently. +Note that you normally do not need to specify the sources involved. The LLVM +Makefile system will infer the source files from the contents of the source +directory. + +The ``LOADABLE_MODULE=1`` directive can be used in conjunction with +``SHARED_LIBRARY=1`` to indicate that the resulting shared library should be +openable with the ``dlopen`` function and searchable with the ``dlsym`` function +(or your operating system's equivalents). While this isn't strictly necessary on +Linux and a few other platforms, it is required on systems like HP-UX and +Darwin. You should use ``LOADABLE_MODULE`` for any shared library that you +intend to be loaded into an tool via the ``-load`` option. :ref:`Pass +documentation ` has an example of why you might +want to do this. + +Loadable Modules +^^^^^^^^^^^^^^^^ + +In some situations, you need to create a loadable module. Loadable modules can +be loaded into programs like ``opt`` or ``llc`` to specify additional passes to +run or targets to support. Loadable modules are also useful for debugging a +pass or providing a pass with another package if that pass can't be included in +LLVM. + +LLVM provides complete support for building such a module. All you need to do is +use the ``LOADABLE_MODULE`` variable in your ``Makefile``. For example, to build +a loadable module named ``MyMod`` that uses the LLVM libraries ``LLVMSupport.a`` +and ``LLVMSystem.a``, you would specify: + +.. code-block:: makefile + + LIBRARYNAME := MyMod + LOADABLE_MODULE := 1 + LINK_COMPONENTS := support system + +Use of the ``LOADABLE_MODULE`` facility implies several things: + +#. There will be no "``lib``" prefix on the module. This differentiates it from + a standard shared library of the same name. + +#. The `SHARED_LIBRARY`_ variable is turned on. + +#. The `LINK_LIBS_IN_SHARED`_ variable is turned on. + +A loadable module is loaded by LLVM via the facilities of libtool's libltdl +library which is part of ``lib/System`` implementation. + +Tools +----- + +For building executable programs (tools), you must provide the name of the tool +and the names of the libraries you wish to link with the tool. For example: + +.. code-block:: makefile + + TOOLNAME = mytool + USEDLIBS = mylib + LINK_COMPONENTS = support system + +says that we are to build a tool name ``mytool`` and that it requires three +libraries: ``mylib``, ``LLVMSupport.a`` and ``LLVMSystem.a``. + +Note that two different variables are used to indicate which libraries are +linked: ``USEDLIBS`` and ``LLVMLIBS``. This distinction is necessary to support +projects. ``LLVMLIBS`` refers to the LLVM libraries found in the LLVM object +directory. ``USEDLIBS`` refers to the libraries built by your project. In the +case of building LLVM tools, ``USEDLIBS`` and ``LLVMLIBS`` can be used +interchangeably since the "project" is LLVM itself and ``USEDLIBS`` refers to +the same place as ``LLVMLIBS``. + +Also note that there are two different ways of specifying a library: with a +``.a`` suffix and without. Without the suffix, the entry refers to the re-linked +(.o) file which will include *all* symbols of the library. This is +useful, for example, to include all passes from a library of passes. If the +``.a`` suffix is used then the library is linked as a searchable library (with +the ``-l`` option). In this case, only the symbols that are unresolved *at +that point* will be resolved from the library, if they exist. Other +(unreferenced) symbols will not be included when the ``.a`` syntax is used. Note +that in order to use the ``.a`` suffix, the library in question must have been +built with the ``BUILD_ARCHIVE`` option set. + +JIT Tools +^^^^^^^^^ + +Many tools will want to use the JIT features of LLVM. To do this, you simply +specify that you want an execution 'engine', and the makefiles will +automatically link in the appropriate JIT for the host or an interpreter if none +is available: + +.. code-block:: makefile + + TOOLNAME = my_jit_tool + USEDLIBS = mylib + LINK_COMPONENTS = engine + +Of course, any additional libraries may be listed as other components. To get a +full understanding of how this changes the linker command, it is recommended +that you: + +.. code-block:: bash + + % cd examples/Fibonacci + % make VERBOSE=1 + +Targets Supported +================= + +This section describes each of the targets that can be built using the LLVM +Makefile system. Any target can be invoked from any directory but not all are +applicable to a given directory (e.g. "check", "dist" and "install" will always +operate as if invoked from the top level directory). + +================= =============== ================== +Target Name Implied Targets Target Description +================= =============== ================== +``all`` \ Compile the software recursively. Default target. +``all-local`` \ Compile the software in the local directory only. +``check`` \ Change to the ``test`` directory in a project and run the test suite there. +``check-local`` \ Run a local test suite. Generally this is only defined in the ``Makefile`` of the project's ``test`` directory. +``clean`` \ Remove built objects recursively. +``clean-local`` \ Remove built objects from the local directory only. +``dist`` ``all`` Prepare a source distribution tarball. +``dist-check`` ``all`` Prepare a source distribution tarball and check that it builds. +``dist-clean`` ``clean`` Clean source distribution tarball temporary files. +``install`` ``all`` Copy built objects to installation directory. +``preconditions`` ``all`` Check to make sure configuration and makefiles are up to date. +``printvars`` ``all`` Prints variables defined by the makefile system (for debugging). +``tags`` \ Make C and C++ tags files for emacs and vi. +``uninstall`` \ Remove built objects from installation directory. +================= =============== ================== + +.. _all: + +``all`` (default) +----------------- + +When you invoke ``make`` with no arguments, you are implicitly instructing it to +seek the ``all`` target (goal). This target is used for building the software +recursively and will do different things in different directories. For example, +in a ``lib`` directory, the ``all`` target will compile source files and +generate libraries. But, in a ``tools`` directory, it will link libraries and +generate executables. + +``all-local`` +------------- + +This target is the same as `all`_ but it operates only on the current directory +instead of recursively. + +``check`` +--------- + +This target can be invoked from anywhere within a project's directories but +always invokes the `check-local`_ target in the project's ``test`` directory, if +it exists and has a ``Makefile``. A warning is produced otherwise. If +`TESTSUITE`_ is defined on the ``make`` command line, it will be passed down to +the invocation of ``make check-local`` in the ``test`` directory. The intended +usage for this is to assist in running specific suites of tests. If +``TESTSUITE`` is not set, the implementation of ``check-local`` should run all +normal tests. It is up to the project to define what different values for +``TESTSUTE`` will do. See the :doc:`Testing Guide ` for further +details. + +``check-local`` +--------------- + +This target should be implemented by the ``Makefile`` in the project's ``test`` +directory. It is invoked by the ``check`` target elsewhere. Each project is +free to define the actions of ``check-local`` as appropriate for that +project. The LLVM project itself uses the :doc:`Lit ` testing +tool to run a suite of feature and regression tests. Other projects may choose +to use :program:`lit` or any other testing mechanism. + +``clean`` +--------- + +This target cleans the build directory, recursively removing all things that the +Makefile builds. The cleaning rules have been made guarded so they shouldn't go +awry (via ``rm -f $(UNSET_VARIABLE)/*`` which will attempt to erase the entire +directory structure). + +``clean-local`` +--------------- + +This target does the same thing as ``clean`` but only for the current (local) +directory. + +``dist`` +-------- + +This target builds a distribution tarball. It first builds the entire project +using the ``all`` target and then tars up the necessary files and compresses +it. The generated tarball is sufficient for a casual source distribution, but +probably not for a release (see ``dist-check``). + +``dist-check`` +-------------- + +This target does the same thing as the ``dist`` target but also checks the +distribution tarball. The check is made by unpacking the tarball to a new +directory, configuring it, building it, installing it, and then verifying that +the installation results are correct (by comparing to the original build). This +target can take a long time to run but should be done before a release goes out +to make sure that the distributed tarball can actually be built into a working +release. + +``dist-clean`` +-------------- + +This is a special form of the ``clean`` clean target. It performs a normal +``clean`` but also removes things pertaining to building the distribution. + +``install`` +----------- + +This target finalizes shared objects and executables and copies all libraries, +headers, executables and documentation to the directory given with the +``--prefix`` option to ``configure``. When completed, the prefix directory will +have everything needed to **use** LLVM. + +The LLVM makefiles can generate complete **internal** documentation for all the +classes by using ``doxygen``. By default, this feature is **not** enabled +because it takes a long time and generates a massive amount of data (>100MB). If +you want this feature, you must configure LLVM with the --enable-doxygen switch +and ensure that a modern version of doxygen (1.3.7 or later) is available in +your ``PATH``. You can download doxygen from `here +`_. + +``preconditions`` +----------------- + +This utility target checks to see if the ``Makefile`` in the object directory is +older than the ``Makefile`` in the source directory and copies it if so. It also +reruns the ``configure`` script if that needs to be done and rebuilds the +``Makefile.config`` file similarly. Users may overload this target to ensure +that sanity checks are run *before* any building of targets as all the targets +depend on ``preconditions``. + +``printvars`` +------------- + +This utility target just causes the LLVM makefiles to print out some of the +makefile variables so that you can double check how things are set. + +``reconfigure`` +--------------- + +This utility target will force a reconfigure of LLVM or your project. It simply +runs ``$(PROJ_OBJ_ROOT)/config.status --recheck`` to rerun the configuration +tests and rebuild the configured files. This isn't generally useful as the +makefiles will reconfigure themselves whenever its necessary. + +``spotless`` +------------ + +.. warning:: + + Use with caution! + +This utility target, only available when ``$(PROJ_OBJ_ROOT)`` is not the same as +``$(PROJ_SRC_ROOT)``, will completely clean the ``$(PROJ_OBJ_ROOT)`` directory +by removing its content entirely and reconfiguring the directory. This returns +the ``$(PROJ_OBJ_ROOT)`` directory to a completely fresh state. All content in +the directory except configured files and top-level makefiles will be lost. + +``tags`` +-------- + +This target will generate a ``TAGS`` file in the top-level source directory. It +is meant for use with emacs, XEmacs, or ViM. The TAGS file provides an index of +symbol definitions so that the editor can jump you to the definition +quickly. + +``uninstall`` +------------- + +This target is the opposite of the ``install`` target. It removes the header, +library and executable files from the installation directories. Note that the +directories themselves are not removed because it is not guaranteed that LLVM is +the only thing installing there (e.g. ``--prefix=/usr``). + +.. _variables: + +Variables +========= + +Variables are used to tell the LLVM Makefile System what to do and to obtain +information from it. Variables are also used internally by the LLVM Makefile +System. Variable names that contain only the upper case alphabetic letters and +underscore are intended for use by the end user. All other variables are +internal to the LLVM Makefile System and should not be relied upon nor +modified. The sections below describe how to use the LLVM Makefile +variables. + +Control Variables +----------------- + +Variables listed in the table below should be set *before* the inclusion of +`$(LEVEL)/Makefile.common`_. These variables provide input to the LLVM make +system that tell it what to do for the current directory. + +``BUILD_ARCHIVE`` + If set to any value, causes an archive (.a) library to be built. + +``BUILT_SOURCES`` + Specifies a set of source files that are generated from other source + files. These sources will be built before any other target processing to + ensure they are present. + +``CONFIG_FILES`` + Specifies a set of configuration files to be installed. + +``DEBUG_SYMBOLS`` + If set to any value, causes the build to include debugging symbols even in + optimized objects, libraries and executables. This alters the flags + specified to the compilers and linkers. Debugging isn't fun in an optimized + build, but it is possible. + +``DIRS`` + Specifies a set of directories, usually children of the current directory, + that should also be made using the same goal. These directories will be + built serially. + +``DISABLE_AUTO_DEPENDENCIES`` + If set to any value, causes the makefiles to **not** automatically generate + dependencies when running the compiler. Use of this feature is discouraged + and it may be removed at a later date. + +``ENABLE_OPTIMIZED`` + If set to 1, causes the build to generate optimized objects, libraries and + executables. This alters the flags specified to the compilers and + linkers. Generally debugging won't be a fun experience with an optimized + build. + +``ENABLE_PROFILING`` + If set to 1, causes the build to generate both optimized and profiled + objects, libraries and executables. This alters the flags specified to the + compilers and linkers to ensure that profile data can be collected from the + tools built. Use the ``gprof`` tool to analyze the output from the profiled + tools (``gmon.out``). + +``DISABLE_ASSERTIONS`` + If set to 1, causes the build to disable assertions, even if building a + debug or profile build. This will exclude all assertion check code from the + build. LLVM will execute faster, but with little help when things go + wrong. + +``EXPERIMENTAL_DIRS`` + Specify a set of directories that should be built, but if they fail, it + should not cause the build to fail. Note that this should only be used + temporarily while code is being written. + +``EXPORTED_SYMBOL_FILE`` + Specifies the name of a single file that contains a list of the symbols to + be exported by the linker. One symbol per line. + +``EXPORTED_SYMBOL_LIST`` + Specifies a set of symbols to be exported by the linker. + +``EXTRA_DIST`` + Specifies additional files that should be distributed with LLVM. All source + files, all built sources, all Makefiles, and most documentation files will + be automatically distributed. Use this variable to distribute any files that + are not automatically distributed. + +``KEEP_SYMBOLS`` + If set to any value, specifies that when linking executables the makefiles + should retain debug symbols in the executable. Normally, symbols are + stripped from the executable. + +``LEVEL`` (required) + Specify the level of nesting from the top level. This variable must be set + in each makefile as it is used to find the top level and thus the other + makefiles. + +``LIBRARYNAME`` + Specify the name of the library to be built. (Required For Libraries) + +``LINK_COMPONENTS`` + When specified for building a tool, the value of this variable will be + passed to the ``llvm-config`` tool to generate a link line for the + tool. Unlike ``USEDLIBS`` and ``LLVMLIBS``, not all libraries need to be + specified. The ``llvm-config`` tool will figure out the library dependencies + and add any libraries that are needed. The ``USEDLIBS`` variable can still + be used in conjunction with ``LINK_COMPONENTS`` so that additional + project-specific libraries can be linked with the LLVM libraries specified + by ``LINK_COMPONENTS``. + +.. _LINK_LIBS_IN_SHARED: + +``LINK_LIBS_IN_SHARED`` + By default, shared library linking will ignore any libraries specified with + the `LLVMLIBS`_ or `USEDLIBS`_. This prevents shared libs from including + things that will be in the LLVM tool the shared library will be loaded + into. However, sometimes it is useful to link certain libraries into your + shared library and this option enables that feature. + +.. _LLVMLIBS: + +``LLVMLIBS`` + Specifies the set of libraries from the LLVM ``$(ObjDir)`` that will be + linked into the tool or library. + +``LOADABLE_MODULE`` + If set to any value, causes the shared library being built to also be a + loadable module. Loadable modules can be opened with the dlopen() function + and searched with dlsym (or the operating system's equivalent). Note that + setting this variable without also setting ``SHARED_LIBRARY`` will have no + effect. + +``NO_INSTALL`` + Specifies that the build products of the directory should not be installed + but should be built even if the ``install`` target is given. This is handy + for directories that build libraries or tools that are only used as part of + the build process, such as code generators (e.g. ``tblgen``). + +``OPTIONAL_DIRS`` + Specify a set of directories that may be built, if they exist, but it is + not an error for them not to exist. + +``PARALLEL_DIRS`` + Specify a set of directories to build recursively and in parallel if the + ``-j`` option was used with ``make``. + +.. _SHARED_LIBRARY: + +``SHARED_LIBRARY`` + If set to any value, causes a shared library (``.so``) to be built in + addition to any other kinds of libraries. Note that this option will cause + all source files to be built twice: once with options for position + independent code and once without. Use it only where you really need a + shared library. + +``SOURCES`` (optional) + Specifies the list of source files in the current directory to be + built. Source files of any type may be specified (programs, documentation, + config files, etc.). If not specified, the makefile system will infer the + set of source files from the files present in the current directory. + +``SUFFIXES`` + Specifies a set of filename suffixes that occur in suffix match rules. Only + set this if your local ``Makefile`` specifies additional suffix match + rules. + +``TARGET`` + Specifies the name of the LLVM code generation target that the current + directory builds. Setting this variable enables additional rules to build + ``.inc`` files from ``.td`` files. + +.. _TESTSUITE: + +``TESTSUITE`` + Specifies the directory of tests to run in ``llvm/test``. + +``TOOLNAME`` + Specifies the name of the tool that the current directory should build. + +``TOOL_VERBOSE`` + Implies ``VERBOSE`` and also tells each tool invoked to be verbose. This is + handy when you're trying to see the sub-tools invoked by each tool invoked + by the makefile. For example, this will pass ``-v`` to the GCC compilers + which causes it to print out the command lines it uses to invoke sub-tools + (compiler, assembler, linker). + +.. _USEDLIBS: + +``USEDLIBS`` + Specifies the list of project libraries that will be linked into the tool or + library. + +``VERBOSE`` + Tells the Makefile system to produce detailed output of what it is doing + instead of just summary comments. This will generate a LOT of output. + +Override Variables +------------------ + +Override variables can be used to override the default values provided by the +LLVM makefile system. These variables can be set in several ways: + +* In the environment (e.g. setenv, export) --- not recommended. +* On the ``make`` command line --- recommended. +* On the ``configure`` command line. +* In the Makefile (only *after* the inclusion of `$(LEVEL)/Makefile.common`_). + +The override variables are given below: + +``AR`` (defaulted) + Specifies the path to the ``ar`` tool. + +``PROJ_OBJ_DIR`` + The directory into which the products of build rules will be placed. This + might be the same as `PROJ_SRC_DIR`_ but typically is not. + +.. _PROJ_SRC_DIR: + +``PROJ_SRC_DIR`` + The directory which contains the source files to be built. + +``BUILD_EXAMPLES`` + If set to 1, build examples in ``examples`` and (if building Clang) + ``tools/clang/examples`` directories. + +``BZIP2`` (configured) + The path to the ``bzip2`` tool. + +``CC`` (configured) + The path to the 'C' compiler. + +``CFLAGS`` + Additional flags to be passed to the 'C' compiler. + +``CPPFLAGS`` + Additional flags passed to the C/C++ preprocessor. + +``CXX`` + Specifies the path to the C++ compiler. + +``CXXFLAGS`` + Additional flags to be passed to the C++ compiler. + +``DATE`` (configured) + Specifies the path to the ``date`` program or any program that can generate + the current date and time on its standard output. + +``DOT`` (configured) + Specifies the path to the ``dot`` tool or ``false`` if there isn't one. + +``ECHO`` (configured) + Specifies the path to the ``echo`` tool for printing output. + +``EXEEXT`` (configured) + Provides the extension to be used on executables built by the makefiles. + The value may be empty on platforms that do not use file extensions for + executables (e.g. Unix). + +``INSTALL`` (configured) + Specifies the path to the ``install`` tool. + +``LDFLAGS`` (configured) + Allows users to specify additional flags to pass to the linker. + +``LIBS`` (configured) + The list of libraries that should be linked with each tool. + +``LIBTOOL`` (configured) + Specifies the path to the ``libtool`` tool. This tool is renamed ``mklib`` + by the ``configure`` script. + +``LLVMAS`` (defaulted) + Specifies the path to the ``llvm-as`` tool. + +``LLVMGCC`` (defaulted) + Specifies the path to the LLVM version of the GCC 'C' Compiler. + +``LLVMGXX`` (defaulted) + Specifies the path to the LLVM version of the GCC C++ Compiler. + +``LLVMLD`` (defaulted) + Specifies the path to the LLVM bitcode linker tool + +``LLVM_OBJ_ROOT`` (configured) + Specifies the top directory into which the output of the build is placed. + +``LLVM_SRC_ROOT`` (configured) + Specifies the top directory in which the sources are found. + +``LLVM_TARBALL_NAME`` (configured) + Specifies the name of the distribution tarball to create. This is configured + from the name of the project and its version number. + +``MKDIR`` (defaulted) + Specifies the path to the ``mkdir`` tool that creates directories. + +``ONLY_TOOLS`` + If set, specifies the list of tools to build. + +``PLATFORMSTRIPOPTS`` + The options to provide to the linker to specify that a stripped (no symbols) + executable should be built. + +``RANLIB`` (defaulted) + Specifies the path to the ``ranlib`` tool. + +``RM`` (defaulted) + Specifies the path to the ``rm`` tool. + +``SED`` (defaulted) + Specifies the path to the ``sed`` tool. + +``SHLIBEXT`` (configured) + Provides the filename extension to use for shared libraries. + +``TBLGEN`` (defaulted) + Specifies the path to the ``tblgen`` tool. + +``TAR`` (defaulted) + Specifies the path to the ``tar`` tool. + +``ZIP`` (defaulted) + Specifies the path to the ``zip`` tool. + +Readable Variables +------------------ + +Variables listed in the table below can be used by the user's Makefile but +should not be changed. Changing the value will generally cause the build to go +wrong, so don't do it. + +``bindir`` + The directory into which executables will ultimately be installed. This + value is derived from the ``--prefix`` option given to ``configure``. + +``BuildMode`` + The name of the type of build being performed: Debug, Release, or + Profile. + +``bytecode_libdir`` + The directory into which bitcode libraries will ultimately be installed. + This value is derived from the ``--prefix`` option given to ``configure``. + +``ConfigureScriptFLAGS`` + Additional flags given to the ``configure`` script when reconfiguring. + +``DistDir`` + The *current* directory for which a distribution copy is being made. + +.. _Echo: + +``Echo`` + The LLVM Makefile System output command. This provides the ``llvm[n]`` + prefix and starts with ``@`` so the command itself is not printed by + ``make``. + +``EchoCmd`` + Same as `Echo`_ but without the leading ``@``. + +``includedir`` + The directory into which include files will ultimately be installed. This + value is derived from the ``--prefix`` option given to ``configure``. + +``libdir`` + The directory into which native libraries will ultimately be installed. + This value is derived from the ``--prefix`` option given to + ``configure``. + +``LibDir`` + The configuration specific directory into which libraries are placed before + installation. + +``MakefileConfig`` + Full path of the ``Makefile.config`` file. + +``MakefileConfigIn`` + Full path of the ``Makefile.config.in`` file. + +``ObjDir`` + The configuration and directory specific directory where build objects + (compilation results) are placed. + +``SubDirs`` + The complete list of sub-directories of the current directory as + specified by other variables. + +``Sources`` + The complete list of source files. + +``sysconfdir`` + The directory into which configuration files will ultimately be + installed. This value is derived from the ``--prefix`` option given to + ``configure``. + +``ToolDir`` + The configuration specific directory into which executables are placed + before they are installed. + +``TopDistDir`` + The top most directory into which the distribution files are copied. + +``Verb`` + Use this as the first thing on your build script lines to enable or disable + verbose mode. It expands to either an ``@`` (quiet mode) or nothing (verbose + mode). + +Internal Variables +------------------ + +Variables listed below are used by the LLVM Makefile System and considered +internal. You should not use these variables under any circumstances. + +.. code-block:: makefile + + Archive + AR.Flags + BaseNameSources + BCLinkLib + C.Flags + Compile.C + CompileCommonOpts + Compile.CXX + ConfigStatusScript + ConfigureScript + CPP.Flags + CPP.Flags + CXX.Flags + DependFiles + DestArchiveLib + DestBitcodeLib + DestModule + DestSharedLib + DestTool + DistAlways + DistCheckDir + DistCheckTop + DistFiles + DistName + DistOther + DistSources + DistSubDirs + DistTarBZ2 + DistTarGZip + DistZip + ExtraLibs + FakeSources + INCFiles + InternalTargets + LD.Flags + LibName.A + LibName.BC + LibName.LA + LibName.O + LibTool.Flags + Link + LinkModule + LLVMLibDir + LLVMLibsOptions + LLVMLibsPaths + LLVMToolDir + LLVMUsedLibs + LocalTargets + Module + ObjectsLO + ObjectsO + ObjMakefiles + ParallelTargets + PreConditions + ProjLibsOptions + ProjLibsPaths + ProjUsedLibs + Ranlib + RecursiveTargets + SrcMakefiles + Strip + StripWarnMsg + TableGen + TDFiles + ToolBuildPath + TopLevelTargets + UserTargets diff --git a/docs/MarkedUpDisassembly.rst b/docs/MarkedUpDisassembly.rst new file mode 100644 index 00000000..cc4dbc81 --- /dev/null +++ b/docs/MarkedUpDisassembly.rst @@ -0,0 +1,86 @@ +======================================= +LLVM's Optional Rich Disassembly Output +======================================= + +.. contents:: + :local: + +Introduction +============ + +LLVM's default disassembly output is raw text. To allow consumers more ability +to introspect the instructions' textual representation or to reformat for a more +user friendly display there is an optional rich disassembly output. + +This optional output is sufficient to reference into individual portions of the +instruction text. This is intended for clients like disassemblers, list file +generators, and pretty-printers, which need more than the raw instructions and +the ability to print them. + +To provide this functionality the assembly text is marked up with annotations. +The markup is simple enough in syntax to be robust even in the case of version +mismatches between consumers and producers. That is, the syntax generally does +not carry semantics beyond "this text has an annotation," so consumers can +simply ignore annotations they do not understand or do not care about. + +After calling ``LLVMCreateDisasm()`` to create a disassembler context the +optional output is enable with this call: + +.. code-block:: c + + LLVMSetDisasmOptions(DC, LLVMDisassembler_Option_UseMarkup); + +Then subsequent calls to ``LLVMDisasmInstruction()`` will return output strings +with the marked up annotations. + +Instruction Annotations +======================= + +.. _contextual markups: + +Contextual markups +------------------ + +Annoated assembly display will supply contextual markup to help clients more +efficiently implement things like pretty printers. Most markup will be target +independent, so clients can effectively provide good display without any target +specific knowledge. + +Annotated assembly goes through the normal instruction printer, but optionally +includes contextual tags on portions of the instruction string. An annotation +is any '<' '>' delimited section of text(1). + +.. code-block:: bat + + annotation: '<' tag-name tag-modifier-list ':' annotated-text '>' + tag-name: identifier + tag-modifier-list: comma delimited identifier list + +The tag-name is an identifier which gives the type of the annotation. For the +first pass, this will be very simple, with memory references, registers, and +immediates having the tag names "mem", "reg", and "imm", respectively. + +The tag-modifier-list is typically additional target-specific context, such as +register class. + +Clients should accept and ignore any tag-names or tag-modifiers they do not +understand, allowing the annotations to grow in richness without breaking older +clients. + +For example, a possible annotation of an ARM load of a stack-relative location +might be annotated as: + +.. code-block:: nasm + + ldr , , ]> + + +1: For assembly dialects in which '<' and/or '>' are legal tokens, a literal token is escaped by following immediately with a repeat of the character. For example, a literal '<' character is output as '<<' in an annotated assembly string. + +C API Details +------------- + +The intended consumers of this information use the C API, therefore the new C +API function for the disassembler will be added to provide an option to produce +disassembled instructions with annotations, ``LLVMSetDisasmOptions()`` and the +``LLVMDisassembler_Option_UseMarkup`` option (see above). diff --git a/docs/NVPTXUsage.rst b/docs/NVPTXUsage.rst new file mode 100644 index 00000000..a9065ce7 --- /dev/null +++ b/docs/NVPTXUsage.rst @@ -0,0 +1,980 @@ +============================= +User Guide for NVPTX Back-end +============================= + +.. contents:: + :local: + :depth: 3 + + +Introduction +============ + +To support GPU programming, the NVPTX back-end supports a subset of LLVM IR +along with a defined set of conventions used to represent GPU programming +concepts. This document provides an overview of the general usage of the back- +end, including a description of the conventions used and the set of accepted +LLVM IR. + +.. note:: + + This document assumes a basic familiarity with CUDA and the PTX + assembly language. Information about the CUDA Driver API and the PTX assembly + language can be found in the `CUDA documentation + `_. + + + +Conventions +=========== + +Marking Functions as Kernels +---------------------------- + +In PTX, there are two types of functions: *device functions*, which are only +callable by device code, and *kernel functions*, which are callable by host +code. By default, the back-end will emit device functions. Metadata is used to +declare a function as a kernel function. This metadata is attached to the +``nvvm.annotations`` named metadata object, and has the following format: + +.. code-block:: llvm + + !0 = metadata !{, metadata !"kernel", i32 1} + +The first parameter is a reference to the kernel function. The following +example shows a kernel function calling a device function in LLVM IR. The +function ``@my_kernel`` is callable from host code, but ``@my_fmad`` is not. + +.. code-block:: llvm + + define float @my_fmad(float %x, float %y, float %z) { + %mul = fmul float %x, %y + %add = fadd float %mul, %z + ret float %add + } + + define void @my_kernel(float* %ptr) { + %val = load float* %ptr + %ret = call float @my_fmad(float %val, float %val, float %val) + store float %ret, float* %ptr + ret void + } + + !nvvm.annotations = !{!1} + !1 = metadata !{void (float*)* @my_kernel, metadata !"kernel", i32 1} + +When compiled, the PTX kernel functions are callable by host-side code. + + +.. _address_spaces: + +Address Spaces +-------------- + +The NVPTX back-end uses the following address space mapping: + + ============= ====================== + Address Space Memory Space + ============= ====================== + 0 Generic + 1 Global + 2 Internal Use + 3 Shared + 4 Constant + 5 Local + ============= ====================== + +Every global variable and pointer type is assigned to one of these address +spaces, with 0 being the default address space. Intrinsics are provided which +can be used to convert pointers between the generic and non-generic address +spaces. + +As an example, the following IR will define an array ``@g`` that resides in +global device memory. + +.. code-block:: llvm + + @g = internal addrspace(1) global [4 x i32] [ i32 0, i32 1, i32 2, i32 3 ] + +LLVM IR functions can read and write to this array, and host-side code can +copy data to it by name with the CUDA Driver API. + +Note that since address space 0 is the generic space, it is illegal to have +global variables in address space 0. Address space 0 is the default address +space in LLVM, so the ``addrspace(N)`` annotation is *required* for global +variables. + + +Triples +------- + +The NVPTX target uses the module triple to select between 32/64-bit code +generation and the driver-compiler interface to use. The triple architecture +can be one of ``nvptx`` (32-bit PTX) or ``nvptx64`` (64-bit PTX). The +operating system should be one of ``cuda`` or ``nvcl``, which determines the +interface used by the generated code to communicate with the driver. Most +users will want to use ``cuda`` as the operating system, which makes the +generated PTX compatible with the CUDA Driver API. + +Example: 32-bit PTX for CUDA Driver API: ``nvptx-nvidia-cuda`` + +Example: 64-bit PTX for CUDA Driver API: ``nvptx64-nvidia-cuda`` + + + +.. _nvptx_intrinsics: + +NVPTX Intrinsics +================ + +Address Space Conversion +------------------------ + +'``llvm.nvvm.ptr.*.to.gen``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +These are overloaded intrinsics. You can use these on any pointer types. + +.. code-block:: llvm + + declare i8* @llvm.nvvm.ptr.global.to.gen.p0i8.p1i8(i8 addrspace(1)*) + declare i8* @llvm.nvvm.ptr.shared.to.gen.p0i8.p3i8(i8 addrspace(3)*) + declare i8* @llvm.nvvm.ptr.constant.to.gen.p0i8.p4i8(i8 addrspace(4)*) + declare i8* @llvm.nvvm.ptr.local.to.gen.p0i8.p5i8(i8 addrspace(5)*) + +Overview: +""""""""" + +The '``llvm.nvvm.ptr.*.to.gen``' intrinsics convert a pointer in a non-generic +address space to a generic address space pointer. + +Semantics: +"""""""""" + +These intrinsics modify the pointer value to be a valid generic address space +pointer. + + +'``llvm.nvvm.ptr.gen.to.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +These are overloaded intrinsics. You can use these on any pointer types. + +.. code-block:: llvm + + declare i8* @llvm.nvvm.ptr.gen.to.global.p1i8.p0i8(i8 addrspace(1)*) + declare i8* @llvm.nvvm.ptr.gen.to.shared.p3i8.p0i8(i8 addrspace(3)*) + declare i8* @llvm.nvvm.ptr.gen.to.constant.p4i8.p0i8(i8 addrspace(4)*) + declare i8* @llvm.nvvm.ptr.gen.to.local.p5i8.p0i8(i8 addrspace(5)*) + +Overview: +""""""""" + +The '``llvm.nvvm.ptr.gen.to.*``' intrinsics convert a pointer in the generic +address space to a pointer in the target address space. Note that these +intrinsics are only useful if the address space of the target address space of +the pointer is known. It is not legal to use address space conversion +intrinsics to convert a pointer from one non-generic address space to another +non-generic address space. + +Semantics: +"""""""""" + +These intrinsics modify the pointer value to be a valid pointer in the target +non-generic address space. + + +Reading PTX Special Registers +----------------------------- + +'``llvm.nvvm.read.ptx.sreg.*``' +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +.. code-block:: llvm + + declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() + declare i32 @llvm.nvvm.read.ptx.sreg.tid.y() + declare i32 @llvm.nvvm.read.ptx.sreg.tid.z() + declare i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + declare i32 @llvm.nvvm.read.ptx.sreg.ntid.y() + declare i32 @llvm.nvvm.read.ptx.sreg.ntid.z() + declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.x() + declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.y() + declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.z() + declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.x() + declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.y() + declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.z() + declare i32 @llvm.nvvm.read.ptx.sreg.warpsize() + +Overview: +""""""""" + +The '``@llvm.nvvm.read.ptx.sreg.*``' intrinsics provide access to the PTX +special registers, in particular the kernel launch bounds. These registers +map in the following way to CUDA builtins: + + ============ ===================================== + CUDA Builtin PTX Special Register Intrinsic + ============ ===================================== + ``threadId`` ``@llvm.nvvm.read.ptx.sreg.tid.*`` + ``blockIdx`` ``@llvm.nvvm.read.ptx.sreg.ctaid.*`` + ``blockDim`` ``@llvm.nvvm.read.ptx.sreg.ntid.*`` + ``gridDim`` ``@llvm.nvvm.read.ptx.sreg.nctaid.*`` + ============ ===================================== + + +Barriers +-------- + +'``llvm.nvvm.barrier0``' +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +.. code-block:: llvm + + declare void @llvm.nvvm.barrier0() + +Overview: +""""""""" + +The '``@llvm.nvvm.barrier0()``' intrinsic emits a PTX ``bar.sync 0`` +instruction, equivalent to the ``__syncthreads()`` call in CUDA. + + +Other Intrinsics +---------------- + +For the full set of NVPTX intrinsics, please see the +``include/llvm/IR/IntrinsicsNVVM.td`` file in the LLVM source tree. + + +.. _libdevice: + +Linking with Libdevice +====================== + +The CUDA Toolkit comes with an LLVM bitcode library called ``libdevice`` that +implements many common mathematical functions. This library can be used as a +high-performance math library for any compilers using the LLVM NVPTX target. +The library can be found under ``nvvm/libdevice/`` in the CUDA Toolkit and +there is a separate version for each compute architecture. + +For a list of all math functions implemented in libdevice, see +`libdevice Users Guide `_. + +To accomodate various math-related compiler flags that can affect code +generation of libdevice code, the library code depends on a special LLVM IR +pass (``NVVMReflect``) to handle conditional compilation within LLVM IR. This +pass looks for calls to the ``@__nvvm_reflect`` function and replaces them +with constants based on the defined reflection parameters. Such conditional +code often follows a pattern: + +.. code-block:: c++ + + float my_function(float a) { + if (__nvvm_reflect("FASTMATH")) + return my_function_fast(a); + else + return my_function_precise(a); + } + +The default value for all unspecified reflection parameters is zero. + +The ``NVVMReflect`` pass should be executed early in the optimization +pipeline, immediately after the link stage. The ``internalize`` pass is also +recommended to remove unused math functions from the resulting PTX. For an +input IR module ``module.bc``, the following compilation flow is recommended: + +1. Save list of external functions in ``module.bc`` +2. Link ``module.bc`` with ``libdevice.compute_XX.YY.bc`` +3. Internalize all functions not in list from (1) +4. Eliminate all unused internal functions +5. Run ``NVVMReflect`` pass +6. Run standard optimization pipeline + +.. note:: + + ``linkonce`` and ``linkonce_odr`` linkage types are not suitable for the + libdevice functions. It is possible to link two IR modules that have been + linked against libdevice using different reflection variables. + +Since the ``NVVMReflect`` pass replaces conditionals with constants, it will +often leave behind dead code of the form: + +.. code-block:: llvm + + entry: + .. + br i1 true, label %foo, label %bar + foo: + .. + bar: + ; Dead code + .. + +Therefore, it is recommended that ``NVVMReflect`` is executed early in the +optimization pipeline before dead-code elimination. + + +Reflection Parameters +--------------------- + +The libdevice library currently uses the following reflection parameters to +control code generation: + +==================== ====================================================== +Flag Description +==================== ====================================================== +``__CUDA_FTZ=[0,1]`` Use optimized code paths that flush subnormals to zero +==================== ====================================================== + + +Invoking NVVMReflect +-------------------- + +To ensure that all dead code caused by the reflection pass is eliminated, it +is recommended that the reflection pass is executed early in the LLVM IR +optimization pipeline. The pass takes an optional mapping of reflection +parameter name to an integer value. This mapping can be specified as either a +command-line option to ``opt`` or as an LLVM ``StringMap`` object when +programmatically creating a pass pipeline. + +With ``opt``: + +.. code-block:: text + + # opt -nvvm-reflect -nvvm-reflect-list==,= module.bc -o module.reflect.bc + + +With programmatic pass pipeline: + +.. code-block:: c++ + + extern ModulePass *llvm::createNVVMReflectPass(const StringMap& Mapping); + + StringMap ReflectParams; + ReflectParams["__CUDA_FTZ"] = 1; + Passes.add(createNVVMReflectPass(ReflectParams)); + + + +Executing PTX +============= + +The most common way to execute PTX assembly on a GPU device is to use the CUDA +Driver API. This API is a low-level interface to the GPU driver and allows for +JIT compilation of PTX code to native GPU machine code. + +Initializing the Driver API: + +.. code-block:: c++ + + CUdevice device; + CUcontext context; + + // Initialize the driver API + cuInit(0); + // Get a handle to the first compute device + cuDeviceGet(&device, 0); + // Create a compute device context + cuCtxCreate(&context, 0, device); + +JIT compiling a PTX string to a device binary: + +.. code-block:: c++ + + CUmodule module; + CUfunction funcion; + + // JIT compile a null-terminated PTX string + cuModuleLoadData(&module, (void*)PTXString); + + // Get a handle to the "myfunction" kernel function + cuModuleGetFunction(&function, module, "myfunction"); + +For full examples of executing PTX assembly, please see the `CUDA Samples +`_ distribution. + + +Common Issues +============= + +ptxas complains of undefined function: __nvvm_reflect +----------------------------------------------------- + +When linking with libdevice, the ``NVVMReflect`` pass must be used. See +:ref:`libdevice` for more information. + + +Tutorial: A Simple Compute Kernel +================================= + +To start, let us take a look at a simple compute kernel written directly in +LLVM IR. The kernel implements vector addition, where each thread computes one +element of the output vector C from the input vectors A and B. To make this +easier, we also assume that only a single CTA (thread block) will be launched, +and that it will be one dimensional. + + +The Kernel +---------- + +.. code-block:: llvm + + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + target triple = "nvptx64-nvidia-cuda" + + ; Intrinsic to read X component of thread ID + declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + + define void @kernel(float addrspace(1)* %A, + float addrspace(1)* %B, + float addrspace(1)* %C) { + entry: + ; What is my ID? + %id = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + + ; Compute pointers into A, B, and C + %ptrA = getelementptr float addrspace(1)* %A, i32 %id + %ptrB = getelementptr float addrspace(1)* %B, i32 %id + %ptrC = getelementptr float addrspace(1)* %C, i32 %id + + ; Read A, B + %valA = load float addrspace(1)* %ptrA, align 4 + %valB = load float addrspace(1)* %ptrB, align 4 + + ; Compute C = A + B + %valC = fadd float %valA, %valB + + ; Store back to C + store float %valC, float addrspace(1)* %ptrC, align 4 + + ret void + } + + !nvvm.annotations = !{!0} + !0 = metadata !{void (float addrspace(1)*, + float addrspace(1)*, + float addrspace(1)*)* @kernel, metadata !"kernel", i32 1} + + +We can use the LLVM ``llc`` tool to directly run the NVPTX code generator: + +.. code-block:: text + + # llc -mcpu=sm_20 kernel.ll -o kernel.ptx + + +.. note:: + + If you want to generate 32-bit code, change ``p:64:64:64`` to ``p:32:32:32`` + in the module data layout string and use ``nvptx-nvidia-cuda`` as the + target triple. + + +The output we get from ``llc`` (as of LLVM 3.4): + +.. code-block:: text + + // + // Generated by LLVM NVPTX Back-End + // + + .version 3.1 + .target sm_20 + .address_size 64 + + // .globl kernel + // @kernel + .visible .entry kernel( + .param .u64 kernel_param_0, + .param .u64 kernel_param_1, + .param .u64 kernel_param_2 + ) + { + .reg .f32 %f<4>; + .reg .s32 %r<2>; + .reg .s64 %rl<8>; + + // BB#0: // %entry + ld.param.u64 %rl1, [kernel_param_0]; + mov.u32 %r1, %tid.x; + mul.wide.s32 %rl2, %r1, 4; + add.s64 %rl3, %rl1, %rl2; + ld.param.u64 %rl4, [kernel_param_1]; + add.s64 %rl5, %rl4, %rl2; + ld.param.u64 %rl6, [kernel_param_2]; + add.s64 %rl7, %rl6, %rl2; + ld.global.f32 %f1, [%rl3]; + ld.global.f32 %f2, [%rl5]; + add.f32 %f3, %f1, %f2; + st.global.f32 [%rl7], %f3; + ret; + } + + +Dissecting the Kernel +--------------------- + +Now let us dissect the LLVM IR that makes up this kernel. + +Data Layout +^^^^^^^^^^^ + +The data layout string determines the size in bits of common data types, their +ABI alignment, and their storage size. For NVPTX, you should use one of the +following: + +32-bit PTX: + +.. code-block:: llvm + + target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + +64-bit PTX: + +.. code-block:: llvm + + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + + +Target Intrinsics +^^^^^^^^^^^^^^^^^ + +In this example, we use the ``@llvm.nvvm.read.ptx.sreg.tid.x`` intrinsic to +read the X component of the current thread's ID, which corresponds to a read +of register ``%tid.x`` in PTX. The NVPTX back-end supports a large set of +intrinsics. A short list is shown below; please see +``include/llvm/IR/IntrinsicsNVVM.td`` for the full list. + + +================================================ ==================== +Intrinsic CUDA Equivalent +================================================ ==================== +``i32 @llvm.nvvm.read.ptx.sreg.tid.{x,y,z}`` threadIdx.{x,y,z} +``i32 @llvm.nvvm.read.ptx.sreg.ctaid.{x,y,z}`` blockIdx.{x,y,z} +``i32 @llvm.nvvm.read.ptx.sreg.ntid.{x,y,z}`` blockDim.{x,y,z} +``i32 @llvm.nvvm.read.ptx.sreg.nctaid.{x,y,z}`` gridDim.{x,y,z} +``void @llvm.cuda.syncthreads()`` __syncthreads() +================================================ ==================== + + +Address Spaces +^^^^^^^^^^^^^^ + +You may have noticed that all of the pointer types in the LLVM IR example had +an explicit address space specifier. What is address space 1? NVIDIA GPU +devices (generally) have four types of memory: + +- Global: Large, off-chip memory +- Shared: Small, on-chip memory shared among all threads in a CTA +- Local: Per-thread, private memory +- Constant: Read-only memory shared across all threads + +These different types of memory are represented in LLVM IR as address spaces. +There is also a fifth address space used by the NVPTX code generator that +corresponds to the "generic" address space. This address space can represent +addresses in any other address space (with a few exceptions). This allows +users to write IR functions that can load/store memory using the same +instructions. Intrinsics are provided to convert pointers between the generic +and non-generic address spaces. + +See :ref:`address_spaces` and :ref:`nvptx_intrinsics` for more information. + + +Kernel Metadata +^^^^^^^^^^^^^^^ + +In PTX, a function can be either a `kernel` function (callable from the host +program), or a `device` function (callable only from GPU code). You can think +of `kernel` functions as entry-points in the GPU program. To mark an LLVM IR +function as a `kernel` function, we make use of special LLVM metadata. The +NVPTX back-end will look for a named metadata node called +``nvvm.annotations``. This named metadata must contain a list of metadata that +describe the IR. For our purposes, we need to declare a metadata node that +assigns the "kernel" attribute to the LLVM IR function that should be emitted +as a PTX `kernel` function. These metadata nodes take the form: + +.. code-block:: text + + metadata !{, metadata !"kernel", i32 1} + +For the previous example, we have: + +.. code-block:: llvm + + !nvvm.annotations = !{!0} + !0 = metadata !{void (float addrspace(1)*, + float addrspace(1)*, + float addrspace(1)*)* @kernel, metadata !"kernel", i32 1} + +Here, we have a single metadata declaration in ``nvvm.annotations``. This +metadata annotates our ``@kernel`` function with the ``kernel`` attribute. + + +Running the Kernel +------------------ + +Generating PTX from LLVM IR is all well and good, but how do we execute it on +a real GPU device? The CUDA Driver API provides a convenient mechanism for +loading and JIT compiling PTX to a native GPU device, and launching a kernel. +The API is similar to OpenCL. A simple example showing how to load and +execute our vector addition code is shown below. Note that for brevity this +code does not perform much error checking! + +.. note:: + + You can also use the ``ptxas`` tool provided by the CUDA Toolkit to offline + compile PTX to machine code (SASS) for a specific GPU architecture. Such + binaries can be loaded by the CUDA Driver API in the same way as PTX. This + can be useful for reducing startup time by precompiling the PTX kernels. + + +.. code-block:: c++ + + #include + #include + #include + #include "cuda.h" + + + void checkCudaErrors(CUresult err) { + assert(err == CUDA_SUCCESS); + } + + /// main - Program entry point + int main(int argc, char **argv) { + CUdevice device; + CUmodule cudaModule; + CUcontext context; + CUfunction function; + CUlinkState linker; + int devCount; + + // CUDA initialization + checkCudaErrors(cuInit(0)); + checkCudaErrors(cuDeviceGetCount(&devCount)); + checkCudaErrors(cuDeviceGet(&device, 0)); + + char name[128]; + checkCudaErrors(cuDeviceGetName(name, 128, device)); + std::cout << "Using CUDA Device [0]: " << name << "\n"; + + int devMajor, devMinor; + checkCudaErrors(cuDeviceComputeCapability(&devMajor, &devMinor, device)); + std::cout << "Device Compute Capability: " + << devMajor << "." << devMinor << "\n"; + if (devMajor < 2) { + std::cerr << "ERROR: Device 0 is not SM 2.0 or greater\n"; + return 1; + } + + std::ifstream t("kernel.ptx"); + if (!t.is_open()) { + std::cerr << "kernel.ptx not found\n"; + return 1; + } + std::string str((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + + // Create driver context + checkCudaErrors(cuCtxCreate(&context, 0, device)); + + // Create module for object + checkCudaErrors(cuModuleLoadDataEx(&cudaModule, str.c_str(), 0, 0, 0)); + + // Get kernel function + checkCudaErrors(cuModuleGetFunction(&function, cudaModule, "kernel")); + + // Device data + CUdeviceptr devBufferA; + CUdeviceptr devBufferB; + CUdeviceptr devBufferC; + + checkCudaErrors(cuMemAlloc(&devBufferA, sizeof(float)*16)); + checkCudaErrors(cuMemAlloc(&devBufferB, sizeof(float)*16)); + checkCudaErrors(cuMemAlloc(&devBufferC, sizeof(float)*16)); + + float* hostA = new float[16]; + float* hostB = new float[16]; + float* hostC = new float[16]; + + // Populate input + for (unsigned i = 0; i != 16; ++i) { + hostA[i] = (float)i; + hostB[i] = (float)(2*i); + hostC[i] = 0.0f; + } + + checkCudaErrors(cuMemcpyHtoD(devBufferA, &hostA[0], sizeof(float)*16)); + checkCudaErrors(cuMemcpyHtoD(devBufferB, &hostB[0], sizeof(float)*16)); + + + unsigned blockSizeX = 16; + unsigned blockSizeY = 1; + unsigned blockSizeZ = 1; + unsigned gridSizeX = 1; + unsigned gridSizeY = 1; + unsigned gridSizeZ = 1; + + // Kernel parameters + void *KernelParams[] = { &devBufferA, &devBufferB, &devBufferC }; + + std::cout << "Launching kernel\n"; + + // Kernel launch + checkCudaErrors(cuLaunchKernel(function, gridSizeX, gridSizeY, gridSizeZ, + blockSizeX, blockSizeY, blockSizeZ, + 0, NULL, KernelParams, NULL)); + + // Retrieve device data + checkCudaErrors(cuMemcpyDtoH(&hostC[0], devBufferC, sizeof(float)*16)); + + + std::cout << "Results:\n"; + for (unsigned i = 0; i != 16; ++i) { + std::cout << hostA[i] << " + " << hostB[i] << " = " << hostC[i] << "\n"; + } + + + // Clean up after ourselves + delete [] hostA; + delete [] hostB; + delete [] hostC; + + // Clean-up + checkCudaErrors(cuMemFree(devBufferA)); + checkCudaErrors(cuMemFree(devBufferB)); + checkCudaErrors(cuMemFree(devBufferC)); + checkCudaErrors(cuModuleUnload(cudaModule)); + checkCudaErrors(cuCtxDestroy(context)); + + return 0; + } + + +You will need to link with the CUDA driver and specify the path to cuda.h. + +.. code-block:: text + + # clang++ sample.cpp -o sample -O2 -g -I/usr/local/cuda-5.5/include -lcuda + +We don't need to specify a path to ``libcuda.so`` since this is installed in a +system location by the driver, not the CUDA toolkit. + +If everything goes as planned, you should see the following output when +running the compiled program: + +.. code-block:: text + + Using CUDA Device [0]: GeForce GTX 680 + Device Compute Capability: 3.0 + Launching kernel + Results: + 0 + 0 = 0 + 1 + 2 = 3 + 2 + 4 = 6 + 3 + 6 = 9 + 4 + 8 = 12 + 5 + 10 = 15 + 6 + 12 = 18 + 7 + 14 = 21 + 8 + 16 = 24 + 9 + 18 = 27 + 10 + 20 = 30 + 11 + 22 = 33 + 12 + 24 = 36 + 13 + 26 = 39 + 14 + 28 = 42 + 15 + 30 = 45 + +.. note:: + + You will likely see a different device identifier based on your hardware + + +Tutorial: Linking with Libdevice +================================ + +In this tutorial, we show a simple example of linking LLVM IR with the +libdevice library. We will use the same kernel as the previous tutorial, +except that we will compute ``C = pow(A, B)`` instead of ``C = A + B``. +Libdevice provides an ``__nv_powf`` function that we will use. + +.. code-block:: llvm + + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + target triple = "nvptx64-nvidia-cuda" + + ; Intrinsic to read X component of thread ID + declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + ; libdevice function + declare float @__nv_powf(float, float) + + define void @kernel(float addrspace(1)* %A, + float addrspace(1)* %B, + float addrspace(1)* %C) { + entry: + ; What is my ID? + %id = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + + ; Compute pointers into A, B, and C + %ptrA = getelementptr float addrspace(1)* %A, i32 %id + %ptrB = getelementptr float addrspace(1)* %B, i32 %id + %ptrC = getelementptr float addrspace(1)* %C, i32 %id + + ; Read A, B + %valA = load float addrspace(1)* %ptrA, align 4 + %valB = load float addrspace(1)* %ptrB, align 4 + + ; Compute C = pow(A, B) + %valC = call float @__nv_exp2f(float %valA, float %valB) + + ; Store back to C + store float %valC, float addrspace(1)* %ptrC, align 4 + + ret void + } + + !nvvm.annotations = !{!0} + !0 = metadata !{void (float addrspace(1)*, + float addrspace(1)*, + float addrspace(1)*)* @kernel, metadata !"kernel", i32 1}% + + +To compile this kernel, we perform the following steps: + +1. Link with libdevice +2. Internalize all but the public kernel function +3. Run ``NVVMReflect`` and set ``__CUDA_FTZ`` to 0 +4. Optimize the linked module +5. Codegen the module + + +These steps can be performed by the LLVM ``llvm-link``, ``opt``, and ``llc`` +tools. In a complete compiler, these steps can also be performed entirely +programmatically by setting up an appropriate pass configuration (see +:ref:`libdevice`). + +.. code-block:: text + + # llvm-link t2.bc libdevice.compute_20.10.bc -o t2.linked.bc + # opt -internalize -internalize-public-api-list=kernel -nvvm-reflect-list=__CUDA_FTZ=0 -nvvm-reflect -O3 t2.linked.bc -o t2.opt.bc + # llc -mcpu=sm_20 t2.opt.bc -o t2.ptx + +.. note:: + + The ``-nvvm-reflect-list=_CUDA_FTZ=0`` is not strictly required, as any + undefined variables will default to zero. It is shown here for evaluation + purposes. + + +This gives us the following PTX (excerpt): + +.. code-block:: text + + // + // Generated by LLVM NVPTX Back-End + // + + .version 3.1 + .target sm_20 + .address_size 64 + + // .globl kernel + // @kernel + .visible .entry kernel( + .param .u64 kernel_param_0, + .param .u64 kernel_param_1, + .param .u64 kernel_param_2 + ) + { + .reg .pred %p<30>; + .reg .f32 %f<111>; + .reg .s32 %r<21>; + .reg .s64 %rl<8>; + + // BB#0: // %entry + ld.param.u64 %rl2, [kernel_param_0]; + mov.u32 %r3, %tid.x; + ld.param.u64 %rl3, [kernel_param_1]; + mul.wide.s32 %rl4, %r3, 4; + add.s64 %rl5, %rl2, %rl4; + ld.param.u64 %rl6, [kernel_param_2]; + add.s64 %rl7, %rl3, %rl4; + add.s64 %rl1, %rl6, %rl4; + ld.global.f32 %f1, [%rl5]; + ld.global.f32 %f2, [%rl7]; + setp.eq.f32 %p1, %f1, 0f3F800000; + setp.eq.f32 %p2, %f2, 0f00000000; + or.pred %p3, %p1, %p2; + @%p3 bra BB0_1; + bra.uni BB0_2; + BB0_1: + mov.f32 %f110, 0f3F800000; + st.global.f32 [%rl1], %f110; + ret; + BB0_2: // %__nv_isnanf.exit.i + abs.f32 %f4, %f1; + setp.gtu.f32 %p4, %f4, 0f7F800000; + @%p4 bra BB0_4; + // BB#3: // %__nv_isnanf.exit5.i + abs.f32 %f5, %f2; + setp.le.f32 %p5, %f5, 0f7F800000; + @%p5 bra BB0_5; + BB0_4: // %.critedge1.i + add.f32 %f110, %f1, %f2; + st.global.f32 [%rl1], %f110; + ret; + BB0_5: // %__nv_isinff.exit.i + + ... + + BB0_26: // %__nv_truncf.exit.i.i.i.i.i + mul.f32 %f90, %f107, 0f3FB8AA3B; + cvt.rzi.f32.f32 %f91, %f90; + mov.f32 %f92, 0fBF317200; + fma.rn.f32 %f93, %f91, %f92, %f107; + mov.f32 %f94, 0fB5BFBE8E; + fma.rn.f32 %f95, %f91, %f94, %f93; + mul.f32 %f89, %f95, 0f3FB8AA3B; + // inline asm + ex2.approx.ftz.f32 %f88,%f89; + // inline asm + add.f32 %f96, %f91, 0f00000000; + ex2.approx.f32 %f97, %f96; + mul.f32 %f98, %f88, %f97; + setp.lt.f32 %p15, %f107, 0fC2D20000; + selp.f32 %f99, 0f00000000, %f98, %p15; + setp.gt.f32 %p16, %f107, 0f42D20000; + selp.f32 %f110, 0f7F800000, %f99, %p16; + setp.eq.f32 %p17, %f110, 0f7F800000; + @%p17 bra BB0_28; + // BB#27: + fma.rn.f32 %f110, %f110, %f108, %f110; + BB0_28: // %__internal_accurate_powf.exit.i + setp.lt.f32 %p18, %f1, 0f00000000; + setp.eq.f32 %p19, %f3, 0f3F800000; + and.pred %p20, %p18, %p19; + @!%p20 bra BB0_30; + bra.uni BB0_29; + BB0_29: + mov.b32 %r9, %f110; + xor.b32 %r10, %r9, -2147483648; + mov.b32 %f110, %r10; + BB0_30: // %__nv_powf.exit + st.global.f32 [%rl1], %f110; + ret; + } + diff --git a/docs/Packaging.rst b/docs/Packaging.rst new file mode 100644 index 00000000..7c2dc956 --- /dev/null +++ b/docs/Packaging.rst @@ -0,0 +1,73 @@ +======================== +Advice on Packaging LLVM +======================== + +.. contents:: + :local: + +Overview +======== + +LLVM sets certain default configure options to make sure our developers don't +break things for constrained platforms. These settings are not optimal for most +desktop systems, and we hope that packagers (e.g., Redhat, Debian, MacPorts, +etc.) will tweak them. This document lists settings we suggest you tweak. + +LLVM's API changes with each release, so users are likely to want, for example, +both LLVM-2.6 and LLVM-2.7 installed at the same time to support apps developed +against each. + +Compile Flags +============= + +LLVM runs much more quickly when it's optimized and assertions are removed. +However, such a build is currently incompatible with users who build without +defining ``NDEBUG``, and the lack of assertions makes it hard to debug problems +in user code. We recommend allowing users to install both optimized and debug +versions of LLVM in parallel. The following configure flags are relevant: + +``--disable-assertions`` + Builds LLVM with ``NDEBUG`` defined. Changes the LLVM ABI. Also available + by setting ``DISABLE_ASSERTIONS=0|1`` in ``make``'s environment. This + defaults to enabled regardless of the optimization setting, but it slows + things down. + +``--enable-debug-symbols`` + Builds LLVM with ``-g``. Also available by setting ``DEBUG_SYMBOLS=0|1`` in + ``make``'s environment. This defaults to disabled when optimizing, so you + should turn it back on to let users debug their programs. + +``--enable-optimized`` + (For svn checkouts) Builds LLVM with ``-O2`` and, by default, turns off + debug symbols. Also available by setting ``ENABLE_OPTIMIZED=0|1`` in + ``make``'s environment. This defaults to enabled when not in a + checkout. + +C++ Features +============ + +RTTI + LLVM disables RTTI by default. Add ``REQUIRES_RTTI=1`` to your environment + while running ``make`` to re-enable it. This will allow users to build with + RTTI enabled and still inherit from LLVM classes. + +Shared Library +============== + +Configure with ``--enable-shared`` to build +``libLLVM-..(so|dylib)`` and link the tools against it. This +saves lots of binary size at the cost of some startup time. + +Dependencies +============ + +``--enable-libffi`` + Depend on `libffi `_ to allow the LLVM + interpreter to call external functions. + +``--with-oprofile`` + + Depend on `libopagent + `_ (>=version 0.9.4) + to let the LLVM JIT tell oprofile about function addresses and line + numbers. diff --git a/docs/Passes.rst b/docs/Passes.rst new file mode 100644 index 00000000..029e472b --- /dev/null +++ b/docs/Passes.rst @@ -0,0 +1,1261 @@ +.. + If Passes.html is up to date, the following "one-liner" should print + an empty diff. + + egrep -e '^-.*.*$' \ + -e '^ .*$' < Passes.html >html; \ + perl >help <<'EOT' && diff -u help html; rm -f help html + open HTML, ") { + m:^-.*.*$: or next; + $order{$1} = sprintf("%03d", 1 + int %order); + } + open HELP, "../Release/bin/opt -help|" or die "open: opt -help: $!\n"; + while () { + m:^ -([^ ]+) +- (.*)$: or next; + my $o = $order{$1}; + $o = "000" unless defined $o; + push @x, "$o-$1$2\n"; + push @y, "$o -$1: $2\n"; + } + @x = map { s/^\d\d\d//; $_ } sort @x; + @y = map { s/^\d\d\d//; $_ } sort @y; + print @x, @y; + EOT + + This (real) one-liner can also be helpful when converting comments to HTML: + + perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print "

\n" if !$on && $_ =~ /\S/; print "

\n" if $on && $_ =~ /^\s*$/; print " $_\n"; $on = ($_ =~ /\S/); } print "

\n" if $on' + +==================================== +LLVM's Analysis and Transform Passes +==================================== + +.. contents:: + :local: + +Introduction +============ + +This document serves as a high level summary of the optimization features that +LLVM provides. Optimizations are implemented as Passes that traverse some +portion of a program to either collect information or transform the program. +The table below divides the passes that LLVM provides into three categories. +Analysis passes compute information that other passes can use or for debugging +or program visualization purposes. Transform passes can use (or invalidate) +the analysis passes. Transform passes all mutate the program in some way. +Utility passes provides some utility but don't otherwise fit categorization. +For example passes to extract functions to bitcode or write a module to bitcode +are neither analysis nor transform passes. The table of contents above +provides a quick summary of each pass and links to the more complete pass +description later in the document. + +Analysis Passes +=============== + +This section describes the LLVM Analysis Passes. + +``-aa-eval``: Exhaustive Alias Analysis Precision Evaluator +----------------------------------------------------------- + +This is a simple N^2 alias analysis accuracy evaluator. Basically, for each +function in the program, it simply queries to see how the alias analysis +implementation answers alias queries between each pair of pointers in the +function. + +This is inspired and adapted from code by: Naveen Neelakantam, Francesco +Spadini, and Wojciech Stryjewski. + +``-basicaa``: Basic Alias Analysis (stateless AA impl) +------------------------------------------------------ + +A basic alias analysis pass that implements identities (two different globals +cannot alias, etc), but does no stateful analysis. + +``-basiccg``: Basic CallGraph Construction +------------------------------------------ + +Yet to be written. + +``-count-aa``: Count Alias Analysis Query Responses +--------------------------------------------------- + +A pass which can be used to count how many alias queries are being made and how +the alias analysis implementation being used responds. + +``-da``: Dependence Analysis +---------------------------- + +Dependence analysis framework, which is used to detect dependences in memory +accesses. + +``-debug-aa``: AA use debugger +------------------------------ + +This simple pass checks alias analysis users to ensure that if they create a +new value, they do not query AA without informing it of the value. It acts as +a shim over any other AA pass you want. + +Yes keeping track of every value in the program is expensive, but this is a +debugging pass. + +``-domfrontier``: Dominance Frontier Construction +------------------------------------------------- + +This pass is a simple dominator construction algorithm for finding forward +dominator frontiers. + +``-domtree``: Dominator Tree Construction +----------------------------------------- + +This pass is a simple dominator construction algorithm for finding forward +dominators. + + +``-dot-callgraph``: Print Call Graph to "dot" file +-------------------------------------------------- + +This pass, only available in ``opt``, prints the call graph into a ``.dot`` +graph. This graph can then be processed with the "dot" tool to convert it to +postscript or some other suitable format. + +``-dot-cfg``: Print CFG of function to "dot" file +------------------------------------------------- + +This pass, only available in ``opt``, prints the control flow graph into a +``.dot`` graph. This graph can then be processed with the :program:`dot` tool +to convert it to postscript or some other suitable format. + +``-dot-cfg-only``: Print CFG of function to "dot" file (with no function bodies) +-------------------------------------------------------------------------------- + +This pass, only available in ``opt``, prints the control flow graph into a +``.dot`` graph, omitting the function bodies. This graph can then be processed +with the :program:`dot` tool to convert it to postscript or some other suitable +format. + +``-dot-dom``: Print dominance tree of function to "dot" file +------------------------------------------------------------ + +This pass, only available in ``opt``, prints the dominator tree into a ``.dot`` +graph. This graph can then be processed with the :program:`dot` tool to +convert it to postscript or some other suitable format. + +``-dot-dom-only``: Print dominance tree of function to "dot" file (with no function bodies) +------------------------------------------------------------------------------------------- + +This pass, only available in ``opt``, prints the dominator tree into a ``.dot`` +graph, omitting the function bodies. This graph can then be processed with the +:program:`dot` tool to convert it to postscript or some other suitable format. + +``-dot-postdom``: Print postdominance tree of function to "dot" file +-------------------------------------------------------------------- + +This pass, only available in ``opt``, prints the post dominator tree into a +``.dot`` graph. This graph can then be processed with the :program:`dot` tool +to convert it to postscript or some other suitable format. + +``-dot-postdom-only``: Print postdominance tree of function to "dot" file (with no function bodies) +--------------------------------------------------------------------------------------------------- + +This pass, only available in ``opt``, prints the post dominator tree into a +``.dot`` graph, omitting the function bodies. This graph can then be processed +with the :program:`dot` tool to convert it to postscript or some other suitable +format. + +``-globalsmodref-aa``: Simple mod/ref analysis for globals +---------------------------------------------------------- + +This simple pass provides alias and mod/ref information for global values that +do not have their address taken, and keeps track of whether functions read or +write memory (are "pure"). For this simple (but very common) case, we can +provide pretty accurate and useful information. + +``-instcount``: Counts the various types of ``Instruction``\ s +-------------------------------------------------------------- + +This pass collects the count of all instructions and reports them. + +``-intervals``: Interval Partition Construction +----------------------------------------------- + +This analysis calculates and represents the interval partition of a function, +or a preexisting interval partition. + +In this way, the interval partition may be used to reduce a flow graph down to +its degenerate single node interval partition (unless it is irreducible). + +``-iv-users``: Induction Variable Users +--------------------------------------- + +Bookkeeping for "interesting" users of expressions computed from induction +variables. + +``-lazy-value-info``: Lazy Value Information Analysis +----------------------------------------------------- + +Interface for lazy computation of value constraint information. + +``-libcall-aa``: LibCall Alias Analysis +--------------------------------------- + +LibCall Alias Analysis. + +``-lint``: Statically lint-checks LLVM IR +----------------------------------------- + +This pass statically checks for common and easily-identified constructs which +produce undefined or likely unintended behavior in LLVM IR. + +It is not a guarantee of correctness, in two ways. First, it isn't +comprehensive. There are checks which could be done statically which are not +yet implemented. Some of these are indicated by TODO comments, but those +aren't comprehensive either. Second, many conditions cannot be checked +statically. This pass does no dynamic instrumentation, so it can't check for +all possible problems. + +Another limitation is that it assumes all code will be executed. A store +through a null pointer in a basic block which is never reached is harmless, but +this pass will warn about it anyway. + +Optimization passes may make conditions that this pass checks for more or less +obvious. If an optimization pass appears to be introducing a warning, it may +be that the optimization pass is merely exposing an existing condition in the +code. + +This code may be run before :ref:`instcombine `. In many +cases, instcombine checks for the same kinds of things and turns instructions +with undefined behavior into unreachable (or equivalent). Because of this, +this pass makes some effort to look through bitcasts and so on. + +``-loops``: Natural Loop Information +------------------------------------ + +This analysis is used to identify natural loops and determine the loop depth of +various nodes of the CFG. Note that the loops identified may actually be +several natural loops that share the same header node... not just a single +natural loop. + +``-memdep``: Memory Dependence Analysis +--------------------------------------- + +An analysis that determines, for a given memory operation, what preceding +memory operations it depends on. It builds on alias analysis information, and +tries to provide a lazy, caching interface to a common kind of alias +information query. + +``-module-debuginfo``: Decodes module-level debug info +------------------------------------------------------ + +This pass decodes the debug info metadata in a module and prints in a +(sufficiently-prepared-) human-readable form. + +For example, run this pass from ``opt`` along with the ``-analyze`` option, and +it'll print to standard output. + +``-no-aa``: No Alias Analysis (always returns 'may' alias) +---------------------------------------------------------- + +This is the default implementation of the Alias Analysis interface. It always +returns "I don't know" for alias queries. NoAA is unlike other alias analysis +implementations, in that it does not chain to a previous analysis. As such it +doesn't follow many of the rules that other alias analyses must. + +``-no-profile``: No Profile Information +--------------------------------------- + +The default "no profile" implementation of the abstract ``ProfileInfo`` +interface. + +``-postdomfrontier``: Post-Dominance Frontier Construction +---------------------------------------------------------- + +This pass is a simple post-dominator construction algorithm for finding +post-dominator frontiers. + +``-postdomtree``: Post-Dominator Tree Construction +-------------------------------------------------- + +This pass is a simple post-dominator construction algorithm for finding +post-dominators. + +``-print-alias-sets``: Alias Set Printer +---------------------------------------- + +Yet to be written. + +``-print-callgraph``: Print a call graph +---------------------------------------- + +This pass, only available in ``opt``, prints the call graph to standard error +in a human-readable form. + +``-print-callgraph-sccs``: Print SCCs of the Call Graph +------------------------------------------------------- + +This pass, only available in ``opt``, prints the SCCs of the call graph to +standard error in a human-readable form. + +``-print-cfg-sccs``: Print SCCs of each function CFG +---------------------------------------------------- + +This pass, only available in ``opt``, printsthe SCCs of each function CFG to +standard error in a human-readable fom. + +``-print-dbginfo``: Print debug info in human readable form +----------------------------------------------------------- + +Pass that prints instructions, and associated debug info: + +#. source/line/col information +#. original variable name +#. original type name + +``-print-dom-info``: Dominator Info Printer +------------------------------------------- + +Dominator Info Printer. + +``-print-externalfnconstants``: Print external fn callsites passed constants +---------------------------------------------------------------------------- + +This pass, only available in ``opt``, prints out call sites to external +functions that are called with constant arguments. This can be useful when +looking for standard library functions we should constant fold or handle in +alias analyses. + +``-print-function``: Print function to stderr +--------------------------------------------- + +The ``PrintFunctionPass`` class is designed to be pipelined with other +``FunctionPasses``, and prints out the functions of the module as they are +processed. + +``-print-module``: Print module to stderr +----------------------------------------- + +This pass simply prints out the entire module when it is executed. + +.. _passes-print-used-types: + +``-print-used-types``: Find Used Types +-------------------------------------- + +This pass is used to seek out all of the types in use by the program. Note +that this analysis explicitly does not include types only used by the symbol +table. + +``-profile-estimator``: Estimate profiling information +------------------------------------------------------ + +Profiling information that estimates the profiling information in a very crude +and unimaginative way. + +``-profile-loader``: Load profile information from ``llvmprof.out`` +------------------------------------------------------------------- + +A concrete implementation of profiling information that loads the information +from a profile dump file. + +``-profile-verifier``: Verify profiling information +--------------------------------------------------- + +Pass that checks profiling information for plausibility. + +``-regions``: Detect single entry single exit regions +----------------------------------------------------- + +The ``RegionInfo`` pass detects single entry single exit regions in a function, +where a region is defined as any subgraph that is connected to the remaining +graph at only two spots. Furthermore, an hierarchical region tree is built. + +``-scalar-evolution``: Scalar Evolution Analysis +------------------------------------------------ + +The ``ScalarEvolution`` analysis can be used to analyze and catagorize scalar +expressions in loops. It specializes in recognizing general induction +variables, representing them with the abstract and opaque ``SCEV`` class. +Given this analysis, trip counts of loops and other important properties can be +obtained. + +This analysis is primarily useful for induction variable substitution and +strength reduction. + +``-scev-aa``: ScalarEvolution-based Alias Analysis +-------------------------------------------------- + +Simple alias analysis implemented in terms of ``ScalarEvolution`` queries. + +This differs from traditional loop dependence analysis in that it tests for +dependencies within a single iteration of a loop, rather than dependencies +between different iterations. + +``ScalarEvolution`` has a more complete understanding of pointer arithmetic +than ``BasicAliasAnalysis``' collection of ad-hoc analyses. + +``-targetdata``: Target Data Layout +----------------------------------- + +Provides other passes access to information on how the size and alignment +required by the target ABI for various data types. + +Transform Passes +================ + +This section describes the LLVM Transform Passes. + +``-adce``: Aggressive Dead Code Elimination +------------------------------------------- + +ADCE aggressively tries to eliminate code. This pass is similar to :ref:`DCE +` but it assumes that values are dead until proven otherwise. This +is similar to :ref:`SCCP `, except applied to the liveness of +values. + +``-always-inline``: Inliner for ``always_inline`` functions +----------------------------------------------------------- + +A custom inliner that handles only functions that are marked as "always +inline". + +``-argpromotion``: Promote 'by reference' arguments to scalars +-------------------------------------------------------------- + +This pass promotes "by reference" arguments to be "by value" arguments. In +practice, this means looking for internal functions that have pointer +arguments. If it can prove, through the use of alias analysis, that an +argument is *only* loaded, then it can pass the value into the function instead +of the address of the value. This can cause recursive simplification of code +and lead to the elimination of allocas (especially in C++ template code like +the STL). + +This pass also handles aggregate arguments that are passed into a function, +scalarizing them if the elements of the aggregate are only loaded. Note that +it refuses to scalarize aggregates which would require passing in more than +three operands to the function, because passing thousands of operands for a +large array or structure is unprofitable! + +Note that this transformation could also be done for arguments that are only +stored to (returning the value instead), but does not currently. This case +would be best handled when and if LLVM starts supporting multiple return values +from functions. + +``-bb-vectorize``: Basic-Block Vectorization +-------------------------------------------- + +This pass combines instructions inside basic blocks to form vector +instructions. It iterates over each basic block, attempting to pair compatible +instructions, repeating this process until no additional pairs are selected for +vectorization. When the outputs of some pair of compatible instructions are +used as inputs by some other pair of compatible instructions, those pairs are +part of a potential vectorization chain. Instruction pairs are only fused into +vector instructions when they are part of a chain longer than some threshold +length. Moreover, the pass attempts to find the best possible chain for each +pair of compatible instructions. These heuristics are intended to prevent +vectorization in cases where it would not yield a performance increase of the +resulting code. + +``-block-placement``: Profile Guided Basic Block Placement +---------------------------------------------------------- + +This pass is a very simple profile guided basic block placement algorithm. The +idea is to put frequently executed blocks together at the start of the function +and hopefully increase the number of fall-through conditional branches. If +there is no profile information for a particular function, this pass basically +orders blocks in depth-first order. + +``-break-crit-edges``: Break critical edges in CFG +-------------------------------------------------- + +Break all of the critical edges in the CFG by inserting a dummy basic block. +It may be "required" by passes that cannot deal with critical edges. This +transformation obviously invalidates the CFG, but can update forward dominator +(set, immediate dominators, tree, and frontier) information. + +``-codegenprepare``: Optimize for code generation +------------------------------------------------- + +This pass munges the code in the input function to better prepare it for +SelectionDAG-based code generation. This works around limitations in its +basic-block-at-a-time approach. It should eventually be removed. + +``-constmerge``: Merge Duplicate Global Constants +------------------------------------------------- + +Merges duplicate global constants together into a single constant that is +shared. This is useful because some passes (i.e., TraceValues) insert a lot of +string constants into the program, regardless of whether or not an existing +string is available. + +``-constprop``: Simple constant propagation +------------------------------------------- + +This pass implements constant propagation and merging. It looks for +instructions involving only constant operands and replaces them with a constant +value instead of an instruction. For example: + +.. code-block:: llvm + + add i32 1, 2 + +becomes + +.. code-block:: llvm + + i32 3 + +NOTE: this pass has a habit of making definitions be dead. It is a good idea +to run a :ref:`Dead Instruction Elimination ` pass sometime after +running this pass. + +.. _passes-dce: + +``-dce``: Dead Code Elimination +------------------------------- + +Dead code elimination is similar to :ref:`dead instruction elimination +`, but it rechecks instructions that were used by removed +instructions to see if they are newly dead. + +``-deadargelim``: Dead Argument Elimination +------------------------------------------- + +This pass deletes dead arguments from internal functions. Dead argument +elimination removes arguments which are directly dead, as well as arguments +only passed into function calls as dead arguments of other functions. This +pass also deletes dead arguments in a similar way. + +This pass is often useful as a cleanup pass to run after aggressive +interprocedural passes, which add possibly-dead arguments. + +``-deadtypeelim``: Dead Type Elimination +---------------------------------------- + +This pass is used to cleanup the output of GCC. It eliminate names for types +that are unused in the entire translation unit, using the :ref:`find used types +` pass. + +.. _passes-die: + +``-die``: Dead Instruction Elimination +-------------------------------------- + +Dead instruction elimination performs a single pass over the function, removing +instructions that are obviously dead. + +``-dse``: Dead Store Elimination +-------------------------------- + +A trivial dead store elimination that only considers basic-block local +redundant stores. + +``-functionattrs``: Deduce function attributes +---------------------------------------------- + +A simple interprocedural pass which walks the call-graph, looking for functions +which do not access or only read non-local memory, and marking them +``readnone``/``readonly``. In addition, it marks function arguments (of +pointer type) "``nocapture``" if a call to the function does not create any +copies of the pointer value that outlive the call. This more or less means +that the pointer is only dereferenced, and not returned from the function or +stored in a global. This pass is implemented as a bottom-up traversal of the +call-graph. + +``-globaldce``: Dead Global Elimination +--------------------------------------- + +This transform is designed to eliminate unreachable internal globals from the +program. It uses an aggressive algorithm, searching out globals that are known +to be alive. After it finds all of the globals which are needed, it deletes +whatever is left over. This allows it to delete recursive chunks of the +program which are unreachable. + +``-globalopt``: Global Variable Optimizer +----------------------------------------- + +This pass transforms simple global variables that never have their address +taken. If obviously true, it marks read/write globals as constant, deletes +variables only stored to, etc. + +``-gvn``: Global Value Numbering +-------------------------------- + +This pass performs global value numbering to eliminate fully and partially +redundant instructions. It also performs redundant load elimination. + +.. _passes-indvars: + +``-indvars``: Canonicalize Induction Variables +---------------------------------------------- + +This transformation analyzes and transforms the induction variables (and +computations derived from them) into simpler forms suitable for subsequent +analysis and transformation. + +This transformation makes the following changes to each loop with an +identifiable induction variable: + +* All loops are transformed to have a *single* canonical induction variable + which starts at zero and steps by one. +* The canonical induction variable is guaranteed to be the first PHI node in + the loop header block. +* Any pointer arithmetic recurrences are raised to use array subscripts. + +If the trip count of a loop is computable, this pass also makes the following +changes: + +* The exit condition for the loop is canonicalized to compare the induction + value against the exit value. This turns loops like: + + .. code-block:: c++ + + for (i = 7; i*i < 1000; ++i) + + into + + .. code-block:: c++ + + for (i = 0; i != 25; ++i) + +* Any use outside of the loop of an expression derived from the indvar is + changed to compute the derived value outside of the loop, eliminating the + dependence on the exit value of the induction variable. If the only purpose + of the loop is to compute the exit value of some derived expression, this + transformation will make the loop dead. + +This transformation should be followed by strength reduction after all of the +desired loop transformations have been performed. Additionally, on targets +where it is profitable, the loop could be transformed to count down to zero +(the "do loop" optimization). + +``-inline``: Function Integration/Inlining +------------------------------------------ + +Bottom-up inlining of functions into callees. + +``-insert-edge-profiling``: Insert instrumentation for edge profiling +--------------------------------------------------------------------- + +This pass instruments the specified program with counters for edge profiling. +Edge profiling can give a reasonable approximation of the hot paths through a +program, and is used for a wide variety of program transformations. + +Note that this implementation is very naïve. It inserts a counter for *every* +edge in the program, instead of using control flow information to prune the +number of counters inserted. + +``-insert-optimal-edge-profiling``: Insert optimal instrumentation for edge profiling +------------------------------------------------------------------------------------- + +This pass instruments the specified program with counters for edge profiling. +Edge profiling can give a reasonable approximation of the hot paths through a +program, and is used for a wide variety of program transformations. + +.. _passes-instcombine: + +``-instcombine``: Combine redundant instructions +------------------------------------------------ + +Combine instructions to form fewer, simple instructions. This pass does not +modify the CFG This pass is where algebraic simplification happens. + +This pass combines things like: + +.. code-block:: llvm + + %Y = add i32 %X, 1 + %Z = add i32 %Y, 1 + +into: + +.. code-block:: llvm + + %Z = add i32 %X, 2 + +This is a simple worklist driven algorithm. + +This pass guarantees that the following canonicalizations are performed on the +program: + +#. If a binary operator has a constant operand, it is moved to the right-hand + side. +#. Bitwise operators with constant operands are always grouped so that shifts + are performed first, then ``or``\ s, then ``and``\ s, then ``xor``\ s. +#. Compare instructions are converted from ``<``, ``>``, ``≤``, or ``≥`` to + ``=`` or ``≠`` if possible. +#. All ``cmp`` instructions on boolean values are replaced with logical + operations. +#. ``add X, X`` is represented as ``mul X, 2`` ⇒ ``shl X, 1`` +#. Multiplies with a constant power-of-two argument are transformed into + shifts. +#. … etc. + +``-internalize``: Internalize Global Symbols +-------------------------------------------- + +This pass loops over all of the functions in the input module, looking for a +main function. If a main function is found, all other functions and all global +variables with initializers are marked as internal. + +``-ipconstprop``: Interprocedural constant propagation +------------------------------------------------------ + +This pass implements an *extremely* simple interprocedural constant propagation +pass. It could certainly be improved in many different ways, like using a +worklist. This pass makes arguments dead, but does not remove them. The +existing dead argument elimination pass should be run after this to clean up +the mess. + +``-ipsccp``: Interprocedural Sparse Conditional Constant Propagation +-------------------------------------------------------------------- + +An interprocedural variant of :ref:`Sparse Conditional Constant Propagation +`. + +``-jump-threading``: Jump Threading +----------------------------------- + +Jump threading tries to find distinct threads of control flow running through a +basic block. This pass looks at blocks that have multiple predecessors and +multiple successors. If one or more of the predecessors of the block can be +proven to always cause a jump to one of the successors, we forward the edge +from the predecessor to the successor by duplicating the contents of this +block. + +An example of when this can occur is code like this: + +.. code-block:: c++ + + if () { ... + X = 4; + } + if (X < 3) { + +In this case, the unconditional branch at the end of the first if can be +revectored to the false side of the second if. + +``-lcssa``: Loop-Closed SSA Form Pass +------------------------------------- + +This pass transforms loops by placing phi nodes at the end of the loops for all +values that are live across the loop boundary. For example, it turns the left +into the right code: + +.. code-block:: c++ + + for (...) for (...) + if (c) if (c) + X1 = ... X1 = ... + else else + X2 = ... X2 = ... + X3 = phi(X1, X2) X3 = phi(X1, X2) + ... = X3 + 4 X4 = phi(X3) + ... = X4 + 4 + +This is still valid LLVM; the extra phi nodes are purely redundant, and will be +trivially eliminated by ``InstCombine``. The major benefit of this +transformation is that it makes many other loop optimizations, such as +``LoopUnswitch``\ ing, simpler. + +.. _passes-licm: + +``-licm``: Loop Invariant Code Motion +------------------------------------- + +This pass performs loop invariant code motion, attempting to remove as much +code from the body of a loop as possible. It does this by either hoisting code +into the preheader block, or by sinking code to the exit blocks if it is safe. +This pass also promotes must-aliased memory locations in the loop to live in +registers, thus hoisting and sinking "invariant" loads and stores. + +This pass uses alias analysis for two purposes: + +#. Moving loop invariant loads and calls out of loops. If we can determine + that a load or call inside of a loop never aliases anything stored to, we + can hoist it or sink it like any other instruction. + +#. Scalar Promotion of Memory. If there is a store instruction inside of the + loop, we try to move the store to happen AFTER the loop instead of inside of + the loop. This can only happen if a few conditions are true: + + #. The pointer stored through is loop invariant. + #. There are no stores or loads in the loop which *may* alias the pointer. + There are no calls in the loop which mod/ref the pointer. + + If these conditions are true, we can promote the loads and stores in the + loop of the pointer to use a temporary alloca'd variable. We then use the + :ref:`mem2reg ` functionality to construct the appropriate + SSA form for the variable. + +``-loop-deletion``: Delete dead loops +------------------------------------- + +This file implements the Dead Loop Deletion Pass. This pass is responsible for +eliminating loops with non-infinite computable trip counts that have no side +effects or volatile instructions, and do not contribute to the computation of +the function's return value. + +.. _passes-loop-extract: + +``-loop-extract``: Extract loops into new functions +--------------------------------------------------- + +A pass wrapper around the ``ExtractLoop()`` scalar transformation to extract +each top-level loop into its own new function. If the loop is the *only* loop +in a given function, it is not touched. This is a pass most useful for +debugging via bugpoint. + +``-loop-extract-single``: Extract at most one loop into a new function +---------------------------------------------------------------------- + +Similar to :ref:`Extract loops into new functions `, this +pass extracts one natural loop from the program into a function if it can. +This is used by :program:`bugpoint`. + +``-loop-reduce``: Loop Strength Reduction +----------------------------------------- + +This pass performs a strength reduction on array references inside loops that +have as one or more of their components the loop induction variable. This is +accomplished by creating a new value to hold the initial value of the array +access for the first iteration, and then creating a new GEP instruction in the +loop to increment the value by the appropriate amount. + +``-loop-rotate``: Rotate Loops +------------------------------ + +A simple loop rotation transformation. + +``-loop-simplify``: Canonicalize natural loops +---------------------------------------------- + +This pass performs several transformations to transform natural loops into a +simpler form, which makes subsequent analyses and transformations simpler and +more effective. + +Loop pre-header insertion guarantees that there is a single, non-critical entry +edge from outside of the loop to the loop header. This simplifies a number of +analyses and transformations, such as :ref:`LICM `. + +Loop exit-block insertion guarantees that all exit blocks from the loop (blocks +which are outside of the loop that have predecessors inside of the loop) only +have predecessors from inside of the loop (and are thus dominated by the loop +header). This simplifies transformations such as store-sinking that are built +into LICM. + +This pass also guarantees that loops will have exactly one backedge. + +Note that the :ref:`simplifycfg ` pass will clean up blocks +which are split out but end up being unnecessary, so usage of this pass should +not pessimize generated code. + +This pass obviously modifies the CFG, but updates loop information and +dominator information. + +``-loop-unroll``: Unroll loops +------------------------------ + +This pass implements a simple loop unroller. It works best when loops have +been canonicalized by the :ref:`indvars ` pass, allowing it to +determine the trip counts of loops easily. + +``-loop-unswitch``: Unswitch loops +---------------------------------- + +This pass transforms loops that contain branches on loop-invariant conditions +to have multiple loops. For example, it turns the left into the right code: + +.. code-block:: c++ + + for (...) if (lic) + A for (...) + if (lic) A; B; C + B else + C for (...) + A; C + +This can increase the size of the code exponentially (doubling it every time a +loop is unswitched) so we only unswitch if the resultant code will be smaller +than a threshold. + +This pass expects :ref:`LICM ` to be run before it to hoist +invariant conditions out of the loop, to make the unswitching opportunity +obvious. + +``-loweratomic``: Lower atomic intrinsics to non-atomic form +------------------------------------------------------------ + +This pass lowers atomic intrinsics to non-atomic form for use in a known +non-preemptible environment. + +The pass does not verify that the environment is non-preemptible (in general +this would require knowledge of the entire call graph of the program including +any libraries which may not be available in bitcode form); it simply lowers +every atomic intrinsic. + +``-lowerinvoke``: Lower invoke and unwind, for unwindless code generators +------------------------------------------------------------------------- + +This transformation is designed for use by code generators which do not yet +support stack unwinding. This pass supports two models of exception handling +lowering, the "cheap" support and the "expensive" support. + +"Cheap" exception handling support gives the program the ability to execute any +program which does not "throw an exception", by turning "``invoke``" +instructions into calls and by turning "``unwind``" instructions into calls to +``abort()``. If the program does dynamically use the "``unwind``" instruction, +the program will print a message then abort. + +"Expensive" exception handling support gives the full exception handling +support to the program at the cost of making the "``invoke``" instruction +really expensive. It basically inserts ``setjmp``/``longjmp`` calls to emulate +the exception handling as necessary. + +Because the "expensive" support slows down programs a lot, and EH is only used +for a subset of the programs, it must be specifically enabled by the +``-enable-correct-eh-support`` option. + +Note that after this pass runs the CFG is not entirely accurate (exceptional +control flow edges are not correct anymore) so only very simple things should +be done after the ``lowerinvoke`` pass has run (like generation of native +code). This should not be used as a general purpose "my LLVM-to-LLVM pass +doesn't support the ``invoke`` instruction yet" lowering pass. + +``-lowerswitch``: Lower ``SwitchInst``\ s to branches +----------------------------------------------------- + +Rewrites switch instructions with a sequence of branches, which allows targets +to get away with not implementing the switch instruction until it is +convenient. + +.. _passes-mem2reg: + +``-mem2reg``: Promote Memory to Register +---------------------------------------- + +This file promotes memory references to be register references. It promotes +alloca instructions which only have loads and stores as uses. An ``alloca`` is +transformed by using dominator frontiers to place phi nodes, then traversing +the function in depth-first order to rewrite loads and stores as appropriate. +This is just the standard SSA construction algorithm to construct "pruned" SSA +form. + +``-memcpyopt``: MemCpy Optimization +----------------------------------- + +This pass performs various transformations related to eliminating ``memcpy`` +calls, or transforming sets of stores into ``memset``\ s. + +``-mergefunc``: Merge Functions +------------------------------- + +This pass looks for equivalent functions that are mergable and folds them. + +A hash is computed from the function, based on its type and number of basic +blocks. + +Once all hashes are computed, we perform an expensive equality comparison on +each function pair. This takes n^2/2 comparisons per bucket, so it's important +that the hash function be high quality. The equality comparison iterates +through each instruction in each basic block. + +When a match is found the functions are folded. If both functions are +overridable, we move the functionality into a new internal function and leave +two overridable thunks to it. + +``-mergereturn``: Unify function exit nodes +------------------------------------------- + +Ensure that functions have at most one ``ret`` instruction in them. +Additionally, it keeps track of which node is the new exit node of the CFG. + +``-partial-inliner``: Partial Inliner +------------------------------------- + +This pass performs partial inlining, typically by inlining an ``if`` statement +that surrounds the body of the function. + +``-prune-eh``: Remove unused exception handling info +---------------------------------------------------- + +This file implements a simple interprocedural pass which walks the call-graph, +turning invoke instructions into call instructions if and only if the callee +cannot throw an exception. It implements this as a bottom-up traversal of the +call-graph. + +``-reassociate``: Reassociate expressions +----------------------------------------- + +This pass reassociates commutative expressions in an order that is designed to +promote better constant propagation, GCSE, :ref:`LICM `, PRE, etc. + +For example: 4 + (x + 5) ⇒ x + (4 + 5) + +In the implementation of this algorithm, constants are assigned rank = 0, +function arguments are rank = 1, and other values are assigned ranks +corresponding to the reverse post order traversal of current function (starting +at 2), which effectively gives values in deep loops higher rank than values not +in loops. + +``-reg2mem``: Demote all values to stack slots +---------------------------------------------- + +This file demotes all registers to memory references. It is intended to be the +inverse of :ref:`mem2reg `. By converting to ``load`` +instructions, the only values live across basic blocks are ``alloca`` +instructions and ``load`` instructions before ``phi`` nodes. It is intended +that this should make CFG hacking much easier. To make later hacking easier, +the entry block is split into two, such that all introduced ``alloca`` +instructions (and nothing else) are in the entry block. + +``-scalarrepl``: Scalar Replacement of Aggregates (DT) +------------------------------------------------------ + +The well-known scalar replacement of aggregates transformation. This transform +breaks up ``alloca`` instructions of aggregate type (structure or array) into +individual ``alloca`` instructions for each member if possible. Then, if +possible, it transforms the individual ``alloca`` instructions into nice clean +scalar SSA form. + +This combines a simple scalar replacement of aggregates algorithm with the +:ref:`mem2reg ` algorithm because they often interact, +especially for C++ programs. As such, iterating between ``scalarrepl``, then +:ref:`mem2reg ` until we run out of things to promote works +well. + +.. _passes-sccp: + +``-sccp``: Sparse Conditional Constant Propagation +-------------------------------------------------- + +Sparse conditional constant propagation and merging, which can be summarized +as: + +* Assumes values are constant unless proven otherwise +* Assumes BasicBlocks are dead unless proven otherwise +* Proves values to be constant, and replaces them with constants +* Proves conditional branches to be unconditional + +Note that this pass has a habit of making definitions be dead. It is a good +idea to run a :ref:`DCE ` pass sometime after running this pass. + +``-simplify-libcalls``: Simplify well-known library calls +--------------------------------------------------------- + +Applies a variety of small optimizations for calls to specific well-known +function calls (e.g. runtime library functions). For example, a call +``exit(3)`` that occurs within the ``main()`` function can be transformed into +simply ``return 3``. + +.. _passes-simplifycfg: + +``-simplifycfg``: Simplify the CFG +---------------------------------- + +Performs dead code elimination and basic block merging. Specifically: + +* Removes basic blocks with no predecessors. +* Merges a basic block into its predecessor if there is only one and the + predecessor only has one successor. +* Eliminates PHI nodes for basic blocks with a single predecessor. +* Eliminates a basic block that only contains an unconditional branch. + +``-sink``: Code sinking +----------------------- + +This pass moves instructions into successor blocks, when possible, so that they +aren't executed on paths where their results aren't needed. + +``-strip``: Strip all symbols from a module +------------------------------------------- + +Performs code stripping. This transformation can delete: + +* names for virtual registers +* symbols for internal globals and functions +* debug information + +Note that this transformation makes code much less readable, so it should only +be used in situations where the strip utility would be used, such as reducing +code size or making it harder to reverse engineer code. + +``-strip-dead-debug-info``: Strip debug info for unused symbols +--------------------------------------------------------------- + +.. FIXME: this description is the same as for -strip + +performs code stripping. this transformation can delete: + +* names for virtual registers +* symbols for internal globals and functions +* debug information + +note that this transformation makes code much less readable, so it should only +be used in situations where the strip utility would be used, such as reducing +code size or making it harder to reverse engineer code. + +``-strip-dead-prototypes``: Strip Unused Function Prototypes +------------------------------------------------------------ + +This pass loops over all of the functions in the input module, looking for dead +declarations and removes them. Dead declarations are declarations of functions +for which no implementation is available (i.e., declarations for unused library +functions). + +``-strip-debug-declare``: Strip all ``llvm.dbg.declare`` intrinsics +------------------------------------------------------------------- + +.. FIXME: this description is the same as for -strip + +This pass implements code stripping. Specifically, it can delete: + +#. names for virtual registers +#. symbols for internal globals and functions +#. debug information + +Note that this transformation makes code much less readable, so it should only +be used in situations where the 'strip' utility would be used, such as reducing +code size or making it harder to reverse engineer code. + +``-strip-nondebug``: Strip all symbols, except dbg symbols, from a module +------------------------------------------------------------------------- + +.. FIXME: this description is the same as for -strip + +This pass implements code stripping. Specifically, it can delete: + +#. names for virtual registers +#. symbols for internal globals and functions +#. debug information + +Note that this transformation makes code much less readable, so it should only +be used in situations where the 'strip' utility would be used, such as reducing +code size or making it harder to reverse engineer code. + +``-tailcallelim``: Tail Call Elimination +---------------------------------------- + +This file transforms calls of the current function (self recursion) followed by +a return instruction with a branch to the entry of the function, creating a +loop. This pass also implements the following extensions to the basic +algorithm: + +#. Trivial instructions between the call and return do not prevent the + transformation from taking place, though currently the analysis cannot + support moving any really useful instructions (only dead ones). +#. This pass transforms functions that are prevented from being tail recursive + by an associative expression to use an accumulator variable, thus compiling + the typical naive factorial or fib implementation into efficient code. +#. TRE is performed if the function returns void, if the return returns the + result returned by the call, or if the function returns a run-time constant + on all exits from the function. It is possible, though unlikely, that the + return returns something else (like constant 0), and can still be TRE'd. It + can be TRE'd if *all other* return instructions in the function return the + exact same value. +#. If it can prove that callees do not access theier caller stack frame, they + are marked as eligible for tail call elimination (by the code generator). + +Utility Passes +============== + +This section describes the LLVM Utility Passes. + +``-deadarghaX0r``: Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE) +------------------------------------------------------------------------ + +Same as dead argument elimination, but deletes arguments to functions which are +external. This is only for use by :doc:`bugpoint `. + +``-extract-blocks``: Extract Basic Blocks From Module (for bugpoint use) +------------------------------------------------------------------------ + +This pass is used by bugpoint to extract all blocks from the module into their +own functions. + +``-instnamer``: Assign names to anonymous instructions +------------------------------------------------------ + +This is a little utility pass that gives instructions names, this is mostly +useful when diffing the effect of an optimization because deleting an unnamed +instruction can change all other instruction numbering, making the diff very +noisy. + +``-preverify``: Preliminary module verification +----------------------------------------------- + +Ensures that the module is in the form required by the :ref:`Module Verifier +` pass. Running the verifier runs this pass automatically, so +there should be no need to use it directly. + +.. _passes-verify: + +``-verify``: Module Verifier +---------------------------- + +Verifies an LLVM IR code. This is useful to run after an optimization which is +undergoing testing. Note that llvm-as verifies its input before emitting +bitcode, and also that malformed bitcode is likely to make LLVM crash. All +language front-ends are therefore encouraged to verify their output before +performing optimizing transformations. + +#. Both of a binary operator's parameters are of the same type. +#. Verify that the indices of mem access instructions match other operands. +#. Verify that arithmetic and other things are only performed on first-class + types. Verify that shifts and logicals only happen on integrals f.e. +#. All of the constants in a switch statement are of the correct type. +#. The code is in valid SSA form. +#. It is illegal to put a label into any other type (like a structure) or to + return one. +#. Only phi nodes can be self referential: ``%x = add i32 %x``, ``%x`` is + invalid. +#. PHI nodes must have an entry for each predecessor, with no extras. +#. PHI nodes must be the first thing in a basic block, all grouped together. +#. PHI nodes must have at least one entry. +#. All basic blocks should only end with terminator insts, not contain them. +#. The entry node to a function must not have predecessors. +#. All Instructions must be embedded into a basic block. +#. Functions cannot take a void-typed parameter. +#. Verify that a function's argument list agrees with its declared type. +#. It is illegal to specify a name for a void value. +#. It is illegal to have an internal global value with no initializer. +#. It is illegal to have a ``ret`` instruction that returns a value that does + not agree with the function return value type. +#. Function call argument types match the function prototype. +#. All other things that are tested by asserts spread about the code. + +Note that this does not provide full security verification (like Java), but +instead just tries to ensure that code is well-formed. + +``-view-cfg``: View CFG of function +----------------------------------- + +Displays the control flow graph using the GraphViz tool. + +``-view-cfg-only``: View CFG of function (with no function bodies) +------------------------------------------------------------------ + +Displays the control flow graph using the GraphViz tool, but omitting function +bodies. + +``-view-dom``: View dominance tree of function +---------------------------------------------- + +Displays the dominator tree using the GraphViz tool. + +``-view-dom-only``: View dominance tree of function (with no function bodies) +----------------------------------------------------------------------------- + +Displays the dominator tree using the GraphViz tool, but omitting function +bodies. + +``-view-postdom``: View postdominance tree of function +------------------------------------------------------ + +Displays the post dominator tree using the GraphViz tool. + +``-view-postdom-only``: View postdominance tree of function (with no function bodies) +------------------------------------------------------------------------------------- + +Displays the post dominator tree using the GraphViz tool, but omitting function +bodies. + diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst new file mode 100644 index 00000000..6fdea1f9 --- /dev/null +++ b/docs/Phabricator.rst @@ -0,0 +1,106 @@ +============================= +Code Reviews with Phabricator +============================= + +.. contents:: + :local: + +If you prefer to use a web user interface for code reviews, +you can now submit your patches for Clang and LLVM at +`LLVM's Phabricator`_. + +Sign up +------- + +There are two options to get an account on Phabricator. You can sign up +immediately with one of the supported OAuth account types if you're comfortable +with OAuth, but you can also email chandlerc@gmail.com to request an account to +be created manually without using OAuth. We're working to get support in +Phabricator to directly create new accounts, but currently this is a manual +process. + +Note that if you use your Subversion user name as Phabricator user name, +Phabricator will automatically connect your submits to your Phabricator user in +the `Code Repository Browser`_. + + +Requesting a review via the command line +---------------------------------------- + +Phabricator has a tool called *Arcanist* to upload patches from +the command line. To get you set up, follow the +`Arcanist Quick Start`_ instructions. + +You can learn more about how to use arc to interact with +Phabricator in the `Arcanist User Guide`_. + +Requesting a review via the web interface +----------------------------------------- + +The tool to create and review patches in Phabricator is called +*Differential*. + +Note that you can upload patches created through various diff tools, +including git and svn. To make reviews easier, please always include +**as much context as possible** with your diff! Don't worry, Phabricator +will automatically send a diff with a smaller context in the review +email, but having the full file in the web interface will help the +reviewer understand your code. + +To get a full diff, use one of the following commands (or just use Arcanist +to upload your patch): + +* ``git diff -U999999 other-branch`` +* ``svn diff --diff-cmd=diff -x -U999999`` + +To upload a new patch: + +* Click *Differential*. +* Click *Create Diff*. +* Paste the text diff or upload the patch file. + Note that TODO +* Leave the drop down on *Create a new Revision...* and click *Continue*. +* Enter a descriptive title and summary; add reviewers and mailing + lists that you want to be included in the review. If your patch is + for LLVM, cc llvm-commits; if your patch is for Clang, cc cfe-commits. +* Click *Save*. + +To submit an updated patch: + +* Click *Differential*. +* Click *Create Diff*. +* Paste the updated diff. +* Select the review you want to from the *Attach To* dropdown and click + *Continue*. +* Click *Save*. + +Reviewing code with Phabricator +------------------------------- + +Phabricator allows you to add inline comments as well as overall comments +to a revision. To add an inline comment, select the lines of code you want +to comment on by clicking and dragging the line numbers in the diff pane. + +You can add overall comments or submit your comments at the bottom of the page. + +Phabricator has many useful features, for example allowing you to select +diffs between different versions of the patch as it was reviewed in the +*Revision Update History*. Most features are self descriptive - explore, and +if you have a question, drop by on #llvm in IRC to get help. + +Note that as e-mail is the system of reference for code reviews, and some +people prefer it over a web interface, we do not generate automated mail +when a review changes state, for example by clicking "Accept Revision" in +the web interface. Thus, please type LGTM into the comment box to accept +a change from Phabricator. + +Status +------ + +Currently, we're testing Phabricator for use with Clang/LLVM. Please let us +know whether you like it and what could be improved! + +.. _LLVM's Phabricator: http://llvm-reviews.chandlerc.com +.. _Code Repository Browser: http://llvm-reviews.chandlerc.com/diffusion/ +.. _Arcanist Quick Start: http://www.phabricator.com/docs/phabricator/article/Arcanist_Quick_Start.html +.. _Arcanist User Guide: http://www.phabricator.com/docs/phabricator/article/Arcanist_User_Guide.html diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst new file mode 100644 index 00000000..99aa5c78 --- /dev/null +++ b/docs/ProgrammersManual.rst @@ -0,0 +1,3204 @@ +======================== +LLVM Programmer's Manual +======================== + +.. contents:: + :local: + +.. warning:: + This is always a work in progress. + +.. _introduction: + +Introduction +============ + +This document is meant to highlight some of the important classes and interfaces +available in the LLVM source-base. This manual is not intended to explain what +LLVM is, how it works, and what LLVM code looks like. It assumes that you know +the basics of LLVM and are interested in writing transformations or otherwise +analyzing or manipulating the code. + +This document should get you oriented so that you can find your way in the +continuously growing source code that makes up the LLVM infrastructure. Note +that this manual is not intended to serve as a replacement for reading the +source code, so if you think there should be a method in one of these classes to +do something, but it's not listed, check the source. Links to the `doxygen +`__ sources are provided to make this as easy as +possible. + +The first section of this document describes general information that is useful +to know when working in the LLVM infrastructure, and the second describes the +Core LLVM classes. In the future this manual will be extended with information +describing how to use extension libraries, such as dominator information, CFG +traversal routines, and useful utilities like the ``InstVisitor`` (`doxygen +`__) template. + +.. _general: + +General Information +=================== + +This section contains general information that is useful if you are working in +the LLVM source-base, but that isn't specific to any particular API. + +.. _stl: + +The C++ Standard Template Library +--------------------------------- + +LLVM makes heavy use of the C++ Standard Template Library (STL), perhaps much +more than you are used to, or have seen before. Because of this, you might want +to do a little background reading in the techniques used and capabilities of the +library. There are many good pages that discuss the STL, and several books on +the subject that you can get, so it will not be discussed in this document. + +Here are some useful links: + +#. `cppreference.com + `_ - an excellent + reference for the STL and other parts of the standard C++ library. + +#. `C++ In a Nutshell `_ - This is an O'Reilly + book in the making. It has a decent Standard Library Reference that rivals + Dinkumware's, and is unfortunately no longer free since the book has been + published. + +#. `C++ Frequently Asked Questions `_. + +#. `SGI's STL Programmer's Guide `_ - Contains a + useful `Introduction to the STL + `_. + +#. `Bjarne Stroustrup's C++ Page + `_. + +#. `Bruce Eckel's Thinking in C++, 2nd ed. Volume 2 Revision 4.0 + (even better, get the book) + `_. + +You are also encouraged to take a look at the :doc:`LLVM Coding Standards +` guide which focuses on how to write maintainable code more +than where to put your curly braces. + +.. _resources: + +Other useful references +----------------------- + +#. `Using static and shared libraries across platforms + `_ + +.. _apis: + +Important and useful LLVM APIs +============================== + +Here we highlight some LLVM APIs that are generally useful and good to know +about when writing transformations. + +.. _isa: + +The ``isa<>``, ``cast<>`` and ``dyn_cast<>`` templates +------------------------------------------------------ + +The LLVM source-base makes extensive use of a custom form of RTTI. These +templates have many similarities to the C++ ``dynamic_cast<>`` operator, but +they don't have some drawbacks (primarily stemming from the fact that +``dynamic_cast<>`` only works on classes that have a v-table). Because they are +used so often, you must know what they do and how they work. All of these +templates are defined in the ``llvm/Support/Casting.h`` (`doxygen +`__) file (note that you very +rarely have to include this file directly). + +``isa<>``: + The ``isa<>`` operator works exactly like the Java "``instanceof``" operator. + It returns true or false depending on whether a reference or pointer points to + an instance of the specified class. This can be very useful for constraint + checking of various sorts (example below). + +``cast<>``: + The ``cast<>`` operator is a "checked cast" operation. It converts a pointer + or reference from a base class to a derived class, causing an assertion + failure if it is not really an instance of the right type. This should be + used in cases where you have some information that makes you believe that + something is of the right type. An example of the ``isa<>`` and ``cast<>`` + template is: + + .. code-block:: c++ + + static bool isLoopInvariant(const Value *V, const Loop *L) { + if (isa(V) || isa(V) || isa(V)) + return true; + + // Otherwise, it must be an instruction... + return !L->contains(cast(V)->getParent()); + } + + Note that you should **not** use an ``isa<>`` test followed by a ``cast<>``, + for that use the ``dyn_cast<>`` operator. + +``dyn_cast<>``: + The ``dyn_cast<>`` operator is a "checking cast" operation. It checks to see + if the operand is of the specified type, and if so, returns a pointer to it + (this operator does not work with references). If the operand is not of the + correct type, a null pointer is returned. Thus, this works very much like + the ``dynamic_cast<>`` operator in C++, and should be used in the same + circumstances. Typically, the ``dyn_cast<>`` operator is used in an ``if`` + statement or some other flow control statement like this: + + .. code-block:: c++ + + if (AllocationInst *AI = dyn_cast(Val)) { + // ... + } + + This form of the ``if`` statement effectively combines together a call to + ``isa<>`` and a call to ``cast<>`` into one statement, which is very + convenient. + + Note that the ``dyn_cast<>`` operator, like C++'s ``dynamic_cast<>`` or Java's + ``instanceof`` operator, can be abused. In particular, you should not use big + chained ``if/then/else`` blocks to check for lots of different variants of + classes. If you find yourself wanting to do this, it is much cleaner and more + efficient to use the ``InstVisitor`` class to dispatch over the instruction + type directly. + +``cast_or_null<>``: + The ``cast_or_null<>`` operator works just like the ``cast<>`` operator, + except that it allows for a null pointer as an argument (which it then + propagates). This can sometimes be useful, allowing you to combine several + null checks into one. + +``dyn_cast_or_null<>``: + The ``dyn_cast_or_null<>`` operator works just like the ``dyn_cast<>`` + operator, except that it allows for a null pointer as an argument (which it + then propagates). This can sometimes be useful, allowing you to combine + several null checks into one. + +These five templates can be used with any classes, whether they have a v-table +or not. If you want to add support for these templates, see the document +:doc:`How to set up LLVM-style RTTI for your class hierarchy +` + +.. _string_apis: + +Passing strings (the ``StringRef`` and ``Twine`` classes) +--------------------------------------------------------- + +Although LLVM generally does not do much string manipulation, we do have several +important APIs which take strings. Two important examples are the Value class +-- which has names for instructions, functions, etc. -- and the ``StringMap`` +class which is used extensively in LLVM and Clang. + +These are generic classes, and they need to be able to accept strings which may +have embedded null characters. Therefore, they cannot simply take a ``const +char *``, and taking a ``const std::string&`` requires clients to perform a heap +allocation which is usually unnecessary. Instead, many LLVM APIs use a +``StringRef`` or a ``const Twine&`` for passing strings efficiently. + +.. _StringRef: + +The ``StringRef`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``StringRef`` data type represents a reference to a constant string (a +character array and a length) and supports the common operations available on +``std::string``, but does not require heap allocation. + +It can be implicitly constructed using a C style null-terminated string, an +``std::string``, or explicitly with a character pointer and length. For +example, the ``StringRef`` find function is declared as: + +.. code-block:: c++ + + iterator find(StringRef Key); + +and clients can call it using any one of: + +.. code-block:: c++ + + Map.find("foo"); // Lookup "foo" + Map.find(std::string("bar")); // Lookup "bar" + Map.find(StringRef("\0baz", 4)); // Lookup "\0baz" + +Similarly, APIs which need to return a string may return a ``StringRef`` +instance, which can be used directly or converted to an ``std::string`` using +the ``str`` member function. See ``llvm/ADT/StringRef.h`` (`doxygen +`__) for more +information. + +You should rarely use the ``StringRef`` class directly, because it contains +pointers to external memory it is not generally safe to store an instance of the +class (unless you know that the external storage will not be freed). +``StringRef`` is small and pervasive enough in LLVM that it should always be +passed by value. + +The ``Twine`` class +^^^^^^^^^^^^^^^^^^^ + +The ``Twine`` (`doxygen `__) +class is an efficient way for APIs to accept concatenated strings. For example, +a common LLVM paradigm is to name one instruction based on the name of another +instruction with a suffix, for example: + +.. code-block:: c++ + + New = CmpInst::Create(..., SO->getName() + ".cmp"); + +The ``Twine`` class is effectively a lightweight `rope +`_ which points to +temporary (stack allocated) objects. Twines can be implicitly constructed as +the result of the plus operator applied to strings (i.e., a C strings, an +``std::string``, or a ``StringRef``). The twine delays the actual concatenation +of strings until it is actually required, at which point it can be efficiently +rendered directly into a character array. This avoids unnecessary heap +allocation involved in constructing the temporary results of string +concatenation. See ``llvm/ADT/Twine.h`` (`doxygen +`__) and :ref:`here ` +for more information. + +As with a ``StringRef``, ``Twine`` objects point to external memory and should +almost never be stored or mentioned directly. They are intended solely for use +when defining a function which should be able to efficiently accept concatenated +strings. + +.. _DEBUG: + +The ``DEBUG()`` macro and ``-debug`` option +------------------------------------------- + +Often when working on your pass you will put a bunch of debugging printouts and +other code into your pass. After you get it working, you want to remove it, but +you may need it again in the future (to work out new bugs that you run across). + +Naturally, because of this, you don't want to delete the debug printouts, but +you don't want them to always be noisy. A standard compromise is to comment +them out, allowing you to enable them if you need them in the future. + +The ``llvm/Support/Debug.h`` (`doxygen +`__) file provides a macro named +``DEBUG()`` that is a much nicer solution to this problem. Basically, you can +put arbitrary code into the argument of the ``DEBUG`` macro, and it is only +executed if '``opt``' (or any other tool) is run with the '``-debug``' command +line argument: + +.. code-block:: c++ + + DEBUG(errs() << "I am here!\n"); + +Then you can run your pass like this: + +.. code-block:: none + + $ opt < a.bc > /dev/null -mypass + + $ opt < a.bc > /dev/null -mypass -debug + I am here! + +Using the ``DEBUG()`` macro instead of a home-brewed solution allows you to not +have to create "yet another" command line option for the debug output for your +pass. Note that ``DEBUG()`` macros are disabled for optimized builds, so they +do not cause a performance impact at all (for the same reason, they should also +not contain side-effects!). + +One additional nice thing about the ``DEBUG()`` macro is that you can enable or +disable it directly in gdb. Just use "``set DebugFlag=0``" or "``set +DebugFlag=1``" from the gdb if the program is running. If the program hasn't +been started yet, you can always just run it with ``-debug``. + +.. _DEBUG_TYPE: + +Fine grained debug info with ``DEBUG_TYPE`` and the ``-debug-only`` option +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes you may find yourself in a situation where enabling ``-debug`` just +turns on **too much** information (such as when working on the code generator). +If you want to enable debug information with more fine-grained control, you +define the ``DEBUG_TYPE`` macro and the ``-debug`` only option as follows: + +.. code-block:: c++ + + #undef DEBUG_TYPE + DEBUG(errs() << "No debug type\n"); + #define DEBUG_TYPE "foo" + DEBUG(errs() << "'foo' debug type\n"); + #undef DEBUG_TYPE + #define DEBUG_TYPE "bar" + DEBUG(errs() << "'bar' debug type\n")); + #undef DEBUG_TYPE + #define DEBUG_TYPE "" + DEBUG(errs() << "No debug type (2)\n"); + +Then you can run your pass like this: + +.. code-block:: none + + $ opt < a.bc > /dev/null -mypass + + $ opt < a.bc > /dev/null -mypass -debug + No debug type + 'foo' debug type + 'bar' debug type + No debug type (2) + $ opt < a.bc > /dev/null -mypass -debug-only=foo + 'foo' debug type + $ opt < a.bc > /dev/null -mypass -debug-only=bar + 'bar' debug type + +Of course, in practice, you should only set ``DEBUG_TYPE`` at the top of a file, +to specify the debug type for the entire module (if you do this before you +``#include "llvm/Support/Debug.h"``, you don't have to insert the ugly +``#undef``'s). Also, you should use names more meaningful than "foo" and "bar", +because there is no system in place to ensure that names do not conflict. If +two different modules use the same string, they will all be turned on when the +name is specified. This allows, for example, all debug information for +instruction scheduling to be enabled with ``-debug-type=InstrSched``, even if +the source lives in multiple files. + +The ``DEBUG_WITH_TYPE`` macro is also available for situations where you would +like to set ``DEBUG_TYPE``, but only for one specific ``DEBUG`` statement. It +takes an additional first parameter, which is the type to use. For example, the +preceding example could be written as: + +.. code-block:: c++ + + DEBUG_WITH_TYPE("", errs() << "No debug type\n"); + DEBUG_WITH_TYPE("foo", errs() << "'foo' debug type\n"); + DEBUG_WITH_TYPE("bar", errs() << "'bar' debug type\n")); + DEBUG_WITH_TYPE("", errs() << "No debug type (2)\n"); + +.. _Statistic: + +The ``Statistic`` class & ``-stats`` option +------------------------------------------- + +The ``llvm/ADT/Statistic.h`` (`doxygen +`__) file provides a class +named ``Statistic`` that is used as a unified way to keep track of what the LLVM +compiler is doing and how effective various optimizations are. It is useful to +see what optimizations are contributing to making a particular program run +faster. + +Often you may run your pass on some big program, and you're interested to see +how many times it makes a certain transformation. Although you can do this with +hand inspection, or some ad-hoc method, this is a real pain and not very useful +for big programs. Using the ``Statistic`` class makes it very easy to keep +track of this information, and the calculated information is presented in a +uniform manner with the rest of the passes being executed. + +There are many examples of ``Statistic`` uses, but the basics of using it are as +follows: + +#. Define your statistic like this: + + .. code-block:: c++ + + #define DEBUG_TYPE "mypassname" // This goes before any #includes. + STATISTIC(NumXForms, "The # of times I did stuff"); + + The ``STATISTIC`` macro defines a static variable, whose name is specified by + the first argument. The pass name is taken from the ``DEBUG_TYPE`` macro, and + the description is taken from the second argument. The variable defined + ("NumXForms" in this case) acts like an unsigned integer. + +#. Whenever you make a transformation, bump the counter: + + .. code-block:: c++ + + ++NumXForms; // I did stuff! + +That's all you have to do. To get '``opt``' to print out the statistics +gathered, use the '``-stats``' option: + +.. code-block:: none + + $ opt -stats -mypassname < program.bc > /dev/null + ... statistics output ... + +When running ``opt`` on a C file from the SPEC benchmark suite, it gives a +report that looks like this: + +.. code-block:: none + + 7646 bitcodewriter - Number of normal instructions + 725 bitcodewriter - Number of oversized instructions + 129996 bitcodewriter - Number of bitcode bytes written + 2817 raise - Number of insts DCEd or constprop'd + 3213 raise - Number of cast-of-self removed + 5046 raise - Number of expression trees converted + 75 raise - Number of other getelementptr's formed + 138 raise - Number of load/store peepholes + 42 deadtypeelim - Number of unused typenames removed from symtab + 392 funcresolve - Number of varargs functions resolved + 27 globaldce - Number of global variables removed + 2 adce - Number of basic blocks removed + 134 cee - Number of branches revectored + 49 cee - Number of setcc instruction eliminated + 532 gcse - Number of loads removed + 2919 gcse - Number of instructions removed + 86 indvars - Number of canonical indvars added + 87 indvars - Number of aux indvars removed + 25 instcombine - Number of dead inst eliminate + 434 instcombine - Number of insts combined + 248 licm - Number of load insts hoisted + 1298 licm - Number of insts hoisted to a loop pre-header + 3 licm - Number of insts hoisted to multiple loop preds (bad, no loop pre-header) + 75 mem2reg - Number of alloca's promoted + 1444 cfgsimplify - Number of blocks simplified + +Obviously, with so many optimizations, having a unified framework for this stuff +is very nice. Making your pass fit well into the framework makes it more +maintainable and useful. + +.. _ViewGraph: + +Viewing graphs while debugging code +----------------------------------- + +Several of the important data structures in LLVM are graphs: for example CFGs +made out of LLVM :ref:`BasicBlocks `, CFGs made out of LLVM +:ref:`MachineBasicBlocks `, and :ref:`Instruction Selection +DAGs `. In many cases, while debugging various parts of the +compiler, it is nice to instantly visualize these graphs. + +LLVM provides several callbacks that are available in a debug build to do +exactly that. If you call the ``Function::viewCFG()`` method, for example, the +current LLVM tool will pop up a window containing the CFG for the function where +each basic block is a node in the graph, and each node contains the instructions +in the block. Similarly, there also exists ``Function::viewCFGOnly()`` (does +not include the instructions), the ``MachineFunction::viewCFG()`` and +``MachineFunction::viewCFGOnly()``, and the ``SelectionDAG::viewGraph()`` +methods. Within GDB, for example, you can usually use something like ``call +DAG.viewGraph()`` to pop up a window. Alternatively, you can sprinkle calls to +these functions in your code in places you want to debug. + +Getting this to work requires a small amount of configuration. On Unix systems +with X11, install the `graphviz `_ toolkit, and make +sure 'dot' and 'gv' are in your path. If you are running on Mac OS/X, download +and install the Mac OS/X `Graphviz program +`_ and add +``/Applications/Graphviz.app/Contents/MacOS/`` (or wherever you install it) to +your path. Once in your system and path are set up, rerun the LLVM configure +script and rebuild LLVM to enable this functionality. + +``SelectionDAG`` has been extended to make it easier to locate *interesting* +nodes in large complex graphs. From gdb, if you ``call DAG.setGraphColor(node, +"color")``, then the next ``call DAG.viewGraph()`` would highlight the node in +the specified color (choices of colors can be found at `colors +`_.) More complex node attributes +can be provided with ``call DAG.setGraphAttrs(node, "attributes")`` (choices can +be found at `Graph attributes `_.) +If you want to restart and clear all the current graph attributes, then you can +``call DAG.clearGraphAttrs()``. + +Note that graph visualization features are compiled out of Release builds to +reduce file size. This means that you need a Debug+Asserts or Release+Asserts +build to use these features. + +.. _datastructure: + +Picking the Right Data Structure for a Task +=========================================== + +LLVM has a plethora of data structures in the ``llvm/ADT/`` directory, and we +commonly use STL data structures. This section describes the trade-offs you +should consider when you pick one. + +The first step is a choose your own adventure: do you want a sequential +container, a set-like container, or a map-like container? The most important +thing when choosing a container is the algorithmic properties of how you plan to +access the container. Based on that, you should use: + + +* a :ref:`map-like ` container if you need efficient look-up of a + value based on another value. Map-like containers also support efficient + queries for containment (whether a key is in the map). Map-like containers + generally do not support efficient reverse mapping (values to keys). If you + need that, use two maps. Some map-like containers also support efficient + iteration through the keys in sorted order. Map-like containers are the most + expensive sort, only use them if you need one of these capabilities. + +* a :ref:`set-like ` container if you need to put a bunch of stuff into + a container that automatically eliminates duplicates. Some set-like + containers support efficient iteration through the elements in sorted order. + Set-like containers are more expensive than sequential containers. + +* a :ref:`sequential ` container provides the most efficient way + to add elements and keeps track of the order they are added to the collection. + They permit duplicates and support efficient iteration, but do not support + efficient look-up based on a key. + +* a :ref:`string ` container is a specialized sequential container or + reference structure that is used for character or byte arrays. + +* a :ref:`bit ` container provides an efficient way to store and + perform set operations on sets of numeric id's, while automatically + eliminating duplicates. Bit containers require a maximum of 1 bit for each + identifier you want to store. + +Once the proper category of container is determined, you can fine tune the +memory use, constant factors, and cache behaviors of access by intelligently +picking a member of the category. Note that constant factors and cache behavior +can be a big deal. If you have a vector that usually only contains a few +elements (but could contain many), for example, it's much better to use +:ref:`SmallVector ` than :ref:`vector `. Doing so +avoids (relatively) expensive malloc/free calls, which dwarf the cost of adding +the elements to the container. + +.. _ds_sequential: + +Sequential Containers (std::vector, std::list, etc) +--------------------------------------------------- + +There are a variety of sequential containers available for you, based on your +needs. Pick the first in this section that will do what you want. + +.. _dss_arrayref: + +llvm/ADT/ArrayRef.h +^^^^^^^^^^^^^^^^^^^ + +The ``llvm::ArrayRef`` class is the preferred class to use in an interface that +accepts a sequential list of elements in memory and just reads from them. By +taking an ``ArrayRef``, the API can be passed a fixed size array, an +``std::vector``, an ``llvm::SmallVector`` and anything else that is contiguous +in memory. + +.. _dss_fixedarrays: + +Fixed Size Arrays +^^^^^^^^^^^^^^^^^ + +Fixed size arrays are very simple and very fast. They are good if you know +exactly how many elements you have, or you have a (low) upper bound on how many +you have. + +.. _dss_heaparrays: + +Heap Allocated Arrays +^^^^^^^^^^^^^^^^^^^^^ + +Heap allocated arrays (``new[]`` + ``delete[]``) are also simple. They are good +if the number of elements is variable, if you know how many elements you will +need before the array is allocated, and if the array is usually large (if not, +consider a :ref:`SmallVector `). The cost of a heap allocated +array is the cost of the new/delete (aka malloc/free). Also note that if you +are allocating an array of a type with a constructor, the constructor and +destructors will be run for every element in the array (re-sizable vectors only +construct those elements actually used). + +.. _dss_tinyptrvector: + +llvm/ADT/TinyPtrVector.h +^^^^^^^^^^^^^^^^^^^^^^^^ + +``TinyPtrVector`` is a highly specialized collection class that is +optimized to avoid allocation in the case when a vector has zero or one +elements. It has two major restrictions: 1) it can only hold values of pointer +type, and 2) it cannot hold a null pointer. + +Since this container is highly specialized, it is rarely used. + +.. _dss_smallvector: + +llvm/ADT/SmallVector.h +^^^^^^^^^^^^^^^^^^^^^^ + +``SmallVector`` is a simple class that looks and smells just like +``vector``: it supports efficient iteration, lays out elements in memory +order (so you can do pointer arithmetic between elements), supports efficient +push_back/pop_back operations, supports efficient random access to its elements, +etc. + +The advantage of SmallVector is that it allocates space for some number of +elements (N) **in the object itself**. Because of this, if the SmallVector is +dynamically smaller than N, no malloc is performed. This can be a big win in +cases where the malloc/free call is far more expensive than the code that +fiddles around with the elements. + +This is good for vectors that are "usually small" (e.g. the number of +predecessors/successors of a block is usually less than 8). On the other hand, +this makes the size of the SmallVector itself large, so you don't want to +allocate lots of them (doing so will waste a lot of space). As such, +SmallVectors are most useful when on the stack. + +SmallVector also provides a nice portable and efficient replacement for +``alloca``. + +.. note:: + + Prefer to use ``SmallVectorImpl`` as a parameter type. + + In APIs that don't care about the "small size" (most?), prefer to use + the ``SmallVectorImpl`` class, which is basically just the "vector + header" (and methods) without the elements allocated after it. Note that + ``SmallVector`` inherits from ``SmallVectorImpl`` so the + conversion is implicit and costs nothing. E.g. + + .. code-block:: c++ + + // BAD: Clients cannot pass e.g. SmallVector. + hardcodedSmallSize(SmallVector &Out); + // GOOD: Clients can pass any SmallVector. + allowsAnySmallSize(SmallVectorImpl &Out); + + void someFunc() { + SmallVector Vec; + hardcodedSmallSize(Vec); // Error. + allowsAnySmallSize(Vec); // Works. + } + + Even though it has "``Impl``" in the name, this is so widely used that + it really isn't "private to the implementation" anymore. A name like + ``SmallVectorHeader`` would be more appropriate. + +.. _dss_vector: + + +^^^^^^^^ + +``std::vector`` is well loved and respected. It is useful when SmallVector +isn't: when the size of the vector is often large (thus the small optimization +will rarely be a benefit) or if you will be allocating many instances of the +vector itself (which would waste space for elements that aren't in the +container). vector is also useful when interfacing with code that expects +vectors :). + +One worthwhile note about std::vector: avoid code like this: + +.. code-block:: c++ + + for ( ... ) { + std::vector V; + // make use of V. + } + +Instead, write this as: + +.. code-block:: c++ + + std::vector V; + for ( ... ) { + // make use of V. + V.clear(); + } + +Doing so will save (at least) one heap allocation and free per iteration of the +loop. + +.. _dss_deque: + + +^^^^^^^ + +``std::deque`` is, in some senses, a generalized version of ``std::vector``. +Like ``std::vector``, it provides constant time random access and other similar +properties, but it also provides efficient access to the front of the list. It +does not guarantee continuity of elements within memory. + +In exchange for this extra flexibility, ``std::deque`` has significantly higher +constant factor costs than ``std::vector``. If possible, use ``std::vector`` or +something cheaper. + +.. _dss_list: + + +^^^^^^ + +``std::list`` is an extremely inefficient class that is rarely useful. It +performs a heap allocation for every element inserted into it, thus having an +extremely high constant factor, particularly for small data types. +``std::list`` also only supports bidirectional iteration, not random access +iteration. + +In exchange for this high cost, std::list supports efficient access to both ends +of the list (like ``std::deque``, but unlike ``std::vector`` or +``SmallVector``). In addition, the iterator invalidation characteristics of +std::list are stronger than that of a vector class: inserting or removing an +element into the list does not invalidate iterator or pointers to other elements +in the list. + +.. _dss_ilist: + +llvm/ADT/ilist.h +^^^^^^^^^^^^^^^^ + +``ilist`` implements an 'intrusive' doubly-linked list. It is intrusive, +because it requires the element to store and provide access to the prev/next +pointers for the list. + +``ilist`` has the same drawbacks as ``std::list``, and additionally requires an +``ilist_traits`` implementation for the element type, but it provides some novel +characteristics. In particular, it can efficiently store polymorphic objects, +the traits class is informed when an element is inserted or removed from the +list, and ``ilist``\ s are guaranteed to support a constant-time splice +operation. + +These properties are exactly what we want for things like ``Instruction``\ s and +basic blocks, which is why these are implemented with ``ilist``\ s. + +Related classes of interest are explained in the following subsections: + +* :ref:`ilist_traits ` + +* :ref:`iplist ` + +* :ref:`llvm/ADT/ilist_node.h ` + +* :ref:`Sentinels ` + +.. _dss_packedvector: + +llvm/ADT/PackedVector.h +^^^^^^^^^^^^^^^^^^^^^^^ + +Useful for storing a vector of values using only a few number of bits for each +value. Apart from the standard operations of a vector-like container, it can +also perform an 'or' set operation. + +For example: + +.. code-block:: c++ + + enum State { + None = 0x0, + FirstCondition = 0x1, + SecondCondition = 0x2, + Both = 0x3 + }; + + State get() { + PackedVector Vec1; + Vec1.push_back(FirstCondition); + + PackedVector Vec2; + Vec2.push_back(SecondCondition); + + Vec1 |= Vec2; + return Vec1[0]; // returns 'Both'. + } + +.. _dss_ilist_traits: + +ilist_traits +^^^^^^^^^^^^ + +``ilist_traits`` is ``ilist``'s customization mechanism. ``iplist`` +(and consequently ``ilist``) publicly derive from this traits class. + +.. _dss_iplist: + +iplist +^^^^^^ + +``iplist`` is ``ilist``'s base and as such supports a slightly narrower +interface. Notably, inserters from ``T&`` are absent. + +``ilist_traits`` is a public base of this class and can be used for a wide +variety of customizations. + +.. _dss_ilist_node: + +llvm/ADT/ilist_node.h +^^^^^^^^^^^^^^^^^^^^^ + +``ilist_node`` implements a the forward and backward links that are expected +by the ``ilist`` (and analogous containers) in the default manner. + +``ilist_node``\ s are meant to be embedded in the node type ``T``, usually +``T`` publicly derives from ``ilist_node``. + +.. _dss_ilist_sentinel: + +Sentinels +^^^^^^^^^ + +``ilist``\ s have another specialty that must be considered. To be a good +citizen in the C++ ecosystem, it needs to support the standard container +operations, such as ``begin`` and ``end`` iterators, etc. Also, the +``operator--`` must work correctly on the ``end`` iterator in the case of +non-empty ``ilist``\ s. + +The only sensible solution to this problem is to allocate a so-called *sentinel* +along with the intrusive list, which serves as the ``end`` iterator, providing +the back-link to the last element. However conforming to the C++ convention it +is illegal to ``operator++`` beyond the sentinel and it also must not be +dereferenced. + +These constraints allow for some implementation freedom to the ``ilist`` how to +allocate and store the sentinel. The corresponding policy is dictated by +``ilist_traits``. By default a ``T`` gets heap-allocated whenever the need +for a sentinel arises. + +While the default policy is sufficient in most cases, it may break down when +``T`` does not provide a default constructor. Also, in the case of many +instances of ``ilist``\ s, the memory overhead of the associated sentinels is +wasted. To alleviate the situation with numerous and voluminous +``T``-sentinels, sometimes a trick is employed, leading to *ghostly sentinels*. + +Ghostly sentinels are obtained by specially-crafted ``ilist_traits`` which +superpose the sentinel with the ``ilist`` instance in memory. Pointer +arithmetic is used to obtain the sentinel, which is relative to the ``ilist``'s +``this`` pointer. The ``ilist`` is augmented by an extra pointer, which serves +as the back-link of the sentinel. This is the only field in the ghostly +sentinel which can be legally accessed. + +.. _dss_other: + +Other Sequential Container options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Other STL containers are available, such as ``std::string``. + +There are also various STL adapter classes such as ``std::queue``, +``std::priority_queue``, ``std::stack``, etc. These provide simplified access +to an underlying container but don't affect the cost of the container itself. + +.. _ds_string: + +String-like containers +---------------------- + +There are a variety of ways to pass around and use strings in C and C++, and +LLVM adds a few new options to choose from. Pick the first option on this list +that will do what you need, they are ordered according to their relative cost. + +Note that is is generally preferred to *not* pass strings around as ``const +char*``'s. These have a number of problems, including the fact that they +cannot represent embedded nul ("\0") characters, and do not have a length +available efficiently. The general replacement for '``const char*``' is +StringRef. + +For more information on choosing string containers for APIs, please see +:ref:`Passing Strings `. + +.. _dss_stringref: + +llvm/ADT/StringRef.h +^^^^^^^^^^^^^^^^^^^^ + +The StringRef class is a simple value class that contains a pointer to a +character and a length, and is quite related to the :ref:`ArrayRef +` class (but specialized for arrays of characters). Because +StringRef carries a length with it, it safely handles strings with embedded nul +characters in it, getting the length does not require a strlen call, and it even +has very convenient APIs for slicing and dicing the character range that it +represents. + +StringRef is ideal for passing simple strings around that are known to be live, +either because they are C string literals, std::string, a C array, or a +SmallVector. Each of these cases has an efficient implicit conversion to +StringRef, which doesn't result in a dynamic strlen being executed. + +StringRef has a few major limitations which make more powerful string containers +useful: + +#. You cannot directly convert a StringRef to a 'const char*' because there is + no way to add a trailing nul (unlike the .c_str() method on various stronger + classes). + +#. StringRef doesn't own or keep alive the underlying string bytes. + As such it can easily lead to dangling pointers, and is not suitable for + embedding in datastructures in most cases (instead, use an std::string or + something like that). + +#. For the same reason, StringRef cannot be used as the return value of a + method if the method "computes" the result string. Instead, use std::string. + +#. StringRef's do not allow you to mutate the pointed-to string bytes and it + doesn't allow you to insert or remove bytes from the range. For editing + operations like this, it interoperates with the :ref:`Twine ` + class. + +Because of its strengths and limitations, it is very common for a function to +take a StringRef and for a method on an object to return a StringRef that points +into some string that it owns. + +.. _dss_twine: + +llvm/ADT/Twine.h +^^^^^^^^^^^^^^^^ + +The Twine class is used as an intermediary datatype for APIs that want to take a +string that can be constructed inline with a series of concatenations. Twine +works by forming recursive instances of the Twine datatype (a simple value +object) on the stack as temporary objects, linking them together into a tree +which is then linearized when the Twine is consumed. Twine is only safe to use +as the argument to a function, and should always be a const reference, e.g.: + +.. code-block:: c++ + + void foo(const Twine &T); + ... + StringRef X = ... + unsigned i = ... + foo(X + "." + Twine(i)); + +This example forms a string like "blarg.42" by concatenating the values +together, and does not form intermediate strings containing "blarg" or "blarg.". + +Because Twine is constructed with temporary objects on the stack, and because +these instances are destroyed at the end of the current statement, it is an +inherently dangerous API. For example, this simple variant contains undefined +behavior and will probably crash: + +.. code-block:: c++ + + void foo(const Twine &T); + ... + StringRef X = ... + unsigned i = ... + const Twine &Tmp = X + "." + Twine(i); + foo(Tmp); + +... because the temporaries are destroyed before the call. That said, Twine's +are much more efficient than intermediate std::string temporaries, and they work +really well with StringRef. Just be aware of their limitations. + +.. _dss_smallstring: + +llvm/ADT/SmallString.h +^^^^^^^^^^^^^^^^^^^^^^ + +SmallString is a subclass of :ref:`SmallVector ` that adds some +convenience APIs like += that takes StringRef's. SmallString avoids allocating +memory in the case when the preallocated space is enough to hold its data, and +it calls back to general heap allocation when required. Since it owns its data, +it is very safe to use and supports full mutation of the string. + +Like SmallVector's, the big downside to SmallString is their sizeof. While they +are optimized for small strings, they themselves are not particularly small. +This means that they work great for temporary scratch buffers on the stack, but +should not generally be put into the heap: it is very rare to see a SmallString +as the member of a frequently-allocated heap data structure or returned +by-value. + +.. _dss_stdstring: + +std::string +^^^^^^^^^^^ + +The standard C++ std::string class is a very general class that (like +SmallString) owns its underlying data. sizeof(std::string) is very reasonable +so it can be embedded into heap data structures and returned by-value. On the +other hand, std::string is highly inefficient for inline editing (e.g. +concatenating a bunch of stuff together) and because it is provided by the +standard library, its performance characteristics depend a lot of the host +standard library (e.g. libc++ and MSVC provide a highly optimized string class, +GCC contains a really slow implementation). + +The major disadvantage of std::string is that almost every operation that makes +them larger can allocate memory, which is slow. As such, it is better to use +SmallVector or Twine as a scratch buffer, but then use std::string to persist +the result. + +.. _ds_set: + +Set-Like Containers (std::set, SmallSet, SetVector, etc) +-------------------------------------------------------- + +Set-like containers are useful when you need to canonicalize multiple values +into a single representation. There are several different choices for how to do +this, providing various trade-offs. + +.. _dss_sortedvectorset: + +A sorted 'vector' +^^^^^^^^^^^^^^^^^ + +If you intend to insert a lot of elements, then do a lot of queries, a great +approach is to use a vector (or other sequential container) with +std::sort+std::unique to remove duplicates. This approach works really well if +your usage pattern has these two distinct phases (insert then query), and can be +coupled with a good choice of :ref:`sequential container `. + +This combination provides the several nice properties: the result data is +contiguous in memory (good for cache locality), has few allocations, is easy to +address (iterators in the final vector are just indices or pointers), and can be +efficiently queried with a standard binary search (e.g. +``std::lower_bound``; if you want the whole range of elements comparing +equal, use ``std::equal_range``). + +.. _dss_smallset: + +llvm/ADT/SmallSet.h +^^^^^^^^^^^^^^^^^^^ + +If you have a set-like data structure that is usually small and whose elements +are reasonably small, a ``SmallSet`` is a good choice. This set has +space for N elements in place (thus, if the set is dynamically smaller than N, +no malloc traffic is required) and accesses them with a simple linear search. +When the set grows beyond 'N' elements, it allocates a more expensive +representation that guarantees efficient access (for most types, it falls back +to std::set, but for pointers it uses something far better, :ref:`SmallPtrSet +`. + +The magic of this class is that it handles small sets extremely efficiently, but +gracefully handles extremely large sets without loss of efficiency. The +drawback is that the interface is quite small: it supports insertion, queries +and erasing, but does not support iteration. + +.. _dss_smallptrset: + +llvm/ADT/SmallPtrSet.h +^^^^^^^^^^^^^^^^^^^^^^ + +SmallPtrSet has all the advantages of ``SmallSet`` (and a ``SmallSet`` of +pointers is transparently implemented with a ``SmallPtrSet``), but also supports +iterators. If more than 'N' insertions are performed, a single quadratically +probed hash table is allocated and grows as needed, providing extremely +efficient access (constant time insertion/deleting/queries with low constant +factors) and is very stingy with malloc traffic. + +Note that, unlike ``std::set``, the iterators of ``SmallPtrSet`` are invalidated +whenever an insertion occurs. Also, the values visited by the iterators are not +visited in sorted order. + +.. _dss_denseset: + +llvm/ADT/DenseSet.h +^^^^^^^^^^^^^^^^^^^ + +DenseSet is a simple quadratically probed hash table. It excels at supporting +small values: it uses a single allocation to hold all of the pairs that are +currently inserted in the set. DenseSet is a great way to unique small values +that are not simple pointers (use :ref:`SmallPtrSet ` for +pointers). Note that DenseSet has the same requirements for the value type that +:ref:`DenseMap ` has. + +.. _dss_sparseset: + +llvm/ADT/SparseSet.h +^^^^^^^^^^^^^^^^^^^^ + +SparseSet holds a small number of objects identified by unsigned keys of +moderate size. It uses a lot of memory, but provides operations that are almost +as fast as a vector. Typical keys are physical registers, virtual registers, or +numbered basic blocks. + +SparseSet is useful for algorithms that need very fast clear/find/insert/erase +and fast iteration over small sets. It is not intended for building composite +data structures. + +.. _dss_sparsemultiset: + +llvm/ADT/SparseMultiSet.h +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +SparseMultiSet adds multiset behavior to SparseSet, while retaining SparseSet's +desirable attributes. Like SparseSet, it typically uses a lot of memory, but +provides operations that are almost as fast as a vector. Typical keys are +physical registers, virtual registers, or numbered basic blocks. + +SparseMultiSet is useful for algorithms that need very fast +clear/find/insert/erase of the entire collection, and iteration over sets of +elements sharing a key. It is often a more efficient choice than using composite +data structures (e.g. vector-of-vectors, map-of-vectors). It is not intended for +building composite data structures. + +.. _dss_FoldingSet: + +llvm/ADT/FoldingSet.h +^^^^^^^^^^^^^^^^^^^^^ + +FoldingSet is an aggregate class that is really good at uniquing +expensive-to-create or polymorphic objects. It is a combination of a chained +hash table with intrusive links (uniqued objects are required to inherit from +FoldingSetNode) that uses :ref:`SmallVector ` as part of its ID +process. + +Consider a case where you want to implement a "getOrCreateFoo" method for a +complex object (for example, a node in the code generator). The client has a +description of **what** it wants to generate (it knows the opcode and all the +operands), but we don't want to 'new' a node, then try inserting it into a set +only to find out it already exists, at which point we would have to delete it +and return the node that already exists. + +To support this style of client, FoldingSet perform a query with a +FoldingSetNodeID (which wraps SmallVector) that can be used to describe the +element that we want to query for. The query either returns the element +matching the ID or it returns an opaque ID that indicates where insertion should +take place. Construction of the ID usually does not require heap traffic. + +Because FoldingSet uses intrusive links, it can support polymorphic objects in +the set (for example, you can have SDNode instances mixed with LoadSDNodes). +Because the elements are individually allocated, pointers to the elements are +stable: inserting or removing elements does not invalidate any pointers to other +elements. + +.. _dss_set: + + +^^^^^ + +``std::set`` is a reasonable all-around set class, which is decent at many +things but great at nothing. std::set allocates memory for each element +inserted (thus it is very malloc intensive) and typically stores three pointers +per element in the set (thus adding a large amount of per-element space +overhead). It offers guaranteed log(n) performance, which is not particularly +fast from a complexity standpoint (particularly if the elements of the set are +expensive to compare, like strings), and has extremely high constant factors for +lookup, insertion and removal. + +The advantages of std::set are that its iterators are stable (deleting or +inserting an element from the set does not affect iterators or pointers to other +elements) and that iteration over the set is guaranteed to be in sorted order. +If the elements in the set are large, then the relative overhead of the pointers +and malloc traffic is not a big deal, but if the elements of the set are small, +std::set is almost never a good choice. + +.. _dss_setvector: + +llvm/ADT/SetVector.h +^^^^^^^^^^^^^^^^^^^^ + +LLVM's ``SetVector`` is an adapter class that combines your choice of a +set-like container along with a :ref:`Sequential Container ` The +important property that this provides is efficient insertion with uniquing +(duplicate elements are ignored) with iteration support. It implements this by +inserting elements into both a set-like container and the sequential container, +using the set-like container for uniquing and the sequential container for +iteration. + +The difference between SetVector and other sets is that the order of iteration +is guaranteed to match the order of insertion into the SetVector. This property +is really important for things like sets of pointers. Because pointer values +are non-deterministic (e.g. vary across runs of the program on different +machines), iterating over the pointers in the set will not be in a well-defined +order. + +The drawback of SetVector is that it requires twice as much space as a normal +set and has the sum of constant factors from the set-like container and the +sequential container that it uses. Use it **only** if you need to iterate over +the elements in a deterministic order. SetVector is also expensive to delete +elements out of (linear time), unless you use its "pop_back" method, which is +faster. + +``SetVector`` is an adapter class that defaults to using ``std::vector`` and a +size 16 ``SmallSet`` for the underlying containers, so it is quite expensive. +However, ``"llvm/ADT/SetVector.h"`` also provides a ``SmallSetVector`` class, +which defaults to using a ``SmallVector`` and ``SmallSet`` of a specified size. +If you use this, and if your sets are dynamically smaller than ``N``, you will +save a lot of heap traffic. + +.. _dss_uniquevector: + +llvm/ADT/UniqueVector.h +^^^^^^^^^^^^^^^^^^^^^^^ + +UniqueVector is similar to :ref:`SetVector ` but it retains a +unique ID for each element inserted into the set. It internally contains a map +and a vector, and it assigns a unique ID for each value inserted into the set. + +UniqueVector is very expensive: its cost is the sum of the cost of maintaining +both the map and vector, it has high complexity, high constant factors, and +produces a lot of malloc traffic. It should be avoided. + +.. _dss_immutableset: + +llvm/ADT/ImmutableSet.h +^^^^^^^^^^^^^^^^^^^^^^^ + +ImmutableSet is an immutable (functional) set implementation based on an AVL +tree. Adding or removing elements is done through a Factory object and results +in the creation of a new ImmutableSet object. If an ImmutableSet already exists +with the given contents, then the existing one is returned; equality is compared +with a FoldingSetNodeID. The time and space complexity of add or remove +operations is logarithmic in the size of the original set. + +There is no method for returning an element of the set, you can only check for +membership. + +.. _dss_otherset: + +Other Set-Like Container Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The STL provides several other options, such as std::multiset and the various +"hash_set" like containers (whether from C++ TR1 or from the SGI library). We +never use hash_set and unordered_set because they are generally very expensive +(each insertion requires a malloc) and very non-portable. + +std::multiset is useful if you're not interested in elimination of duplicates, +but has all the drawbacks of std::set. A sorted vector (where you don't delete +duplicate entries) or some other approach is almost always better. + +.. _ds_map: + +Map-Like Containers (std::map, DenseMap, etc) +--------------------------------------------- + +Map-like containers are useful when you want to associate data to a key. As +usual, there are a lot of different ways to do this. :) + +.. _dss_sortedvectormap: + +A sorted 'vector' +^^^^^^^^^^^^^^^^^ + +If your usage pattern follows a strict insert-then-query approach, you can +trivially use the same approach as :ref:`sorted vectors for set-like containers +`. The only difference is that your query function (which +uses std::lower_bound to get efficient log(n) lookup) should only compare the +key, not both the key and value. This yields the same advantages as sorted +vectors for sets. + +.. _dss_stringmap: + +llvm/ADT/StringMap.h +^^^^^^^^^^^^^^^^^^^^ + +Strings are commonly used as keys in maps, and they are difficult to support +efficiently: they are variable length, inefficient to hash and compare when +long, expensive to copy, etc. StringMap is a specialized container designed to +cope with these issues. It supports mapping an arbitrary range of bytes to an +arbitrary other object. + +The StringMap implementation uses a quadratically-probed hash table, where the +buckets store a pointer to the heap allocated entries (and some other stuff). +The entries in the map must be heap allocated because the strings are variable +length. The string data (key) and the element object (value) are stored in the +same allocation with the string data immediately after the element object. +This container guarantees the "``(char*)(&Value+1)``" points to the key string +for a value. + +The StringMap is very fast for several reasons: quadratic probing is very cache +efficient for lookups, the hash value of strings in buckets is not recomputed +when looking up an element, StringMap rarely has to touch the memory for +unrelated objects when looking up a value (even when hash collisions happen), +hash table growth does not recompute the hash values for strings already in the +table, and each pair in the map is store in a single allocation (the string data +is stored in the same allocation as the Value of a pair). + +StringMap also provides query methods that take byte ranges, so it only ever +copies a string if a value is inserted into the table. + +StringMap iteratation order, however, is not guaranteed to be deterministic, so +any uses which require that should instead use a std::map. + +.. _dss_indexmap: + +llvm/ADT/IndexedMap.h +^^^^^^^^^^^^^^^^^^^^^ + +IndexedMap is a specialized container for mapping small dense integers (or +values that can be mapped to small dense integers) to some other type. It is +internally implemented as a vector with a mapping function that maps the keys +to the dense integer range. + +This is useful for cases like virtual registers in the LLVM code generator: they +have a dense mapping that is offset by a compile-time constant (the first +virtual register ID). + +.. _dss_densemap: + +llvm/ADT/DenseMap.h +^^^^^^^^^^^^^^^^^^^ + +DenseMap is a simple quadratically probed hash table. It excels at supporting +small keys and values: it uses a single allocation to hold all of the pairs +that are currently inserted in the map. DenseMap is a great way to map +pointers to pointers, or map other small types to each other. + +There are several aspects of DenseMap that you should be aware of, however. +The iterators in a DenseMap are invalidated whenever an insertion occurs, +unlike map. Also, because DenseMap allocates space for a large number of +key/value pairs (it starts with 64 by default), it will waste a lot of space if +your keys or values are large. Finally, you must implement a partial +specialization of DenseMapInfo for the key that you want, if it isn't already +supported. This is required to tell DenseMap about two special marker values +(which can never be inserted into the map) that it needs internally. + +DenseMap's find_as() method supports lookup operations using an alternate key +type. This is useful in cases where the normal key type is expensive to +construct, but cheap to compare against. The DenseMapInfo is responsible for +defining the appropriate comparison and hashing methods for each alternate key +type used. + +.. _dss_valuemap: + +llvm/ADT/ValueMap.h +^^^^^^^^^^^^^^^^^^^ + +ValueMap is a wrapper around a :ref:`DenseMap ` mapping +``Value*``\ s (or subclasses) to another type. When a Value is deleted or +RAUW'ed, ValueMap will update itself so the new version of the key is mapped to +the same value, just as if the key were a WeakVH. You can configure exactly how +this happens, and what else happens on these two events, by passing a ``Config`` +parameter to the ValueMap template. + +.. _dss_intervalmap: + +llvm/ADT/IntervalMap.h +^^^^^^^^^^^^^^^^^^^^^^ + +IntervalMap is a compact map for small keys and values. It maps key intervals +instead of single keys, and it will automatically coalesce adjacent intervals. +When then map only contains a few intervals, they are stored in the map object +itself to avoid allocations. + +The IntervalMap iterators are quite big, so they should not be passed around as +STL iterators. The heavyweight iterators allow a smaller data structure. + +.. _dss_map: + + +^^^^^ + +std::map has similar characteristics to :ref:`std::set `: it uses a +single allocation per pair inserted into the map, it offers log(n) lookup with +an extremely large constant factor, imposes a space penalty of 3 pointers per +pair in the map, etc. + +std::map is most useful when your keys or values are very large, if you need to +iterate over the collection in sorted order, or if you need stable iterators +into the map (i.e. they don't get invalidated if an insertion or deletion of +another element takes place). + +.. _dss_mapvector: + +llvm/ADT/MapVector.h +^^^^^^^^^^^^^^^^^^^^ + +``MapVector`` provides a subset of the DenseMap interface. The +main difference is that the iteration order is guaranteed to be the insertion +order, making it an easy (but somewhat expensive) solution for non-deterministic +iteration over maps of pointers. + +It is implemented by mapping from key to an index in a vector of key,value +pairs. This provides fast lookup and iteration, but has two main drawbacks: The +key is stored twice and it doesn't support removing elements. + +.. _dss_inteqclasses: + +llvm/ADT/IntEqClasses.h +^^^^^^^^^^^^^^^^^^^^^^^ + +IntEqClasses provides a compact representation of equivalence classes of small +integers. Initially, each integer in the range 0..n-1 has its own equivalence +class. Classes can be joined by passing two class representatives to the +join(a, b) method. Two integers are in the same class when findLeader() returns +the same representative. + +Once all equivalence classes are formed, the map can be compressed so each +integer 0..n-1 maps to an equivalence class number in the range 0..m-1, where m +is the total number of equivalence classes. The map must be uncompressed before +it can be edited again. + +.. _dss_immutablemap: + +llvm/ADT/ImmutableMap.h +^^^^^^^^^^^^^^^^^^^^^^^ + +ImmutableMap is an immutable (functional) map implementation based on an AVL +tree. Adding or removing elements is done through a Factory object and results +in the creation of a new ImmutableMap object. If an ImmutableMap already exists +with the given key set, then the existing one is returned; equality is compared +with a FoldingSetNodeID. The time and space complexity of add or remove +operations is logarithmic in the size of the original map. + +.. _dss_othermap: + +Other Map-Like Container Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The STL provides several other options, such as std::multimap and the various +"hash_map" like containers (whether from C++ TR1 or from the SGI library). We +never use hash_set and unordered_set because they are generally very expensive +(each insertion requires a malloc) and very non-portable. + +std::multimap is useful if you want to map a key to multiple values, but has all +the drawbacks of std::map. A sorted vector or some other approach is almost +always better. + +.. _ds_bit: + +Bit storage containers (BitVector, SparseBitVector) +--------------------------------------------------- + +Unlike the other containers, there are only two bit storage containers, and +choosing when to use each is relatively straightforward. + +One additional option is ``std::vector``: we discourage its use for two +reasons 1) the implementation in many common compilers (e.g. commonly +available versions of GCC) is extremely inefficient and 2) the C++ standards +committee is likely to deprecate this container and/or change it significantly +somehow. In any case, please don't use it. + +.. _dss_bitvector: + +BitVector +^^^^^^^^^ + +The BitVector container provides a dynamic size set of bits for manipulation. +It supports individual bit setting/testing, as well as set operations. The set +operations take time O(size of bitvector), but operations are performed one word +at a time, instead of one bit at a time. This makes the BitVector very fast for +set operations compared to other containers. Use the BitVector when you expect +the number of set bits to be high (i.e. a dense set). + +.. _dss_smallbitvector: + +SmallBitVector +^^^^^^^^^^^^^^ + +The SmallBitVector container provides the same interface as BitVector, but it is +optimized for the case where only a small number of bits, less than 25 or so, +are needed. It also transparently supports larger bit counts, but slightly less +efficiently than a plain BitVector, so SmallBitVector should only be used when +larger counts are rare. + +At this time, SmallBitVector does not support set operations (and, or, xor), and +its operator[] does not provide an assignable lvalue. + +.. _dss_sparsebitvector: + +SparseBitVector +^^^^^^^^^^^^^^^ + +The SparseBitVector container is much like BitVector, with one major difference: +Only the bits that are set, are stored. This makes the SparseBitVector much +more space efficient than BitVector when the set is sparse, as well as making +set operations O(number of set bits) instead of O(size of universe). The +downside to the SparseBitVector is that setting and testing of random bits is +O(N), and on large SparseBitVectors, this can be slower than BitVector. In our +implementation, setting or testing bits in sorted order (either forwards or +reverse) is O(1) worst case. Testing and setting bits within 128 bits (depends +on size) of the current bit is also O(1). As a general statement, +testing/setting bits in a SparseBitVector is O(distance away from last set bit). + +.. _common: + +Helpful Hints for Common Operations +=================================== + +This section describes how to perform some very simple transformations of LLVM +code. This is meant to give examples of common idioms used, showing the +practical side of LLVM transformations. + +Because this is a "how-to" section, you should also read about the main classes +that you will be working with. The :ref:`Core LLVM Class Hierarchy Reference +` contains details and descriptions of the main classes that you +should know about. + +.. _inspection: + +Basic Inspection and Traversal Routines +--------------------------------------- + +The LLVM compiler infrastructure have many different data structures that may be +traversed. Following the example of the C++ standard template library, the +techniques used to traverse these various data structures are all basically the +same. For a enumerable sequence of values, the ``XXXbegin()`` function (or +method) returns an iterator to the start of the sequence, the ``XXXend()`` +function returns an iterator pointing to one past the last valid element of the +sequence, and there is some ``XXXiterator`` data type that is common between the +two operations. + +Because the pattern for iteration is common across many different aspects of the +program representation, the standard template library algorithms may be used on +them, and it is easier to remember how to iterate. First we show a few common +examples of the data structures that need to be traversed. Other data +structures are traversed in very similar ways. + +.. _iterate_function: + +Iterating over the ``BasicBlock`` in a ``Function`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It's quite common to have a ``Function`` instance that you'd like to transform +in some way; in particular, you'd like to manipulate its ``BasicBlock``\ s. To +facilitate this, you'll need to iterate over all of the ``BasicBlock``\ s that +constitute the ``Function``. The following is an example that prints the name +of a ``BasicBlock`` and the number of ``Instruction``\ s it contains: + +.. code-block:: c++ + + // func is a pointer to a Function instance + for (Function::iterator i = func->begin(), e = func->end(); i != e; ++i) + // Print out the name of the basic block if it has one, and then the + // number of instructions that it contains + errs() << "Basic block (name=" << i->getName() << ") has " + << i->size() << " instructions.\n"; + +Note that i can be used as if it were a pointer for the purposes of invoking +member functions of the ``Instruction`` class. This is because the indirection +operator is overloaded for the iterator classes. In the above code, the +expression ``i->size()`` is exactly equivalent to ``(*i).size()`` just like +you'd expect. + +.. _iterate_basicblock: + +Iterating over the ``Instruction`` in a ``BasicBlock`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Just like when dealing with ``BasicBlock``\ s in ``Function``\ s, it's easy to +iterate over the individual instructions that make up ``BasicBlock``\ s. Here's +a code snippet that prints out each instruction in a ``BasicBlock``: + +.. code-block:: c++ + + // blk is a pointer to a BasicBlock instance + for (BasicBlock::iterator i = blk->begin(), e = blk->end(); i != e; ++i) + // The next statement works since operator<<(ostream&,...) + // is overloaded for Instruction& + errs() << *i << "\n"; + + +However, this isn't really the best way to print out the contents of a +``BasicBlock``! Since the ostream operators are overloaded for virtually +anything you'll care about, you could have just invoked the print routine on the +basic block itself: ``errs() << *blk << "\n";``. + +.. _iterate_insiter: + +Iterating over the ``Instruction`` in a ``Function`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you're finding that you commonly iterate over a ``Function``'s +``BasicBlock``\ s and then that ``BasicBlock``'s ``Instruction``\ s, +``InstIterator`` should be used instead. You'll need to include +``llvm/Support/InstIterator.h`` (`doxygen +`__) and then instantiate +``InstIterator``\ s explicitly in your code. Here's a small example that shows +how to dump all instructions in a function to the standard error stream: + +.. code-block:: c++ + + #include "llvm/Support/InstIterator.h" + + // F is a pointer to a Function instance + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + errs() << *I << "\n"; + +Easy, isn't it? You can also use ``InstIterator``\ s to fill a work list with +its initial contents. For example, if you wanted to initialize a work list to +contain all instructions in a ``Function`` F, all you would need to do is +something like: + +.. code-block:: c++ + + std::set worklist; + // or better yet, SmallPtrSet worklist; + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + worklist.insert(&*I); + +The STL set ``worklist`` would now contain all instructions in the ``Function`` +pointed to by F. + +.. _iterate_convert: + +Turning an iterator into a class pointer (and vice-versa) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes, it'll be useful to grab a reference (or pointer) to a class instance +when all you've got at hand is an iterator. Well, extracting a reference or a +pointer from an iterator is very straight-forward. Assuming that ``i`` is a +``BasicBlock::iterator`` and ``j`` is a ``BasicBlock::const_iterator``: + +.. code-block:: c++ + + Instruction& inst = *i; // Grab reference to instruction reference + Instruction* pinst = &*i; // Grab pointer to instruction reference + const Instruction& inst = *j; + +However, the iterators you'll be working with in the LLVM framework are special: +they will automatically convert to a ptr-to-instance type whenever they need to. +Instead of derferencing the iterator and then taking the address of the result, +you can simply assign the iterator to the proper pointer type and you get the +dereference and address-of operation as a result of the assignment (behind the +scenes, this is a result of overloading casting mechanisms). Thus the last line +of the last example, + +.. code-block:: c++ + + Instruction *pinst = &*i; + +is semantically equivalent to + +.. code-block:: c++ + + Instruction *pinst = i; + +It's also possible to turn a class pointer into the corresponding iterator, and +this is a constant time operation (very efficient). The following code snippet +illustrates use of the conversion constructors provided by LLVM iterators. By +using these, you can explicitly grab the iterator of something without actually +obtaining it via iteration over some structure: + +.. code-block:: c++ + + void printNextInstruction(Instruction* inst) { + BasicBlock::iterator it(inst); + ++it; // After this line, it refers to the instruction after *inst + if (it != inst->getParent()->end()) errs() << *it << "\n"; + } + +Unfortunately, these implicit conversions come at a cost; they prevent these +iterators from conforming to standard iterator conventions, and thus from being +usable with standard algorithms and containers. For example, they prevent the +following code, where ``B`` is a ``BasicBlock``, from compiling: + +.. code-block:: c++ + + llvm::SmallVector(B->begin(), B->end()); + +Because of this, these implicit conversions may be removed some day, and +``operator*`` changed to return a pointer instead of a reference. + +.. _iterate_complex: + +Finding call sites: a slightly more complex example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Say that you're writing a FunctionPass and would like to count all the locations +in the entire module (that is, across every ``Function``) where a certain +function (i.e., some ``Function *``) is already in scope. As you'll learn +later, you may want to use an ``InstVisitor`` to accomplish this in a much more +straight-forward manner, but this example will allow us to explore how you'd do +it if you didn't have ``InstVisitor`` around. In pseudo-code, this is what we +want to do: + +.. code-block:: none + + initialize callCounter to zero + for each Function f in the Module + for each BasicBlock b in f + for each Instruction i in b + if (i is a CallInst and calls the given function) + increment callCounter + +And the actual code is (remember, because we're writing a ``FunctionPass``, our +``FunctionPass``-derived class simply has to override the ``runOnFunction`` +method): + +.. code-block:: c++ + + Function* targetFunc = ...; + + class OurFunctionPass : public FunctionPass { + public: + OurFunctionPass(): callCounter(0) { } + + virtual runOnFunction(Function& F) { + for (Function::iterator b = F.begin(), be = F.end(); b != be; ++b) { + for (BasicBlock::iterator i = b->begin(), ie = b->end(); i != ie; ++i) { + if (CallInst* callInst = dyn_cast(&*i)) { + // We know we've encountered a call instruction, so we + // need to determine if it's a call to the + // function pointed to by m_func or not. + if (callInst->getCalledFunction() == targetFunc) + ++callCounter; + } + } + } + } + + private: + unsigned callCounter; + }; + +.. _calls_and_invokes: + +Treating calls and invokes the same way +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You may have noticed that the previous example was a bit oversimplified in that +it did not deal with call sites generated by 'invoke' instructions. In this, +and in other situations, you may find that you want to treat ``CallInst``\ s and +``InvokeInst``\ s the same way, even though their most-specific common base +class is ``Instruction``, which includes lots of less closely-related things. +For these cases, LLVM provides a handy wrapper class called ``CallSite`` +(`doxygen `__) It is +essentially a wrapper around an ``Instruction`` pointer, with some methods that +provide functionality common to ``CallInst``\ s and ``InvokeInst``\ s. + +This class has "value semantics": it should be passed by value, not by reference +and it should not be dynamically allocated or deallocated using ``operator new`` +or ``operator delete``. It is efficiently copyable, assignable and +constructable, with costs equivalents to that of a bare pointer. If you look at +its definition, it has only a single pointer member. + +.. _iterate_chains: + +Iterating over def-use & use-def chains +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Frequently, we might have an instance of the ``Value`` class (`doxygen +`__) and we want to determine +which ``User`` s use the ``Value``. The list of all ``User``\ s of a particular +``Value`` is called a *def-use* chain. For example, let's say we have a +``Function*`` named ``F`` to a particular function ``foo``. Finding all of the +instructions that *use* ``foo`` is as simple as iterating over the *def-use* +chain of ``F``: + +.. code-block:: c++ + + Function *F = ...; + + for (Value::use_iterator i = F->use_begin(), e = F->use_end(); i != e; ++i) + if (Instruction *Inst = dyn_cast(*i)) { + errs() << "F is used in instruction:\n"; + errs() << *Inst << "\n"; + } + +Note that dereferencing a ``Value::use_iterator`` is not a very cheap operation. +Instead of performing ``*i`` above several times, consider doing it only once in +the loop body and reusing its result. + +Alternatively, it's common to have an instance of the ``User`` Class (`doxygen +`__) and need to know what +``Value``\ s are used by it. The list of all ``Value``\ s used by a ``User`` is +known as a *use-def* chain. Instances of class ``Instruction`` are common +``User`` s, so we might want to iterate over all of the values that a particular +instruction uses (that is, the operands of the particular ``Instruction``): + +.. code-block:: c++ + + Instruction *pi = ...; + + for (User::op_iterator i = pi->op_begin(), e = pi->op_end(); i != e; ++i) { + Value *v = *i; + // ... + } + +Declaring objects as ``const`` is an important tool of enforcing mutation free +algorithms (such as analyses, etc.). For this purpose above iterators come in +constant flavors as ``Value::const_use_iterator`` and +``Value::const_op_iterator``. They automatically arise when calling +``use/op_begin()`` on ``const Value*``\ s or ``const User*``\ s respectively. +Upon dereferencing, they return ``const Use*``\ s. Otherwise the above patterns +remain unchanged. + +.. _iterate_preds: + +Iterating over predecessors & successors of blocks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Iterating over the predecessors and successors of a block is quite easy with the +routines defined in ``"llvm/Support/CFG.h"``. Just use code like this to +iterate over all predecessors of BB: + +.. code-block:: c++ + + #include "llvm/Support/CFG.h" + BasicBlock *BB = ...; + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + BasicBlock *Pred = *PI; + // ... + } + +Similarly, to iterate over successors use ``succ_iterator/succ_begin/succ_end``. + +.. _simplechanges: + +Making simple changes +--------------------- + +There are some primitive transformation operations present in the LLVM +infrastructure that are worth knowing about. When performing transformations, +it's fairly common to manipulate the contents of basic blocks. This section +describes some of the common methods for doing so and gives example code. + +.. _schanges_creating: + +Creating and inserting new ``Instruction``\ s +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Instantiating Instructions* + +Creation of ``Instruction``\ s is straight-forward: simply call the constructor +for the kind of instruction to instantiate and provide the necessary parameters. +For example, an ``AllocaInst`` only *requires* a (const-ptr-to) ``Type``. Thus: + +.. code-block:: c++ + + AllocaInst* ai = new AllocaInst(Type::Int32Ty); + +will create an ``AllocaInst`` instance that represents the allocation of one +integer in the current stack frame, at run time. Each ``Instruction`` subclass +is likely to have varying default parameters which change the semantics of the +instruction, so refer to the `doxygen documentation for the subclass of +Instruction `_ that +you're interested in instantiating. + +*Naming values* + +It is very useful to name the values of instructions when you're able to, as +this facilitates the debugging of your transformations. If you end up looking +at generated LLVM machine code, you definitely want to have logical names +associated with the results of instructions! By supplying a value for the +``Name`` (default) parameter of the ``Instruction`` constructor, you associate a +logical name with the result of the instruction's execution at run time. For +example, say that I'm writing a transformation that dynamically allocates space +for an integer on the stack, and that integer is going to be used as some kind +of index by some other code. To accomplish this, I place an ``AllocaInst`` at +the first point in the first ``BasicBlock`` of some ``Function``, and I'm +intending to use it within the same ``Function``. I might do: + +.. code-block:: c++ + + AllocaInst* pa = new AllocaInst(Type::Int32Ty, 0, "indexLoc"); + +where ``indexLoc`` is now the logical name of the instruction's execution value, +which is a pointer to an integer on the run time stack. + +*Inserting instructions* + +There are essentially two ways to insert an ``Instruction`` into an existing +sequence of instructions that form a ``BasicBlock``: + +* Insertion into an explicit instruction list + + Given a ``BasicBlock* pb``, an ``Instruction* pi`` within that ``BasicBlock``, + and a newly-created instruction we wish to insert before ``*pi``, we do the + following: + + .. code-block:: c++ + + BasicBlock *pb = ...; + Instruction *pi = ...; + Instruction *newInst = new Instruction(...); + + pb->getInstList().insert(pi, newInst); // Inserts newInst before pi in pb + + Appending to the end of a ``BasicBlock`` is so common that the ``Instruction`` + class and ``Instruction``-derived classes provide constructors which take a + pointer to a ``BasicBlock`` to be appended to. For example code that looked + like: + + .. code-block:: c++ + + BasicBlock *pb = ...; + Instruction *newInst = new Instruction(...); + + pb->getInstList().push_back(newInst); // Appends newInst to pb + + becomes: + + .. code-block:: c++ + + BasicBlock *pb = ...; + Instruction *newInst = new Instruction(..., pb); + + which is much cleaner, especially if you are creating long instruction + streams. + +* Insertion into an implicit instruction list + + ``Instruction`` instances that are already in ``BasicBlock``\ s are implicitly + associated with an existing instruction list: the instruction list of the + enclosing basic block. Thus, we could have accomplished the same thing as the + above code without being given a ``BasicBlock`` by doing: + + .. code-block:: c++ + + Instruction *pi = ...; + Instruction *newInst = new Instruction(...); + + pi->getParent()->getInstList().insert(pi, newInst); + + In fact, this sequence of steps occurs so frequently that the ``Instruction`` + class and ``Instruction``-derived classes provide constructors which take (as + a default parameter) a pointer to an ``Instruction`` which the newly-created + ``Instruction`` should precede. That is, ``Instruction`` constructors are + capable of inserting the newly-created instance into the ``BasicBlock`` of a + provided instruction, immediately before that instruction. Using an + ``Instruction`` constructor with a ``insertBefore`` (default) parameter, the + above code becomes: + + .. code-block:: c++ + + Instruction* pi = ...; + Instruction* newInst = new Instruction(..., pi); + + which is much cleaner, especially if you're creating a lot of instructions and + adding them to ``BasicBlock``\ s. + +.. _schanges_deleting: + +Deleting Instructions +^^^^^^^^^^^^^^^^^^^^^ + +Deleting an instruction from an existing sequence of instructions that form a +BasicBlock_ is very straight-forward: just call the instruction's +``eraseFromParent()`` method. For example: + +.. code-block:: c++ + + Instruction *I = .. ; + I->eraseFromParent(); + +This unlinks the instruction from its containing basic block and deletes it. If +you'd just like to unlink the instruction from its containing basic block but +not delete it, you can use the ``removeFromParent()`` method. + +.. _schanges_replacing: + +Replacing an Instruction with another Value +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Replacing individual instructions +""""""""""""""""""""""""""""""""" + +Including "`llvm/Transforms/Utils/BasicBlockUtils.h +`_" permits use of two +very useful replace functions: ``ReplaceInstWithValue`` and +``ReplaceInstWithInst``. + +.. _schanges_deleting_sub: + +Deleting Instructions +""""""""""""""""""""" + +* ``ReplaceInstWithValue`` + + This function replaces all uses of a given instruction with a value, and then + removes the original instruction. The following example illustrates the + replacement of the result of a particular ``AllocaInst`` that allocates memory + for a single integer with a null pointer to an integer. + + .. code-block:: c++ + + AllocaInst* instToReplace = ...; + BasicBlock::iterator ii(instToReplace); + + ReplaceInstWithValue(instToReplace->getParent()->getInstList(), ii, + Constant::getNullValue(PointerType::getUnqual(Type::Int32Ty))); + +* ``ReplaceInstWithInst`` + + This function replaces a particular instruction with another instruction, + inserting the new instruction into the basic block at the location where the + old instruction was, and replacing any uses of the old instruction with the + new instruction. The following example illustrates the replacement of one + ``AllocaInst`` with another. + + .. code-block:: c++ + + AllocaInst* instToReplace = ...; + BasicBlock::iterator ii(instToReplace); + + ReplaceInstWithInst(instToReplace->getParent()->getInstList(), ii, + new AllocaInst(Type::Int32Ty, 0, "ptrToReplacedInt")); + + +Replacing multiple uses of Users and Values +""""""""""""""""""""""""""""""""""""""""""" + +You can use ``Value::replaceAllUsesWith`` and ``User::replaceUsesOfWith`` to +change more than one use at a time. See the doxygen documentation for the +`Value Class `_ and `User Class +`_, respectively, for more +information. + +.. _schanges_deletingGV: + +Deleting GlobalVariables +^^^^^^^^^^^^^^^^^^^^^^^^ + +Deleting a global variable from a module is just as easy as deleting an +Instruction. First, you must have a pointer to the global variable that you +wish to delete. You use this pointer to erase it from its parent, the module. +For example: + +.. code-block:: c++ + + GlobalVariable *GV = .. ; + + GV->eraseFromParent(); + + +.. _create_types: + +How to Create Types +------------------- + +In generating IR, you may need some complex types. If you know these types +statically, you can use ``TypeBuilder<...>::get()``, defined in +``llvm/Support/TypeBuilder.h``, to retrieve them. ``TypeBuilder`` has two forms +depending on whether you're building types for cross-compilation or native +library use. ``TypeBuilder`` requires that ``T`` be independent of the +host environment, meaning that it's built out of types from the ``llvm::types`` +(`doxygen `__) namespace +and pointers, functions, arrays, etc. built of those. ``TypeBuilder`` +additionally allows native C types whose size may depend on the host compiler. +For example, + +.. code-block:: c++ + + FunctionType *ft = TypeBuilder(types::i<32>*), true>::get(); + +is easier to read and write than the equivalent + +.. code-block:: c++ + + std::vector params; + params.push_back(PointerType::getUnqual(Type::Int32Ty)); + FunctionType *ft = FunctionType::get(Type::Int8Ty, params, false); + +See the `class comment +`_ for more details. + +.. _threading: + +Threads and LLVM +================ + +This section describes the interaction of the LLVM APIs with multithreading, +both on the part of client applications, and in the JIT, in the hosted +application. + +Note that LLVM's support for multithreading is still relatively young. Up +through version 2.5, the execution of threaded hosted applications was +supported, but not threaded client access to the APIs. While this use case is +now supported, clients *must* adhere to the guidelines specified below to ensure +proper operation in multithreaded mode. + +Note that, on Unix-like platforms, LLVM requires the presence of GCC's atomic +intrinsics in order to support threaded operation. If you need a +multhreading-capable LLVM on a platform without a suitably modern system +compiler, consider compiling LLVM and LLVM-GCC in single-threaded mode, and +using the resultant compiler to build a copy of LLVM with multithreading +support. + +.. _startmultithreaded: + +Entering and Exiting Multithreaded Mode +--------------------------------------- + +In order to properly protect its internal data structures while avoiding +excessive locking overhead in the single-threaded case, the LLVM must intialize +certain data structures necessary to provide guards around its internals. To do +so, the client program must invoke ``llvm_start_multithreaded()`` before making +any concurrent LLVM API calls. To subsequently tear down these structures, use +the ``llvm_stop_multithreaded()`` call. You can also use the +``llvm_is_multithreaded()`` call to check the status of multithreaded mode. + +Note that both of these calls must be made *in isolation*. That is to say that +no other LLVM API calls may be executing at any time during the execution of +``llvm_start_multithreaded()`` or ``llvm_stop_multithreaded``. It is the +client's responsibility to enforce this isolation. + +The return value of ``llvm_start_multithreaded()`` indicates the success or +failure of the initialization. Failure typically indicates that your copy of +LLVM was built without multithreading support, typically because GCC atomic +intrinsics were not found in your system compiler. In this case, the LLVM API +will not be safe for concurrent calls. However, it *will* be safe for hosting +threaded applications in the JIT, though :ref:`care must be taken +` to ensure that side exits and the like do not accidentally +result in concurrent LLVM API calls. + +.. _shutdown: + +Ending Execution with ``llvm_shutdown()`` +----------------------------------------- + +When you are done using the LLVM APIs, you should call ``llvm_shutdown()`` to +deallocate memory used for internal structures. This will also invoke +``llvm_stop_multithreaded()`` if LLVM is operating in multithreaded mode. As +such, ``llvm_shutdown()`` requires the same isolation guarantees as +``llvm_stop_multithreaded()``. + +Note that, if you use scope-based shutdown, you can use the +``llvm_shutdown_obj`` class, which calls ``llvm_shutdown()`` in its destructor. + +.. _managedstatic: + +Lazy Initialization with ``ManagedStatic`` +------------------------------------------ + +``ManagedStatic`` is a utility class in LLVM used to implement static +initialization of static resources, such as the global type tables. Before the +invocation of ``llvm_shutdown()``, it implements a simple lazy initialization +scheme. Once ``llvm_start_multithreaded()`` returns, however, it uses +double-checked locking to implement thread-safe lazy initialization. + +Note that, because no other threads are allowed to issue LLVM API calls before +``llvm_start_multithreaded()`` returns, it is possible to have +``ManagedStatic``\ s of ``llvm::sys::Mutex``\ s. + +The ``llvm_acquire_global_lock()`` and ``llvm_release_global_lock`` APIs provide +access to the global lock used to implement the double-checked locking for lazy +initialization. These should only be used internally to LLVM, and only if you +know what you're doing! + +.. _llvmcontext: + +Achieving Isolation with ``LLVMContext`` +---------------------------------------- + +``LLVMContext`` is an opaque class in the LLVM API which clients can use to +operate multiple, isolated instances of LLVM concurrently within the same +address space. For instance, in a hypothetical compile-server, the compilation +of an individual translation unit is conceptually independent from all the +others, and it would be desirable to be able to compile incoming translation +units concurrently on independent server threads. Fortunately, ``LLVMContext`` +exists to enable just this kind of scenario! + +Conceptually, ``LLVMContext`` provides isolation. Every LLVM entity +(``Module``\ s, ``Value``\ s, ``Type``\ s, ``Constant``\ s, etc.) in LLVM's +in-memory IR belongs to an ``LLVMContext``. Entities in different contexts +*cannot* interact with each other: ``Module``\ s in different contexts cannot be +linked together, ``Function``\ s cannot be added to ``Module``\ s in different +contexts, etc. What this means is that is is safe to compile on multiple +threads simultaneously, as long as no two threads operate on entities within the +same context. + +In practice, very few places in the API require the explicit specification of a +``LLVMContext``, other than the ``Type`` creation/lookup APIs. Because every +``Type`` carries a reference to its owning context, most other entities can +determine what context they belong to by looking at their own ``Type``. If you +are adding new entities to LLVM IR, please try to maintain this interface +design. + +For clients that do *not* require the benefits of isolation, LLVM provides a +convenience API ``getGlobalContext()``. This returns a global, lazily +initialized ``LLVMContext`` that may be used in situations where isolation is +not a concern. + +.. _jitthreading: + +Threads and the JIT +------------------- + +LLVM's "eager" JIT compiler is safe to use in threaded programs. Multiple +threads can call ``ExecutionEngine::getPointerToFunction()`` or +``ExecutionEngine::runFunction()`` concurrently, and multiple threads can run +code output by the JIT concurrently. The user must still ensure that only one +thread accesses IR in a given ``LLVMContext`` while another thread might be +modifying it. One way to do that is to always hold the JIT lock while accessing +IR outside the JIT (the JIT *modifies* the IR by adding ``CallbackVH``\ s). +Another way is to only call ``getPointerToFunction()`` from the +``LLVMContext``'s thread. + +When the JIT is configured to compile lazily (using +``ExecutionEngine::DisableLazyCompilation(false)``), there is currently a `race +condition `_ in updating call sites +after a function is lazily-jitted. It's still possible to use the lazy JIT in a +threaded program if you ensure that only one thread at a time can call any +particular lazy stub and that the JIT lock guards any IR access, but we suggest +using only the eager JIT in threaded programs. + +.. _advanced: + +Advanced Topics +=============== + +This section describes some of the advanced or obscure API's that most clients +do not need to be aware of. These API's tend manage the inner workings of the +LLVM system, and only need to be accessed in unusual circumstances. + +.. _SymbolTable: + +The ``ValueSymbolTable`` class +------------------------------ + +The ``ValueSymbolTable`` (`doxygen +`__) class provides +a symbol table that the :ref:`Function ` and Module_ classes use for +naming value definitions. The symbol table can provide a name for any Value_. + +Note that the ``SymbolTable`` class should not be directly accessed by most +clients. It should only be used when iteration over the symbol table names +themselves are required, which is very special purpose. Note that not all LLVM +Value_\ s have names, and those without names (i.e. they have an empty name) do +not exist in the symbol table. + +Symbol tables support iteration over the values in the symbol table with +``begin/end/iterator`` and supports querying to see if a specific name is in the +symbol table (with ``lookup``). The ``ValueSymbolTable`` class exposes no +public mutator methods, instead, simply call ``setName`` on a value, which will +autoinsert it into the appropriate symbol table. + +.. _UserLayout: + +The ``User`` and owned ``Use`` classes' memory layout +----------------------------------------------------- + +The ``User`` (`doxygen `__) +class provides a basis for expressing the ownership of ``User`` towards other +`Value instance `_\ s. The +``Use`` (`doxygen `__) helper +class is employed to do the bookkeeping and to facilitate *O(1)* addition and +removal. + +.. _Use2User: + +Interaction and relationship between ``User`` and ``Use`` objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A subclass of ``User`` can choose between incorporating its ``Use`` objects or +refer to them out-of-line by means of a pointer. A mixed variant (some ``Use`` +s inline others hung off) is impractical and breaks the invariant that the +``Use`` objects belonging to the same ``User`` form a contiguous array. + +We have 2 different layouts in the ``User`` (sub)classes: + +* Layout a) + + The ``Use`` object(s) are inside (resp. at fixed offset) of the ``User`` + object and there are a fixed number of them. + +* Layout b) + + The ``Use`` object(s) are referenced by a pointer to an array from the + ``User`` object and there may be a variable number of them. + +As of v2.4 each layout still possesses a direct pointer to the start of the +array of ``Use``\ s. Though not mandatory for layout a), we stick to this +redundancy for the sake of simplicity. The ``User`` object also stores the +number of ``Use`` objects it has. (Theoretically this information can also be +calculated given the scheme presented below.) + +Special forms of allocation operators (``operator new``) enforce the following +memory layouts: + +* Layout a) is modelled by prepending the ``User`` object by the ``Use[]`` + array. + + .. code-block:: none + + ...---.---.---.---.-------... + | P | P | P | P | User + '''---'---'---'---'-------''' + +* Layout b) is modelled by pointing at the ``Use[]`` array. + + .. code-block:: none + + .-------... + | User + '-------''' + | + v + .---.---.---.---... + | P | P | P | P | + '---'---'---'---''' + +*(In the above figures* '``P``' *stands for the* ``Use**`` *that is stored in +each* ``Use`` *object in the member* ``Use::Prev`` *)* + +.. _Waymarking: + +The waymarking algorithm +^^^^^^^^^^^^^^^^^^^^^^^^ + +Since the ``Use`` objects are deprived of the direct (back)pointer to their +``User`` objects, there must be a fast and exact method to recover it. This is +accomplished by the following scheme: + +A bit-encoding in the 2 LSBits (least significant bits) of the ``Use::Prev`` +allows to find the start of the ``User`` object: + +* ``00`` --- binary digit 0 + +* ``01`` --- binary digit 1 + +* ``10`` --- stop and calculate (``s``) + +* ``11`` --- full stop (``S``) + +Given a ``Use*``, all we have to do is to walk till we get a stop and we either +have a ``User`` immediately behind or we have to walk to the next stop picking +up digits and calculating the offset: + +.. code-block:: none + + .---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---------------- + | 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*) + '---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---------------- + |+15 |+10 |+6 |+3 |+1 + | | | | | __> + | | | | __________> + | | | ______________________> + | | ______________________________________> + | __________________________________________________________> + +Only the significant number of bits need to be stored between the stops, so that +the *worst case is 20 memory accesses* when there are 1000 ``Use`` objects +associated with a ``User``. + +.. _ReferenceImpl: + +Reference implementation +^^^^^^^^^^^^^^^^^^^^^^^^ + +The following literate Haskell fragment demonstrates the concept: + +.. code-block:: haskell + + > import Test.QuickCheck + > + > digits :: Int -> [Char] -> [Char] + > digits 0 acc = '0' : acc + > digits 1 acc = '1' : acc + > digits n acc = digits (n `div` 2) $ digits (n `mod` 2) acc + > + > dist :: Int -> [Char] -> [Char] + > dist 0 [] = ['S'] + > dist 0 acc = acc + > dist 1 acc = let r = dist 0 acc in 's' : digits (length r) r + > dist n acc = dist (n - 1) $ dist 1 acc + > + > takeLast n ss = reverse $ take n $ reverse ss + > + > test = takeLast 40 $ dist 20 [] + > + +Printing gives: ``"1s100000s11010s10100s1111s1010s110s11s1S"`` + +The reverse algorithm computes the length of the string just by examining a +certain prefix: + +.. code-block:: haskell + + > pref :: [Char] -> Int + > pref "S" = 1 + > pref ('s':'1':rest) = decode 2 1 rest + > pref (_:rest) = 1 + pref rest + > + > decode walk acc ('0':rest) = decode (walk + 1) (acc * 2) rest + > decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest + > decode walk acc _ = walk + acc + > + +Now, as expected, printing gives ``40``. + +We can *quickCheck* this with following property: + +.. code-block:: haskell + + > testcase = dist 2000 [] + > testcaseLength = length testcase + > + > identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr + > where arr = takeLast n testcase + > + +As expected gives: + +:: + + *Main> quickCheck identityProp + OK, passed 100 tests. + +Let's be a bit more exhaustive: + +.. code-block:: haskell + + > + > deepCheck p = check (defaultConfig { configMaxTest = 500 }) p + > + +And here is the result of : + +:: + + *Main> deepCheck identityProp + OK, passed 500 tests. + +.. _Tagging: + +Tagging considerations +^^^^^^^^^^^^^^^^^^^^^^ + +To maintain the invariant that the 2 LSBits of each ``Use**`` in ``Use`` never +change after being set up, setters of ``Use::Prev`` must re-tag the new +``Use**`` on every modification. Accordingly getters must strip the tag bits. + +For layout b) instead of the ``User`` we find a pointer (``User*`` with LSBit +set). Following this pointer brings us to the ``User``. A portable trick +ensures that the first bytes of ``User`` (if interpreted as a pointer) never has +the LSBit set. (Portability is relying on the fact that all known compilers +place the ``vptr`` in the first word of the instances.) + +.. _coreclasses: + +The Core LLVM Class Hierarchy Reference +======================================= + +``#include "llvm/IR/Type.h"`` + +header source: `Type.h `_ + +doxygen info: `Type Clases `_ + +The Core LLVM classes are the primary means of representing the program being +inspected or transformed. The core LLVM classes are defined in header files in +the ``include/llvm/`` directory, and implemented in the ``lib/VMCore`` +directory. + +.. _Type: + +The Type class and Derived Types +-------------------------------- + +``Type`` is a superclass of all type classes. Every ``Value`` has a ``Type``. +``Type`` cannot be instantiated directly but only through its subclasses. +Certain primitive types (``VoidType``, ``LabelType``, ``FloatType`` and +``DoubleType``) have hidden subclasses. They are hidden because they offer no +useful functionality beyond what the ``Type`` class offers except to distinguish +themselves from other subclasses of ``Type``. + +All other types are subclasses of ``DerivedType``. Types can be named, but this +is not a requirement. There exists exactly one instance of a given shape at any +one time. This allows type equality to be performed with address equality of +the Type Instance. That is, given two ``Type*`` values, the types are identical +if the pointers are identical. + +.. _m_Type: + +Important Public Methods +^^^^^^^^^^^^^^^^^^^^^^^^ + +* ``bool isIntegerTy() const``: Returns true for any integer type. + +* ``bool isFloatingPointTy()``: Return true if this is one of the five + floating point types. + +* ``bool isSized()``: Return true if the type has known size. Things + that don't have a size are abstract types, labels and void. + +.. _derivedtypes: + +Important Derived Types +^^^^^^^^^^^^^^^^^^^^^^^ + +``IntegerType`` + Subclass of DerivedType that represents integer types of any bit width. Any + bit width between ``IntegerType::MIN_INT_BITS`` (1) and + ``IntegerType::MAX_INT_BITS`` (~8 million) can be represented. + + * ``static const IntegerType* get(unsigned NumBits)``: get an integer + type of a specific bit width. + + * ``unsigned getBitWidth() const``: Get the bit width of an integer type. + +``SequentialType`` + This is subclassed by ArrayType, PointerType and VectorType. + + * ``const Type * getElementType() const``: Returns the type of each + of the elements in the sequential type. + +``ArrayType`` + This is a subclass of SequentialType and defines the interface for array + types. + + * ``unsigned getNumElements() const``: Returns the number of elements + in the array. + +``PointerType`` + Subclass of SequentialType for pointer types. + +``VectorType`` + Subclass of SequentialType for vector types. A vector type is similar to an + ArrayType but is distinguished because it is a first class type whereas + ArrayType is not. Vector types are used for vector operations and are usually + small vectors of of an integer or floating point type. + +``StructType`` + Subclass of DerivedTypes for struct types. + +.. _FunctionType: + +``FunctionType`` + Subclass of DerivedTypes for function types. + + * ``bool isVarArg() const``: Returns true if it's a vararg function. + + * ``const Type * getReturnType() const``: Returns the return type of the + function. + + * ``const Type * getParamType (unsigned i)``: Returns the type of the ith + parameter. + + * ``const unsigned getNumParams() const``: Returns the number of formal + parameters. + +.. _Module: + +The ``Module`` class +-------------------- + +``#include "llvm/IR/Module.h"`` + +header source: `Module.h `_ + +doxygen info: `Module Class `_ + +The ``Module`` class represents the top level structure present in LLVM +programs. An LLVM module is effectively either a translation unit of the +original program or a combination of several translation units merged by the +linker. The ``Module`` class keeps track of a list of :ref:`Function +`\ s, a list of GlobalVariable_\ s, and a SymbolTable_. +Additionally, it contains a few helpful member functions that try to make common +operations easy. + +.. _m_Module: + +Important Public Members of the ``Module`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* ``Module::Module(std::string name = "")`` + + Constructing a Module_ is easy. You can optionally provide a name for it + (probably based on the name of the translation unit). + +* | ``Module::iterator`` - Typedef for function list iterator + | ``Module::const_iterator`` - Typedef for const_iterator. + | ``begin()``, ``end()``, ``size()``, ``empty()`` + + These are forwarding methods that make it easy to access the contents of a + ``Module`` object's :ref:`Function ` list. + +* ``Module::FunctionListType &getFunctionList()`` + + Returns the list of :ref:`Function `\ s. This is necessary to use + when you need to update the list or perform a complex action that doesn't have + a forwarding method. + +---------------- + +* | ``Module::global_iterator`` - Typedef for global variable list iterator + | ``Module::const_global_iterator`` - Typedef for const_iterator. + | ``global_begin()``, ``global_end()``, ``global_size()``, ``global_empty()`` + + These are forwarding methods that make it easy to access the contents of a + ``Module`` object's GlobalVariable_ list. + +* ``Module::GlobalListType &getGlobalList()`` + + Returns the list of GlobalVariable_\ s. This is necessary to use when you + need to update the list or perform a complex action that doesn't have a + forwarding method. + +---------------- + +* ``SymbolTable *getSymbolTable()`` + + Return a reference to the SymbolTable_ for this ``Module``. + +---------------- + +* ``Function *getFunction(StringRef Name) const`` + + Look up the specified function in the ``Module`` SymbolTable_. If it does not + exist, return ``null``. + +* ``Function *getOrInsertFunction(const std::string &Name, const FunctionType + *T)`` + + Look up the specified function in the ``Module`` SymbolTable_. If it does not + exist, add an external declaration for the function and return it. + +* ``std::string getTypeName(const Type *Ty)`` + + If there is at least one entry in the SymbolTable_ for the specified Type_, + return it. Otherwise return the empty string. + +* ``bool addTypeName(const std::string &Name, const Type *Ty)`` + + Insert an entry in the SymbolTable_ mapping ``Name`` to ``Ty``. If there is + already an entry for this name, true is returned and the SymbolTable_ is not + modified. + +.. _Value: + +The ``Value`` class +------------------- + +``#include "llvm/IR/Value.h"`` + +header source: `Value.h `_ + +doxygen info: `Value Class `_ + +The ``Value`` class is the most important class in the LLVM Source base. It +represents a typed value that may be used (among other things) as an operand to +an instruction. There are many different types of ``Value``\ s, such as +Constant_\ s, Argument_\ s. Even Instruction_\ s and :ref:`Function +`\ s are ``Value``\ s. + +A particular ``Value`` may be used many times in the LLVM representation for a +program. For example, an incoming argument to a function (represented with an +instance of the Argument_ class) is "used" by every instruction in the function +that references the argument. To keep track of this relationship, the ``Value`` +class keeps a list of all of the ``User``\ s that is using it (the User_ class +is a base class for all nodes in the LLVM graph that can refer to ``Value``\ s). +This use list is how LLVM represents def-use information in the program, and is +accessible through the ``use_*`` methods, shown below. + +Because LLVM is a typed representation, every LLVM ``Value`` is typed, and this +Type_ is available through the ``getType()`` method. In addition, all LLVM +values can be named. The "name" of the ``Value`` is a symbolic string printed +in the LLVM code: + +.. code-block:: llvm + + %foo = add i32 1, 2 + +.. _nameWarning: + +The name of this instruction is "foo". **NOTE** that the name of any value may +be missing (an empty string), so names should **ONLY** be used for debugging +(making the source code easier to read, debugging printouts), they should not be +used to keep track of values or map between them. For this purpose, use a +``std::map`` of pointers to the ``Value`` itself instead. + +One important aspect of LLVM is that there is no distinction between an SSA +variable and the operation that produces it. Because of this, any reference to +the value produced by an instruction (or the value available as an incoming +argument, for example) is represented as a direct pointer to the instance of the +class that represents this value. Although this may take some getting used to, +it simplifies the representation and makes it easier to manipulate. + +.. _m_Value: + +Important Public Members of the ``Value`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* | ``Value::use_iterator`` - Typedef for iterator over the use-list + | ``Value::const_use_iterator`` - Typedef for const_iterator over the + use-list + | ``unsigned use_size()`` - Returns the number of users of the value. + | ``bool use_empty()`` - Returns true if there are no users. + | ``use_iterator use_begin()`` - Get an iterator to the start of the + use-list. + | ``use_iterator use_end()`` - Get an iterator to the end of the use-list. + | ``User *use_back()`` - Returns the last element in the list. + + These methods are the interface to access the def-use information in LLVM. + As with all other iterators in LLVM, the naming conventions follow the + conventions defined by the STL_. + +* ``Type *getType() const`` + This method returns the Type of the Value. + +* | ``bool hasName() const`` + | ``std::string getName() const`` + | ``void setName(const std::string &Name)`` + + This family of methods is used to access and assign a name to a ``Value``, be + aware of the :ref:`precaution above `. + +* ``void replaceAllUsesWith(Value *V)`` + + This method traverses the use list of a ``Value`` changing all User_\ s of the + current value to refer to "``V``" instead. For example, if you detect that an + instruction always produces a constant value (for example through constant + folding), you can replace all uses of the instruction with the constant like + this: + + .. code-block:: c++ + + Inst->replaceAllUsesWith(ConstVal); + +.. _User: + +The ``User`` class +------------------ + +``#include "llvm/IR/User.h"`` + +header source: `User.h `_ + +doxygen info: `User Class `_ + +Superclass: Value_ + +The ``User`` class is the common base class of all LLVM nodes that may refer to +``Value``\ s. It exposes a list of "Operands" that are all of the ``Value``\ s +that the User is referring to. The ``User`` class itself is a subclass of +``Value``. + +The operands of a ``User`` point directly to the LLVM ``Value`` that it refers +to. Because LLVM uses Static Single Assignment (SSA) form, there can only be +one definition referred to, allowing this direct connection. This connection +provides the use-def information in LLVM. + +.. _m_User: + +Important Public Members of the ``User`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``User`` class exposes the operand list in two ways: through an index access +interface and through an iterator based interface. + +* | ``Value *getOperand(unsigned i)`` + | ``unsigned getNumOperands()`` + + These two methods expose the operands of the ``User`` in a convenient form for + direct access. + +* | ``User::op_iterator`` - Typedef for iterator over the operand list + | ``op_iterator op_begin()`` - Get an iterator to the start of the operand + list. + | ``op_iterator op_end()`` - Get an iterator to the end of the operand list. + + Together, these methods make up the iterator based interface to the operands + of a ``User``. + + +.. _Instruction: + +The ``Instruction`` class +------------------------- + +``#include "llvm/IR/Instruction.h"`` + +header source: `Instruction.h +`_ + +doxygen info: `Instruction Class +`_ + +Superclasses: User_, Value_ + +The ``Instruction`` class is the common base class for all LLVM instructions. +It provides only a few methods, but is a very commonly used class. The primary +data tracked by the ``Instruction`` class itself is the opcode (instruction +type) and the parent BasicBlock_ the ``Instruction`` is embedded into. To +represent a specific type of instruction, one of many subclasses of +``Instruction`` are used. + +Because the ``Instruction`` class subclasses the User_ class, its operands can +be accessed in the same way as for other ``User``\ s (with the +``getOperand()``/``getNumOperands()`` and ``op_begin()``/``op_end()`` methods). +An important file for the ``Instruction`` class is the ``llvm/Instruction.def`` +file. This file contains some meta-data about the various different types of +instructions in LLVM. It describes the enum values that are used as opcodes +(for example ``Instruction::Add`` and ``Instruction::ICmp``), as well as the +concrete sub-classes of ``Instruction`` that implement the instruction (for +example BinaryOperator_ and CmpInst_). Unfortunately, the use of macros in this +file confuses doxygen, so these enum values don't show up correctly in the +`doxygen output `_. + +.. _s_Instruction: + +Important Subclasses of the ``Instruction`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _BinaryOperator: + +* ``BinaryOperator`` + + This subclasses represents all two operand instructions whose operands must be + the same type, except for the comparison instructions. + +.. _CastInst: + +* ``CastInst`` + This subclass is the parent of the 12 casting instructions. It provides + common operations on cast instructions. + +.. _CmpInst: + +* ``CmpInst`` + + This subclass respresents the two comparison instructions, + `ICmpInst `_ (integer opreands), and + `FCmpInst `_ (floating point operands). + +.. _TerminatorInst: + +* ``TerminatorInst`` + + This subclass is the parent of all terminator instructions (those which can + terminate a block). + +.. _m_Instruction: + +Important Public Members of the ``Instruction`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* ``BasicBlock *getParent()`` + + Returns the BasicBlock_ that this + ``Instruction`` is embedded into. + +* ``bool mayWriteToMemory()`` + + Returns true if the instruction writes to memory, i.e. it is a ``call``, + ``free``, ``invoke``, or ``store``. + +* ``unsigned getOpcode()`` + + Returns the opcode for the ``Instruction``. + +* ``Instruction *clone() const`` + + Returns another instance of the specified instruction, identical in all ways + to the original except that the instruction has no parent (i.e. it's not + embedded into a BasicBlock_), and it has no name. + +.. _Constant: + +The ``Constant`` class and subclasses +------------------------------------- + +Constant represents a base class for different types of constants. It is +subclassed by ConstantInt, ConstantArray, etc. for representing the various +types of Constants. GlobalValue_ is also a subclass, which represents the +address of a global variable or function. + +.. _s_Constant: + +Important Subclasses of Constant +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* ConstantInt : This subclass of Constant represents an integer constant of + any width. + + * ``const APInt& getValue() const``: Returns the underlying + value of this constant, an APInt value. + + * ``int64_t getSExtValue() const``: Converts the underlying APInt value to an + int64_t via sign extension. If the value (not the bit width) of the APInt + is too large to fit in an int64_t, an assertion will result. For this + reason, use of this method is discouraged. + + * ``uint64_t getZExtValue() const``: Converts the underlying APInt value + to a uint64_t via zero extension. IF the value (not the bit width) of the + APInt is too large to fit in a uint64_t, an assertion will result. For this + reason, use of this method is discouraged. + + * ``static ConstantInt* get(const APInt& Val)``: Returns the ConstantInt + object that represents the value provided by ``Val``. The type is implied + as the IntegerType that corresponds to the bit width of ``Val``. + + * ``static ConstantInt* get(const Type *Ty, uint64_t Val)``: Returns the + ConstantInt object that represents the value provided by ``Val`` for integer + type ``Ty``. + +* ConstantFP : This class represents a floating point constant. + + * ``double getValue() const``: Returns the underlying value of this constant. + +* ConstantArray : This represents a constant array. + + * ``const std::vector &getValues() const``: Returns a vector of + component constants that makeup this array. + +* ConstantStruct : This represents a constant struct. + + * ``const std::vector &getValues() const``: Returns a vector of + component constants that makeup this array. + +* GlobalValue : This represents either a global variable or a function. In + either case, the value is a constant fixed address (after linking). + +.. _GlobalValue: + +The ``GlobalValue`` class +------------------------- + +``#include "llvm/IR/GlobalValue.h"`` + +header source: `GlobalValue.h +`_ + +doxygen info: `GlobalValue Class +`_ + +Superclasses: Constant_, User_, Value_ + +Global values ( GlobalVariable_\ s or :ref:`Function `\ s) are the +only LLVM values that are visible in the bodies of all :ref:`Function +`\ s. Because they are visible at global scope, they are also +subject to linking with other globals defined in different translation units. +To control the linking process, ``GlobalValue``\ s know their linkage rules. +Specifically, ``GlobalValue``\ s know whether they have internal or external +linkage, as defined by the ``LinkageTypes`` enumeration. + +If a ``GlobalValue`` has internal linkage (equivalent to being ``static`` in C), +it is not visible to code outside the current translation unit, and does not +participate in linking. If it has external linkage, it is visible to external +code, and does participate in linking. In addition to linkage information, +``GlobalValue``\ s keep track of which Module_ they are currently part of. + +Because ``GlobalValue``\ s are memory objects, they are always referred to by +their **address**. As such, the Type_ of a global is always a pointer to its +contents. It is important to remember this when using the ``GetElementPtrInst`` +instruction because this pointer must be dereferenced first. For example, if +you have a ``GlobalVariable`` (a subclass of ``GlobalValue)`` that is an array +of 24 ints, type ``[24 x i32]``, then the ``GlobalVariable`` is a pointer to +that array. Although the address of the first element of this array and the +value of the ``GlobalVariable`` are the same, they have different types. The +``GlobalVariable``'s type is ``[24 x i32]``. The first element's type is +``i32.`` Because of this, accessing a global value requires you to dereference +the pointer with ``GetElementPtrInst`` first, then its elements can be accessed. +This is explained in the `LLVM Language Reference Manual +`_. + +.. _m_GlobalValue: + +Important Public Members of the ``GlobalValue`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* | ``bool hasInternalLinkage() const`` + | ``bool hasExternalLinkage() const`` + | ``void setInternalLinkage(bool HasInternalLinkage)`` + + These methods manipulate the linkage characteristics of the ``GlobalValue``. + +* ``Module *getParent()`` + + This returns the Module_ that the + GlobalValue is currently embedded into. + +.. _c_Function: + +The ``Function`` class +---------------------- + +``#include "llvm/IR/Function.h"`` + +header source: `Function.h `_ + +doxygen info: `Function Class +`_ + +Superclasses: GlobalValue_, Constant_, User_, Value_ + +The ``Function`` class represents a single procedure in LLVM. It is actually +one of the more complex classes in the LLVM hierarchy because it must keep track +of a large amount of data. The ``Function`` class keeps track of a list of +BasicBlock_\ s, a list of formal Argument_\ s, and a SymbolTable_. + +The list of BasicBlock_\ s is the most commonly used part of ``Function`` +objects. The list imposes an implicit ordering of the blocks in the function, +which indicate how the code will be laid out by the backend. Additionally, the +first BasicBlock_ is the implicit entry node for the ``Function``. It is not +legal in LLVM to explicitly branch to this initial block. There are no implicit +exit nodes, and in fact there may be multiple exit nodes from a single +``Function``. If the BasicBlock_ list is empty, this indicates that the +``Function`` is actually a function declaration: the actual body of the function +hasn't been linked in yet. + +In addition to a list of BasicBlock_\ s, the ``Function`` class also keeps track +of the list of formal Argument_\ s that the function receives. This container +manages the lifetime of the Argument_ nodes, just like the BasicBlock_ list does +for the BasicBlock_\ s. + +The SymbolTable_ is a very rarely used LLVM feature that is only used when you +have to look up a value by name. Aside from that, the SymbolTable_ is used +internally to make sure that there are not conflicts between the names of +Instruction_\ s, BasicBlock_\ s, or Argument_\ s in the function body. + +Note that ``Function`` is a GlobalValue_ and therefore also a Constant_. The +value of the function is its address (after linking) which is guaranteed to be +constant. + +.. _m_Function: + +Important Public Members of the ``Function`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* ``Function(const FunctionType *Ty, LinkageTypes Linkage, + const std::string &N = "", Module* Parent = 0)`` + + Constructor used when you need to create new ``Function``\ s to add the + program. The constructor must specify the type of the function to create and + what type of linkage the function should have. The FunctionType_ argument + specifies the formal arguments and return value for the function. The same + FunctionType_ value can be used to create multiple functions. The ``Parent`` + argument specifies the Module in which the function is defined. If this + argument is provided, the function will automatically be inserted into that + module's list of functions. + +* ``bool isDeclaration()`` + + Return whether or not the ``Function`` has a body defined. If the function is + "external", it does not have a body, and thus must be resolved by linking with + a function defined in a different translation unit. + +* | ``Function::iterator`` - Typedef for basic block list iterator + | ``Function::const_iterator`` - Typedef for const_iterator. + | ``begin()``, ``end()``, ``size()``, ``empty()`` + + These are forwarding methods that make it easy to access the contents of a + ``Function`` object's BasicBlock_ list. + +* ``Function::BasicBlockListType &getBasicBlockList()`` + + Returns the list of BasicBlock_\ s. This is necessary to use when you need to + update the list or perform a complex action that doesn't have a forwarding + method. + +* | ``Function::arg_iterator`` - Typedef for the argument list iterator + | ``Function::const_arg_iterator`` - Typedef for const_iterator. + | ``arg_begin()``, ``arg_end()``, ``arg_size()``, ``arg_empty()`` + + These are forwarding methods that make it easy to access the contents of a + ``Function`` object's Argument_ list. + +* ``Function::ArgumentListType &getArgumentList()`` + + Returns the list of Argument_. This is necessary to use when you need to + update the list or perform a complex action that doesn't have a forwarding + method. + +* ``BasicBlock &getEntryBlock()`` + + Returns the entry ``BasicBlock`` for the function. Because the entry block + for the function is always the first block, this returns the first block of + the ``Function``. + +* | ``Type *getReturnType()`` + | ``FunctionType *getFunctionType()`` + + This traverses the Type_ of the ``Function`` and returns the return type of + the function, or the FunctionType_ of the actual function. + +* ``SymbolTable *getSymbolTable()`` + + Return a pointer to the SymbolTable_ for this ``Function``. + +.. _GlobalVariable: + +The ``GlobalVariable`` class +---------------------------- + +``#include "llvm/IR/GlobalVariable.h"`` + +header source: `GlobalVariable.h +`_ + +doxygen info: `GlobalVariable Class +`_ + +Superclasses: GlobalValue_, Constant_, User_, Value_ + +Global variables are represented with the (surprise surprise) ``GlobalVariable`` +class. Like functions, ``GlobalVariable``\ s are also subclasses of +GlobalValue_, and as such are always referenced by their address (global values +must live in memory, so their "name" refers to their constant address). See +GlobalValue_ for more on this. Global variables may have an initial value +(which must be a Constant_), and if they have an initializer, they may be marked +as "constant" themselves (indicating that their contents never change at +runtime). + +.. _m_GlobalVariable: + +Important Public Members of the ``GlobalVariable`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* ``GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes &Linkage, + Constant *Initializer = 0, const std::string &Name = "", Module* Parent = 0)`` + + Create a new global variable of the specified type. If ``isConstant`` is true + then the global variable will be marked as unchanging for the program. The + Linkage parameter specifies the type of linkage (internal, external, weak, + linkonce, appending) for the variable. If the linkage is InternalLinkage, + WeakAnyLinkage, WeakODRLinkage, LinkOnceAnyLinkage or LinkOnceODRLinkage, then + the resultant global variable will have internal linkage. AppendingLinkage + concatenates together all instances (in different translation units) of the + variable into a single variable but is only applicable to arrays. See the + `LLVM Language Reference `_ for further details + on linkage types. Optionally an initializer, a name, and the module to put + the variable into may be specified for the global variable as well. + +* ``bool isConstant() const`` + + Returns true if this is a global variable that is known not to be modified at + runtime. + +* ``bool hasInitializer()`` + + Returns true if this ``GlobalVariable`` has an intializer. + +* ``Constant *getInitializer()`` + + Returns the initial value for a ``GlobalVariable``. It is not legal to call + this method if there is no initializer. + +.. _BasicBlock: + +The ``BasicBlock`` class +------------------------ + +``#include "llvm/IR/BasicBlock.h"`` + +header source: `BasicBlock.h +`_ + +doxygen info: `BasicBlock Class +`_ + +Superclass: Value_ + +This class represents a single entry single exit section of the code, commonly +known as a basic block by the compiler community. The ``BasicBlock`` class +maintains a list of Instruction_\ s, which form the body of the block. Matching +the language definition, the last element of this list of instructions is always +a terminator instruction (a subclass of the TerminatorInst_ class). + +In addition to tracking the list of instructions that make up the block, the +``BasicBlock`` class also keeps track of the :ref:`Function ` that +it is embedded into. + +Note that ``BasicBlock``\ s themselves are Value_\ s, because they are +referenced by instructions like branches and can go in the switch tables. +``BasicBlock``\ s have type ``label``. + +.. _m_BasicBlock: + +Important Public Members of the ``BasicBlock`` class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* ``BasicBlock(const std::string &Name = "", Function *Parent = 0)`` + + The ``BasicBlock`` constructor is used to create new basic blocks for + insertion into a function. The constructor optionally takes a name for the + new block, and a :ref:`Function ` to insert it into. If the + ``Parent`` parameter is specified, the new ``BasicBlock`` is automatically + inserted at the end of the specified :ref:`Function `, if not + specified, the BasicBlock must be manually inserted into the :ref:`Function + `. + +* | ``BasicBlock::iterator`` - Typedef for instruction list iterator + | ``BasicBlock::const_iterator`` - Typedef for const_iterator. + | ``begin()``, ``end()``, ``front()``, ``back()``, + ``size()``, ``empty()`` + STL-style functions for accessing the instruction list. + + These methods and typedefs are forwarding functions that have the same + semantics as the standard library methods of the same names. These methods + expose the underlying instruction list of a basic block in a way that is easy + to manipulate. To get the full complement of container operations (including + operations to update the list), you must use the ``getInstList()`` method. + +* ``BasicBlock::InstListType &getInstList()`` + + This method is used to get access to the underlying container that actually + holds the Instructions. This method must be used when there isn't a + forwarding function in the ``BasicBlock`` class for the operation that you + would like to perform. Because there are no forwarding functions for + "updating" operations, you need to use this if you want to update the contents + of a ``BasicBlock``. + +* ``Function *getParent()`` + + Returns a pointer to :ref:`Function ` the block is embedded into, + or a null pointer if it is homeless. + +* ``TerminatorInst *getTerminator()`` + + Returns a pointer to the terminator instruction that appears at the end of the + ``BasicBlock``. If there is no terminator instruction, or if the last + instruction in the block is not a terminator, then a null pointer is returned. + +.. _Argument: + +The ``Argument`` class +---------------------- + +This subclass of Value defines the interface for incoming formal arguments to a +function. A Function maintains a list of its formal arguments. An argument has +a pointer to the parent Function. + + diff --git a/docs/Projects.rst b/docs/Projects.rst new file mode 100644 index 00000000..3246e3ff --- /dev/null +++ b/docs/Projects.rst @@ -0,0 +1,323 @@ +======================== +Creating an LLVM Project +======================== + +.. contents:: + :local: + +Overview +======== + +The LLVM build system is designed to facilitate the building of third party +projects that use LLVM header files, libraries, and tools. In order to use +these facilities, a ``Makefile`` from a project must do the following things: + +* Set ``make`` variables. There are several variables that a ``Makefile`` needs + to set to use the LLVM build system: + + * ``PROJECT_NAME`` - The name by which your project is known. + * ``LLVM_SRC_ROOT`` - The root of the LLVM source tree. + * ``LLVM_OBJ_ROOT`` - The root of the LLVM object tree. + * ``PROJ_SRC_ROOT`` - The root of the project's source tree. + * ``PROJ_OBJ_ROOT`` - The root of the project's object tree. + * ``PROJ_INSTALL_ROOT`` - The root installation directory. + * ``LEVEL`` - The relative path from the current directory to the + project's root ``($PROJ_OBJ_ROOT)``. + +* Include ``Makefile.config`` from ``$(LLVM_OBJ_ROOT)``. + +* Include ``Makefile.rules`` from ``$(LLVM_SRC_ROOT)``. + +There are two ways that you can set all of these variables: + +* You can write your own ``Makefiles`` which hard-code these values. + +* You can use the pre-made LLVM sample project. This sample project includes + ``Makefiles``, a configure script that can be used to configure the location + of LLVM, and the ability to support multiple object directories from a single + source directory. + +This document assumes that you will base your project on the LLVM sample project +found in ``llvm/projects/sample``. If you want to devise your own build system, +studying the sample project and LLVM ``Makefiles`` will probably provide enough +information on how to write your own ``Makefiles``. + +Create a Project from the Sample Project +======================================== + +Follow these simple steps to start your project: + +1. Copy the ``llvm/projects/sample`` directory to any place of your choosing. + You can place it anywhere you like. Rename the directory to match the name + of your project. + +2. If you downloaded LLVM using Subversion, remove all the directories named + ``.svn`` (and all the files therein) from your project's new source tree. + This will keep Subversion from thinking that your project is inside + ``llvm/trunk/projects/sample``. + +3. Add your source code and Makefiles to your source tree. + +4. If you want your project to be configured with the ``configure`` script then + you need to edit ``autoconf/configure.ac`` as follows: + + * **AC_INIT** - Place the name of your project, its version number and a + contact email address for your project as the arguments to this macro + + * **AC_CONFIG_AUX_DIR** - If your project isn't in the ``llvm/projects`` + directory then you might need to adjust this so that it specifies a + relative path to the ``llvm/autoconf`` directory. + + * **LLVM_CONFIG_PROJECT** - Just leave this alone. + + * **AC_CONFIG_SRCDIR** - Specify a path to a file name that identifies your + project; or just leave it at ``Makefile.common.in``. + + * **AC_CONFIG_FILES** - Do not change. + + * **AC_CONFIG_MAKEFILE** - Use one of these macros for each Makefile that + your project uses. This macro arranges for your makefiles to be copied from + the source directory, unmodified, to the build directory. + +5. After updating ``autoconf/configure.ac``, regenerate the configure script + with these commands. (You must be using ``Autoconf`` version 2.59 or later + and your ``aclocal`` version should be 1.9 or later.) + + .. code-block:: bash + + % cd autoconf + % ./AutoRegen.sh + +6. Run ``configure`` in the directory in which you want to place object code. + Use the following options to tell your project where it can find LLVM: + + ``--with-llvmsrc=`` + Tell your project where the LLVM source tree is located. + + ``--with-llvmobj=`` + Tell your project where the LLVM object tree is located. + + ``--prefix=`` + Tell your project where it should get installed. + +That's it! Now all you have to do is type ``gmake`` (or ``make`` if you're on a +GNU/Linux system) in the root of your object directory, and your project should +build. + +Source Tree Layout +================== + +In order to use the LLVM build system, you will want to organize your source +code so that it can benefit from the build system's features. Mainly, you want +your source tree layout to look similar to the LLVM source tree layout. The +best way to do this is to just copy the project tree from +``llvm/projects/sample`` and modify it to meet your needs, but you can certainly +add to it if you want. + +Underneath your top level directory, you should have the following directories: + +**lib** + + This subdirectory should contain all of your library source code. For each + library that you build, you will have one directory in **lib** that will + contain that library's source code. + + Libraries can be object files, archives, or dynamic libraries. The **lib** + directory is just a convenient place for libraries as it places them all in + a directory from which they can be linked later. + +**include** + + This subdirectory should contain any header files that are global to your + project. By global, we mean that they are used by more than one library or + executable of your project. + + By placing your header files in **include**, they will be found + automatically by the LLVM build system. For example, if you have a file + **include/jazz/note.h**, then your source files can include it simply with + **#include "jazz/note.h"**. + +**tools** + + This subdirectory should contain all of your source code for executables. + For each program that you build, you will have one directory in **tools** + that will contain that program's source code. + +**test** + + This subdirectory should contain tests that verify that your code works + correctly. Automated tests are especially useful. + + Currently, the LLVM build system provides basic support for tests. The LLVM + system provides the following: + +* LLVM contains regression tests in ``llvm/test``. These tests are run by the + :doc:`Lit ` testing tool. This test procedure uses ``RUN`` + lines in the actual test case to determine how to run the test. See the + :doc:`TestingGuide` for more details. + +* LLVM contains an optional package called ``llvm-test``, which provides + benchmarks and programs that are known to compile with the Clang front + end. You can use these programs to test your code, gather statistical + information, and compare it to the current LLVM performance statistics. + + Currently, there is no way to hook your tests directly into the ``llvm/test`` + testing harness. You will simply need to find a way to use the source + provided within that directory on your own. + +Typically, you will want to build your **lib** directory first followed by your +**tools** directory. + +Writing LLVM Style Makefiles +============================ + +The LLVM build system provides a convenient way to build libraries and +executables. Most of your project Makefiles will only need to define a few +variables. Below is a list of the variables one can set and what they can +do: + +Required Variables +------------------ + +``LEVEL`` + + This variable is the relative path from this ``Makefile`` to the top + directory of your project's source code. For example, if your source code + is in ``/tmp/src``, then the ``Makefile`` in ``/tmp/src/jump/high`` + would set ``LEVEL`` to ``"../.."``. + +Variables for Building Subdirectories +------------------------------------- + +``DIRS`` + + This is a space separated list of subdirectories that should be built. They + will be built, one at a time, in the order specified. + +``PARALLEL_DIRS`` + + This is a list of directories that can be built in parallel. These will be + built after the directories in DIRS have been built. + +``OPTIONAL_DIRS`` + + This is a list of directories that can be built if they exist, but will not + cause an error if they do not exist. They are built serially in the order + in which they are listed. + +Variables for Building Libraries +-------------------------------- + +``LIBRARYNAME`` + + This variable contains the base name of the library that will be built. For + example, to build a library named ``libsample.a``, ``LIBRARYNAME`` should + be set to ``sample``. + +``BUILD_ARCHIVE`` + + By default, a library is a ``.o`` file that is linked directly into a + program. To build an archive (also known as a static library), set the + ``BUILD_ARCHIVE`` variable. + +``SHARED_LIBRARY`` + + If ``SHARED_LIBRARY`` is defined in your Makefile, a shared (or dynamic) + library will be built. + +Variables for Building Programs +------------------------------- + +``TOOLNAME`` + + This variable contains the name of the program that will be built. For + example, to build an executable named ``sample``, ``TOOLNAME`` should be set + to ``sample``. + +``USEDLIBS`` + + This variable holds a space separated list of libraries that should be + linked into the program. These libraries must be libraries that come from + your **lib** directory. The libraries must be specified without their + ``lib`` prefix. For example, to link ``libsample.a``, you would set + ``USEDLIBS`` to ``sample.a``. + + Note that this works only for statically linked libraries. + +``LLVMLIBS`` + + This variable holds a space separated list of libraries that should be + linked into the program. These libraries must be LLVM libraries. The + libraries must be specified without their ``lib`` prefix. For example, to + link with a driver that performs an IR transformation you might set + ``LLVMLIBS`` to this minimal set of libraries ``LLVMSupport.a LLVMCore.a + LLVMBitReader.a LLVMAsmParser.a LLVMAnalysis.a LLVMTransformUtils.a + LLVMScalarOpts.a LLVMTarget.a``. + + Note that this works only for statically linked libraries. LLVM is split + into a large number of static libraries, and the list of libraries you + require may be much longer than the list above. To see a full list of + libraries use: ``llvm-config --libs all``. Using ``LINK_COMPONENTS`` as + described below, obviates the need to set ``LLVMLIBS``. + +``LINK_COMPONENTS`` + + This variable holds a space separated list of components that the LLVM + ``Makefiles`` pass to the ``llvm-config`` tool to generate a link line for + the program. For example, to link with all LLVM libraries use + ``LINK_COMPONENTS = all``. + +``LIBS`` + + To link dynamic libraries, add ``-l`` to the ``LIBS`` + variable. The LLVM build system will look in the same places for dynamic + libraries as it does for static libraries. + + For example, to link ``libsample.so``, you would have the following line in + your ``Makefile``: + + .. code-block:: makefile + + LIBS += -lsample + +Note that ``LIBS`` must occur in the Makefile after the inclusion of +``Makefile.common``. + +Miscellaneous Variables +----------------------- + +``CFLAGS`` & ``CPPFLAGS`` + + This variable can be used to add options to the C and C++ compiler, + respectively. It is typically used to add options that tell the compiler + the location of additional directories to search for header files. + + It is highly suggested that you append to ``CFLAGS`` and ``CPPFLAGS`` as + opposed to overwriting them. The master ``Makefiles`` may already have + useful options in them that you may not want to overwrite. + +Placement of Object Code +======================== + +The final location of built libraries and executables will depend upon whether +you do a ``Debug``, ``Release``, or ``Profile`` build. + +Libraries + + All libraries (static and dynamic) will be stored in + ``PROJ_OBJ_ROOT//lib``, where *type* is ``Debug``, ``Release``, or + ``Profile`` for a debug, optimized, or profiled build, respectively. + +Executables + + All executables will be stored in ``PROJ_OBJ_ROOT//bin``, where *type* + is ``Debug``, ``Release``, or ``Profile`` for a debug, optimized, or + profiled build, respectively. + +Further Help +============ + +If you have any questions or need any help creating an LLVM project, the LLVM +team would be more than happy to help. You can always post your questions to +the `LLVM Developers Mailing List +`_. diff --git a/docs/README.txt b/docs/README.txt new file mode 100644 index 00000000..22cf9307 --- /dev/null +++ b/docs/README.txt @@ -0,0 +1,42 @@ +LLVM Documentation +================== + +LLVM's documentation is written in reStructuredText, a lightweight +plaintext markup language (file extension `.rst`). While the +reStructuredText documentation should be quite readable in source form, it +is mostly meant to be processed by the Sphinx documentation generation +system to create HTML pages which are hosted on and +updated after every commit. Manpage output is also supported, see below. + +If you instead would like to generate and view the HTML locally, install +Sphinx and then do: + + cd docs/ + make -f Makefile.sphinx + $BROWSER _build/html/index.html + +The mapping between reStructuredText files and generated documentation is +`docs/Foo.rst` <-> `_build/html/Foo.html` <-> `http://llvm.org/docs/Foo.html`. + +If you are interested in writing new documentation, you will want to read +`SphinxQuickstartTemplate.rst` which will get you writing documentation +very fast and includes examples of the most important reStructuredText +markup syntax. + +Manpage Output +=============== + +Building the manpages is similar to building the HTML documentation. The +primary difference is to use the `man` makefile target, instead of the +default (which is `html`). Sphinx then produces the man pages in the +directory `_build/man/`. + + cd docs/ + make -f Makefile.sphinx man + man -l _build/man/FileCheck.1 + +The correspondence between .rst files and man pages is +`docs/CommandGuide/Foo.rst` <-> `_build/man/Foo.1`. +These .rst files are also included during HTML generation so they are also +viewable online (as noted above) at e.g. +`http://llvm.org/docs/CommandGuide/Foo.html`. diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst new file mode 100644 index 00000000..94663c4a --- /dev/null +++ b/docs/ReleaseNotes.rst @@ -0,0 +1,249 @@ +====================== +LLVM 3.4 Release Notes +====================== + +.. contents:: + :local: + +Introduction +============ + +This document contains the release notes for the LLVM Compiler Infrastructure, +release 3.4. Here we describe the status of LLVM, including major improvements +from the previous release, improvements in various subprojects of LLVM, and +some of the current users of the code. All LLVM releases may be downloaded +from the `LLVM releases web site `_. + +For more information about LLVM, including information about the latest +release, please check out the `main LLVM web site `_. If you +have questions or comments, the `LLVM Developer's Mailing List +`_ is a good place to send +them. + +Note that if you are reading this file from a Subversion checkout or the main +LLVM web page, this document applies to the *next* release, not the current +one. To see the release notes for a specific release, please see the `releases +page `_. + +Non-comprehensive list of changes in this release +================================================= + +* This is expected to be the last release of LLVM which compiles using a C++98 + toolchain. We expect to start using some C++11 features in LLVM and other + sub-projects starting after this release. That said, we are committed to + supporting a reasonable set of modern C++ toolchains as the host compiler on + all of the platforms. This will at least include Visual Studio 2012 on + Windows, and Clang 3.1 or GCC 4.7.x on Mac and Linux. The final set of + compilers (and the C++11 features they support) is not set in stone, but we + wanted users of LLVM to have a heads up that the next release will involve + a substantial change in the host toolchain requirements. + +* The regression tests now fail if any command in a pipe fails. To disable it in + a directory, just add ``config.pipefail = False`` to its ``lit.local.cfg``. + See :doc:`Lit ` for the details. + +* Support for exception handling has been removed from the old JIT. Use MCJIT + if you need EH support. + +* The R600 backend is not marked experimental anymore and is built by default. + +* ``APFloat::isNormal()`` was renamed to ``APFloat::isFiniteNonZero()`` and + ``APFloat::isIEEENormal()`` was renamed to ``APFloat::isNormal()``. This + ensures that ``APFloat::isNormal()`` conforms to IEEE-754R-2008. + +* The library call simplification pass has been removed. Its functionality + has been integrated into the instruction combiner and function attribute + marking passes. + +* Support for building using Visual Studio 2008 has been dropped. Use VS 2010 + or later instead. For more information, see the `Getting Started using Visual + Studio `_ page. + +* The Loop Vectorizer that was previously enabled for ``-O3`` is now enabled + for ``-Os`` and ``-O2``. + +* The new SLP Vectorizer is now enabled by default. + +* ``llvm-ar`` now uses the new Object library and produces archives and + symbol tables in the gnu format. + +* FileCheck now allows specifing ``-check-prefix`` multiple times. This + helps reduce duplicate check lines when using multiple RUN lines. + +* The bitcast instruction no longer allows casting between pointers + with different address spaces. To achieve this, use the new addrspacecast + instruction. + +* Different sized pointers for different address spaces should now + generally work. This is primarily useful for GPU targets. + +* OCaml bindings have been significantly extended to cover almost all of the + LLVM libraries. + +Mips Target +----------- + +Support for the MIPS SIMD Architecture (MSA) has been added. MSA is supported +through inline assembly, intrinsics with the prefix '``__builtin_msa``', and +normal code generation. + +For more information on MSA (including documentation for the instruction set), +see the `MIPS SIMD page at Imagination Technologies +`_ + +PowerPC Target +-------------- + +Changes in the PowerPC backend include: + +* fast-isel support (for faster ``-O0`` code generation) +* many improvements to the builtin assembler +* support for generating unaligned (Altivec) vector loads +* support for generating the fcpsgn instruction +* generate ``frin`` for ``round()`` (not ``nearbyint()`` and ``rint()``, which + had been done only in fast-math mode) +* improved instruction scheduling for embedded cores (such as the A2) +* improved prologue/epilogue generation (especially in 32-bit mode) +* support for dynamic stack alignment (and dynamic stack allocations with large alignments) +* improved generation of counter-register-based loops +* bug fixes + +SPARC Target +------------ + +The SPARC backend got many improvements, namely + +* experimental SPARC V9 backend +* JIT support for SPARC +* fp128 support +* exception handling +* TLS support +* leaf functions optimization +* bug fixes + +SystemZ/s390x Backend +--------------------- + +LLVM and clang can now optimize for zEnterprise z196 and zEnterprise EC12 +targets. In clang these targets are selected using ``-march=z196`` and +``-march=zEC12`` respectively. + +External Open Source Projects Using LLVM 3.4 +============================================ + +An exciting aspect of LLVM is that it is used as an enabling technology for +a lot of other language and tools projects. This section lists some of the +projects that have already been updated to work with LLVM 3.4. + +DXR +--- + +`DXR `_ is Mozilla's code search and navigation +tool, aimed at making sense of large projects like Firefox. It supports +full-text and regex searches as well as structural queries like "Find all the +callers of this function." Behind the scenes, it uses a custom trigram index, +the re2 library, and structural data collected by a clang compiler plugin. + +LDC - the LLVM-based D compiler +------------------------------- + +`D `_ is a language with C-like syntax and static typing. It +pragmatically combines efficiency, control, and modeling power, with safety and +programmer productivity. D supports powerful concepts like Compile-Time Function +Execution (CTFE) and Template Meta-Programming, provides an innovative approach +to concurrency and offers many classical paradigms. + +`LDC `_ uses the frontend from the reference compiler +combined with LLVM as backend to produce efficient native code. LDC targets +x86/x86_64 systems like Linux, OS X, FreeBSD and Windows and also Linux/PPC64. +Ports to other architectures like ARM and AArch64 are underway. + +LibBeauty +--------- + +The `LibBeauty `_ decompiler and reverse +engineering tool currently utilises the LLVM disassembler and the LLVM IR +Builder. The current aim of the project is to take a x86_64 binary ``.o`` file +as input, and produce an equivalent LLVM IR ``.bc`` or ``.ll`` file as +output. Support for ARM binary ``.o`` file as input will be added later. + +Likely +------ + +`Likely `_ is an open source domain specific +language for image recognition. Algorithms are just-in-time compiled using +LLVM's MCJIT infrastructure to execute on single or multi-threaded CPUs as well +as OpenCL SPIR or CUDA enabled GPUs. Likely exploits the observation that while +image processing and statistical learning kernels must be written generically +to handle any matrix datatype, at runtime they tend to be executed repeatedly +on the same type. + +Portable Computing Language (pocl) +---------------------------------- + +In addition to producing an easily portable open source OpenCL +implementation, another major goal of `pocl `_ +is improving performance portability of OpenCL programs with +compiler optimizations, reducing the need for target-dependent manual +optimizations. An important part of pocl is a set of LLVM passes used to +statically parallelize multiple work-items with the kernel compiler, even in +the presence of work-group barriers. This enables static parallelization of +the fine-grained static concurrency in the work groups in multiple ways. + +Portable Native Client (PNaCl) +------------------------------ + +`Portable Native Client (PNaCl) `_ +is a Chrome initiative to bring the performance and low-level control of native +code to modern web browsers, without sacrificing the security benefits and +portability of web applications. PNaCl works by compiling native C and C++ code +to an intermediate representation using the LLVM clang compiler. This +intermediate representation is a subset of LLVM bytecode that is wrapped into a +portable executable, which can be hosted on a web server like any other website +asset. When the site is accessed, Chrome fetches and translates the portable +executable into an architecture-specific machine code optimized directly for +the underlying device. PNaCl lets developers compile their code once to run on +any hardware platform and embed their PNaCl application in any website, +enabling developers to directly leverage the power of the underlying CPU and +GPU. + +TTA-based Co-design Environment (TCE) +------------------------------------- + +`TCE `_ is a toolset for designing new +exposed datapath processors based on the Transport triggered architecture (TTA). +The toolset provides a complete co-design flow from C/C++ +programs down to synthesizable VHDL/Verilog and parallel program binaries. +Processor customization points include the register files, function units, +supported operations, and the interconnection network. + +TCE uses Clang and LLVM for C/C++/OpenCL C language support, target independent +optimizations and also for parts of code generation. It generates +new LLVM-based code generators "on the fly" for the designed processors and +loads them in to the compiler backend as runtime libraries to avoid +per-target recompilation of larger parts of the compiler chain. + +WebCL Validator +--------------- + +`WebCL Validator `_ implements +validation for WebCL C language which is a subset of OpenCL ES 1.1. Validator +checks the correctness of WebCL C, and implements memory protection for it as a +source-2-source transformation. The transformation converts WebCL to memory +protected OpenCL. The protected OpenCL cannot access any memory ranges which +were not allocated for it, and its memory is always initialized to prevent +information leakage from other programs. + + +Additional Information +====================== + +A wide variety of additional information is available on the `LLVM web page +`_, in particular in the `documentation +`_ section. The web page also contains versions of the +API documentation which is up-to-date with the Subversion version of the source +code. You can access versions of these documents specific to this release by +going into the ``llvm/docs/`` directory in the LLVM tree. + +If you have any questions or comments about LLVM, please feel free to contact +us via the `mailing lists `_. diff --git a/docs/ReleaseProcess.rst b/docs/ReleaseProcess.rst new file mode 100644 index 00000000..0836b6e9 --- /dev/null +++ b/docs/ReleaseProcess.rst @@ -0,0 +1,212 @@ +============================= +How To Validate a New Release +============================= + +.. contents:: + :local: + :depth: 1 + +Introduction +============ + +This document contains information about testing the release candidates that will +ultimately be the next LLVM release. For more information on how to manage the +actual release, please refer to :doc:`HowToReleaseLLVM`. + +Overview of the Release Process +------------------------------- + +Once the release process starts, the Release Manager will ask for volunteers, +and it'll be the role of each volunteer to: + +* Test and benchmark the previous release + +* Test and benchmark each release candidate, comparing to the previous release and candidates + +* Identify, reduce and report every regression found during tests and benchmarks + +* Make sure the critical bugs get fixed and merged to the next release candidate + +Not all bugs or regressions are show-stoppers and it's a bit of a grey area what +should be fixed before the next candidate and what can wait until the next release. + +It'll depend on: + +* The severity of the bug, how many people it affects and if it's a regression or a + known bug. Known bugs are "unsupported features" and some bugs can be disabled if + they have been implemented recently. + +* The stage in the release. Less critical bugs should be considered to be fixed between + RC1 and RC2, but not so much at the end of it. + +* If it's a correctness or a performance regression. Performance regression tends to be + taken more lightly than correctness. + +.. _scripts: + +Scripts +======= + +The scripts are in the ``utils/release`` directory. + +test-release.sh +--------------- + +This script will check-out, configure and compile LLVM+Clang (+ most add-ons, +like ``compiler-rt``, ``libcxx`` and ``clang-extra-tools``) in three stages, and +will test the final stage. It'll have installed the final binaries on the +Phase3/Releasei(+Asserts) directory, and that's the one you should use for the +test-suite and other external tests. + +To run the script on a specific release candidate run:: + + ./test-release.sh \ + -release 3.4 \ + -rc 1 \ + -triple x86_64-apple-darwin \ + -no-64bit \ + -test-asserts \ + -no-compare-files + +Each system will require different options. For instance, x86_64 will obviously not need +``-no-64bit`` while 32-bit systems will, or the script will fail. + +The important flags to get right are: + +* On the pre-release, you should change ``-rc 1`` to ``-final``. On RC2, change it to ``-rc 2`` and so on. + +* On non-release testing, you can use ``-final`` in conjunction with ``-no-checkout``, but you'll have to + create the ``final`` directory by hand and link the correct source dir to ``final/llvm.src``. + +* For release candidates, you need ``-test-asserts``, or it won't create a "Release+Asserts" directory, + which is needed for release testing and benchmarking. This will take twice as long. + +* On the final candidate you just need Release builds, and that's the binary directory you'll have to pack. + +This script builds three phases of Clang+LLVM twice each (Release and Release+Asserts), so use +screen or nohup to avoid headaches, since it'll take a long time. + +Use the ``--help`` option to see all the options and chose it according to your needs. + + +findRegressions-nightly.py +-------------------------- + +TODO + +.. _test-suite: + +Test Suite +========== + +.. contents:: + :local: + +Follow the `LNT Quick Start Guide `__ link on how to set-up the test-suite + +The binary location you'll have to use for testing is inside the ``rcN/Phase3/Release+Asserts/llvmCore-REL-RC.install``. +Link that directory to an easier location and run the test-suite. + +An example on the run command line, assuming you created a link from the correct +install directory to ``~/devel/llvm/install``:: + + ./sandbox/bin/python sandbox/bin/lnt runtest \ + nt \ + -j4 \ + --sandbox sandbox \ + --test-suite ~/devel/llvm/test/test-suite \ + --cc ~/devel/llvm/install/bin/clang \ + --cxx ~/devel/llvm/install/bin/clang++ + +It should have no new regressions, compared to the previous release or release candidate. You don't need to fix +all the bugs in the test-suite, since they're not necessarily meant to pass on all architectures all the time. This is +due to the nature of the result checking, which relies on direct comparison, and most of the time, the failures are +related to bad output checking, rather than bad code generation. + +If the errors are in LLVM itself, please report every single regression found as blocker, and all the other bugs +as important, but not necessarily blocking the release to proceed. They can be set as "known failures" and to be +fix on a future date. + +.. _pre-release-process: + +Pre-Release Process +=================== + +.. contents:: + :local: + +When the release process is announced on the mailing list, you should prepare +for the testing, by applying the same testing you'll do on the release candidates, +on the previous release. + +You should: + +* Download the previous release sources from http://llvm.org/releases/download.html. + +* Run the test-release.sh script on ``final`` mode (change ``-rc 1`` to ``-final``). + +* Once all three stages are done, it'll test the final stage. + +* Using the ``Phase3/Release+Asserts/llvmCore-MAJ.MIN-final.install`` base, run the test-suite. + +If the final phase's ``make check-all`` failed, it's a good idea to also test the +intermediate stages by going on the obj directory and running ``make check-all`` to find +if there's at least one stage that passes (helps when reducing the error for bug report +purposes). + +.. _release-process: + +Release Process +=============== + +.. contents:: + :local: + +When the Release Manager sends you the release candidate, download all sources, +unzip on the same directory (there will be sym-links from the appropriate places +to them), and run the release test as above. + +You should: + +* Download the current candidate sources from where the release manager points you + (ex. http://llvm.org/pre-releases/3.3/rc1/). + +* Repeat the steps above with ``-rc 1``, ``-rc 2`` etc modes and run the test-suite + the same way. + +* Compare the results, report all errors on Bugzilla and publish the binary blob + where the release manager can grab it. + +Once the release manages announces that the latest candidate is the good one, you +have to pack the ``Release`` (no Asserts) install directory on ``Phase3`` and that +will be the official binary. + +* Rename (or link) ``clang+llvm-REL-ARCH-ENV`` to the .install directory + +* Tar that into the same name with ``.tar.gz`` extensioan from outside the directory + +* Make it available for the release manager to download + +.. _bug-reporting: + +Bug Reporting Process +===================== + +.. contents:: + :local: + +If you found regressions or failures when comparing a release candidate with the +previous release, follow the rules below: + +* Critical bugs on compilation should be fixed as soon as possible, possibly before + releasing the binary blobs. + +* Check-all tests should be fixed before the next release candidate, but can wait + until the test-suite run is finished. + +* Bugs in the test suite or unimportant check-all tests can be fixed in between + release candidates. + +* New features or recent big changes, when close to the release, should have done + in a way that it's easy to disable. If they misbehave, prefer disabling them than + releasing an unstable (but untested) binary package. diff --git a/docs/SegmentedStacks.rst b/docs/SegmentedStacks.rst new file mode 100644 index 00000000..e44ce423 --- /dev/null +++ b/docs/SegmentedStacks.rst @@ -0,0 +1,78 @@ +======================== +Segmented Stacks in LLVM +======================== + +.. contents:: + :local: + +Introduction +============ + +Segmented stack allows stack space to be allocated incrementally than as a +monolithic chunk (of some worst case size) at thread initialization. This is +done by allocating stack blocks (henceforth called *stacklets*) and linking them +into a doubly linked list. The function prologue is responsible for checking if +the current stacklet has enough space for the function to execute; and if not, +call into the libgcc runtime to allocate more stack space. When using ``llc``, +segmented stacks can be enabled by adding ``-segmented-stacks`` to the command +line. + +The runtime functionality is `already there in libgcc +`_. + +Implementation Details +====================== + +.. _allocating stacklets: + +Allocating Stacklets +-------------------- + +As mentioned above, the function prologue checks if the current stacklet has +enough space. The current approach is to use a slot in the TCB to store the +current stack limit (minus the amount of space needed to allocate a new block) - +this slot's offset is again dictated by ``libgcc``. The generated +assembly looks like this on x86-64: + +.. code-block:: nasm + + leaq -8(%rsp), %r10 + cmpq %fs:112, %r10 + jg .LBB0_2 + + # More stack space needs to be allocated + movabsq $8, %r10 # The amount of space needed + movabsq $0, %r11 # The total size of arguments passed on stack + callq __morestack + ret # The reason for this extra return is explained below + .LBB0_2: + # Usual prologue continues here + +The size of function arguments on the stack needs to be passed to +``__morestack`` (this function is implemented in ``libgcc``) since that number +of bytes has to be copied from the previous stacklet to the current one. This is +so that SP (and FP) relative addressing of function arguments work as expected. + +The unusual ``ret`` is needed to have the function which made a call to +``__morestack`` return correctly. ``__morestack``, instead of returning, calls +into ``.LBB0_2``. This is possible since both, the size of the ``ret`` +instruction and the PC of call to ``__morestack`` are known. When the function +body returns, control is transferred back to ``__morestack``. ``__morestack`` +then de-allocates the new stacklet, restores the correct SP value, and does a +second return, which returns control to the correct caller. + +Variable Sized Allocas +---------------------- + +The section on `allocating stacklets`_ automatically assumes that every stack +frame will be of fixed size. However, LLVM allows the use of the ``llvm.alloca`` +intrinsic to allocate dynamically sized blocks of memory on the stack. When +faced with such a variable-sized alloca, code is generated to: + +* Check if the current stacklet has enough space. If yes, just bump the SP, like + in the normal case. +* If not, generate a call to ``libgcc``, which allocates the memory from the + heap. + +The memory allocated from the heap is linked into a list in the current +stacklet, and freed along with the same. This prevents a memory leak. diff --git a/docs/SourceLevelDebugging.rst b/docs/SourceLevelDebugging.rst new file mode 100644 index 00000000..a1d81106 --- /dev/null +++ b/docs/SourceLevelDebugging.rst @@ -0,0 +1,2317 @@ +================================ +Source Level Debugging with LLVM +================================ + +.. contents:: + :local: + +Introduction +============ + +This document is the central repository for all information pertaining to debug +information in LLVM. It describes the :ref:`actual format that the LLVM debug +information takes `, which is useful for those interested in creating +front-ends or dealing directly with the information. Further, this document +provides specific examples of what debug information for C/C++ looks like. + +Philosophy behind LLVM debugging information +-------------------------------------------- + +The idea of the LLVM debugging information is to capture how the important +pieces of the source-language's Abstract Syntax Tree map onto LLVM code. +Several design aspects have shaped the solution that appears here. The +important ones are: + +* Debugging information should have very little impact on the rest of the + compiler. No transformations, analyses, or code generators should need to + be modified because of debugging information. + +* LLVM optimizations should interact in :ref:`well-defined and easily described + ways ` with the debugging information. + +* Because LLVM is designed to support arbitrary programming languages, + LLVM-to-LLVM tools should not need to know anything about the semantics of + the source-level-language. + +* Source-level languages are often **widely** different from one another. + LLVM should not put any restrictions of the flavor of the source-language, + and the debugging information should work with any language. + +* With code generator support, it should be possible to use an LLVM compiler + to compile a program to native machine code and standard debugging + formats. This allows compatibility with traditional machine-code level + debuggers, like GDB or DBX. + +The approach used by the LLVM implementation is to use a small set of +:ref:`intrinsic functions ` to define a mapping +between LLVM program objects and the source-level objects. The description of +the source-level program is maintained in LLVM metadata in an +:ref:`implementation-defined format ` (the C/C++ front-end +currently uses working draft 7 of the `DWARF 3 standard +`_). + +When a program is being debugged, a debugger interacts with the user and turns +the stored debug information into source-language specific information. As +such, a debugger must be aware of the source-language, and is thus tied to a +specific language or family of languages. + +Debug information consumers +--------------------------- + +The role of debug information is to provide meta information normally stripped +away during the compilation process. This meta information provides an LLVM +user a relationship between generated code and the original program source +code. + +Currently, debug information is consumed by DwarfDebug to produce dwarf +information used by the gdb debugger. Other targets could use the same +information to produce stabs or other debug forms. + +It would also be reasonable to use debug information to feed profiling tools +for analysis of generated code, or, tools for reconstructing the original +source from generated code. + +TODO - expound a bit more. + +.. _intro_debugopt: + +Debugging optimized code +------------------------ + +An extremely high priority of LLVM debugging information is to make it interact +well with optimizations and analysis. In particular, the LLVM debug +information provides the following guarantees: + +* LLVM debug information **always provides information to accurately read + the source-level state of the program**, regardless of which LLVM + optimizations have been run, and without any modification to the + optimizations themselves. However, some optimizations may impact the + ability to modify the current state of the program with a debugger, such + as setting program variables, or calling functions that have been + deleted. + +* As desired, LLVM optimizations can be upgraded to be aware of the LLVM + debugging information, allowing them to update the debugging information + as they perform aggressive optimizations. This means that, with effort, + the LLVM optimizers could optimize debug code just as well as non-debug + code. + +* LLVM debug information does not prevent optimizations from + happening (for example inlining, basic block reordering/merging/cleanup, + tail duplication, etc). + +* LLVM debug information is automatically optimized along with the rest of + the program, using existing facilities. For example, duplicate + information is automatically merged by the linker, and unused information + is automatically removed. + +Basically, the debug information allows you to compile a program with +"``-O0 -g``" and get full debug information, allowing you to arbitrarily modify +the program as it executes from a debugger. Compiling a program with +"``-O3 -g``" gives you full debug information that is always available and +accurate for reading (e.g., you get accurate stack traces despite tail call +elimination and inlining), but you might lose the ability to modify the program +and call functions where were optimized out of the program, or inlined away +completely. + +:ref:`LLVM test suite ` provides a framework to test +optimizer's handling of debugging information. It can be run like this: + +.. code-block:: bash + + % cd llvm/projects/test-suite/MultiSource/Benchmarks # or some other level + % make TEST=dbgopt + +This will test impact of debugging information on optimization passes. If +debugging information influences optimization passes then it will be reported +as a failure. See :doc:`TestingGuide` for more information on LLVM test +infrastructure and how to run various tests. + +.. _format: + +Debugging information format +============================ + +LLVM debugging information has been carefully designed to make it possible for +the optimizer to optimize the program and debugging information without +necessarily having to know anything about debugging information. In +particular, the use of metadata avoids duplicated debugging information from +the beginning, and the global dead code elimination pass automatically deletes +debugging information for a function if it decides to delete the function. + +To do this, most of the debugging information (descriptors for types, +variables, functions, source files, etc) is inserted by the language front-end +in the form of LLVM metadata. + +Debug information is designed to be agnostic about the target debugger and +debugging information representation (e.g. DWARF/Stabs/etc). It uses a generic +pass to decode the information that represents variables, types, functions, +namespaces, etc: this allows for arbitrary source-language semantics and +type-systems to be used, as long as there is a module written for the target +debugger to interpret the information. + +To provide basic functionality, the LLVM debugger does have to make some +assumptions about the source-level language being debugged, though it keeps +these to a minimum. The only common features that the LLVM debugger assumes +exist are :ref:`source files `, and :ref:`program objects +`. These abstract objects are used by a debugger to +form stack traces, show information about local variables, etc. + +This section of the documentation first describes the representation aspects +common to any source-language. :ref:`ccxx_frontend` describes the data layout +conventions used by the C and C++ front-ends. + +Debug information descriptors +----------------------------- + +In consideration of the complexity and volume of debug information, LLVM +provides a specification for well formed debug descriptors. + +Consumers of LLVM debug information expect the descriptors for program objects +to start in a canonical format, but the descriptors can include additional +information appended at the end that is source-language specific. All debugging +information objects start with a tag to indicate what type of object it is. +The source-language is allowed to define its own objects, by using unreserved +tag numbers. We recommend using with tags in the range 0x1000 through 0x2000 +(there is a defined ``enum DW_TAG_user_base = 0x1000``.) + +The fields of debug descriptors used internally by LLVM are restricted to only +the simple data types ``i32``, ``i1``, ``float``, ``double``, ``mdstring`` and +``mdnode``. + +.. code-block:: llvm + + !1 = metadata !{ + i32, ;; A tag + ... + } + +The first field of a descriptor is always an +``i32`` containing a tag value identifying the content of the descriptor. +The remaining fields are specific to the descriptor. The values of tags are +loosely bound to the tag values of DWARF information entries. However, that +does not restrict the use of the information supplied to DWARF targets. + +The details of the various descriptors follow. + +Compile unit descriptors +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !0 = metadata !{ + i32, ;; Tag = 17 (DW_TAG_compile_unit) + metadata, ;; Source directory (including trailing slash) & file pair + i32, ;; DWARF language identifier (ex. DW_LANG_C89) + metadata ;; Producer (ex. "4.0.1 LLVM (LLVM research group)") + i1, ;; True if this is optimized. + metadata, ;; Flags + i32 ;; Runtime version + metadata ;; List of enums types + metadata ;; List of retained types + metadata ;; List of subprograms + metadata ;; List of global variables + metadata ;; List of imported entities + metadata ;; Split debug filename + } + +These descriptors contain a source language ID for the file (we use the DWARF +3.0 ID numbers, such as ``DW_LANG_C89``, ``DW_LANG_C_plus_plus``, +``DW_LANG_Cobol74``, etc), a reference to a metadata node containing a pair of +strings for the source file name and the working directory, as well as an +identifier string for the compiler that produced it. + +Compile unit descriptors provide the root context for objects declared in a +specific compilation unit. File descriptors are defined using this context. +These descriptors are collected by a named metadata ``!llvm.dbg.cu``. They +keep track of subprograms, global variables, type information, and imported +entities (declarations and namespaces). + +.. _format_files: + +File descriptors +^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !0 = metadata !{ + i32, ;; Tag = 41 (DW_TAG_file_type) + metadata, ;; Source directory (including trailing slash) & file pair + } + +These descriptors contain information for a file. Global variables and top +level functions would be defined using this context. File descriptors also +provide context for source line correspondence. + +Each input file is encoded as a separate file descriptor in LLVM debugging +information output. + +.. _format_global_variables: + +Global variable descriptors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !1 = metadata !{ + i32, ;; Tag = 52 (DW_TAG_variable) + i32, ;; Unused field. + metadata, ;; Reference to context descriptor + metadata, ;; Name + metadata, ;; Display name (fully qualified C++ name) + metadata, ;; MIPS linkage name (for C++) + metadata, ;; Reference to file where defined + i32, ;; Line number where defined + metadata, ;; Reference to type descriptor + i1, ;; True if the global is local to compile unit (static) + i1, ;; True if the global is defined in the compile unit (not extern) + {}*, ;; Reference to the global variable + metadata, ;; The static member declaration, if any + } + +These descriptors provide debug information about globals variables. They +provide details such as name, type and where the variable is defined. All +global variables are collected inside the named metadata ``!llvm.dbg.cu``. + +.. _format_subprograms: + +Subprogram descriptors +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32, ;; Tag = 46 (DW_TAG_subprogram) + metadata, ;; Source directory (including trailing slash) & file pair + metadata, ;; Reference to context descriptor + metadata, ;; Name + metadata, ;; Display name (fully qualified C++ name) + metadata, ;; MIPS linkage name (for C++) + i32, ;; Line number where defined + metadata, ;; Reference to type descriptor + i1, ;; True if the global is local to compile unit (static) + i1, ;; True if the global is defined in the compile unit (not extern) + i32, ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual + i32, ;; Index into a virtual function + metadata, ;; indicates which base type contains the vtable pointer for the + ;; derived class + i32, ;; Flags - Artificial, Private, Protected, Explicit, Prototyped. + i1, ;; isOptimized + Function * , ;; Pointer to LLVM function + metadata, ;; Lists function template parameters + metadata, ;; Function declaration descriptor + metadata, ;; List of function variables + i32 ;; Line number where the scope of the subprogram begins + } + +These descriptors provide debug information about functions, methods and +subprograms. They provide details such as name, return types and the source +location where the subprogram is defined. + +Block descriptors +^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !3 = metadata !{ + i32, ;; Tag = 11 (DW_TAG_lexical_block) + metadata,;; Source directory (including trailing slash) & file pair + metadata,;; Reference to context descriptor + i32, ;; Line number + i32, ;; Column number + i32 ;; Unique ID to identify blocks from a template function + } + +This descriptor provides debug information about nested blocks within a +subprogram. The line number and column numbers are used to dinstinguish two +lexical blocks at same depth. + +.. code-block:: llvm + + !3 = metadata !{ + i32, ;; Tag = 11 (DW_TAG_lexical_block) + metadata,;; Source directory (including trailing slash) & file pair + metadata ;; Reference to the scope we're annotating with a file change + } + +This descriptor provides a wrapper around a lexical scope to handle file +changes in the middle of a lexical block. + +.. _format_basic_type: + +Basic type descriptors +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !4 = metadata !{ + i32, ;; Tag = 36 (DW_TAG_base_type) + metadata, ;; Source directory (including trailing slash) & file pair (may be null) + metadata, ;; Reference to context + metadata, ;; Name (may be "" for anonymous types) + i32, ;; Line number where defined (may be 0) + i64, ;; Size in bits + i64, ;; Alignment in bits + i64, ;; Offset in bits + i32, ;; Flags + i32 ;; DWARF type encoding + } + +These descriptors define primitive types used in the code. Example ``int``, +``bool`` and ``float``. The context provides the scope of the type, which is +usually the top level. Since basic types are not usually user defined the +context and line number can be left as NULL and 0. The size, alignment and +offset are expressed in bits and can be 64 bit values. The alignment is used +to round the offset when embedded in a :ref:`composite type +` (example to keep float doubles on 64 bit boundaries). +The offset is the bit offset if embedded in a :ref:`composite type +`. + +The type encoding provides the details of the type. The values are typically +one of the following: + +.. code-block:: llvm + + DW_ATE_address = 1 + DW_ATE_boolean = 2 + DW_ATE_float = 4 + DW_ATE_signed = 5 + DW_ATE_signed_char = 6 + DW_ATE_unsigned = 7 + DW_ATE_unsigned_char = 8 + +.. _format_derived_type: + +Derived type descriptors +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !5 = metadata !{ + i32, ;; Tag (see below) + metadata, ;; Source directory (including trailing slash) & file pair (may be null) + metadata, ;; Reference to context + metadata, ;; Name (may be "" for anonymous types) + i32, ;; Line number where defined (may be 0) + i64, ;; Size in bits + i64, ;; Alignment in bits + i64, ;; Offset in bits + i32, ;; Flags to encode attributes, e.g. private + metadata, ;; Reference to type derived from + metadata, ;; (optional) Name of the Objective C property associated with + ;; Objective-C an ivar, or the type of which this + ;; pointer-to-member is pointing to members of. + metadata, ;; (optional) Name of the Objective C property getter selector. + metadata, ;; (optional) Name of the Objective C property setter selector. + i32 ;; (optional) Objective C property attributes. + } + +These descriptors are used to define types derived from other types. The value +of the tag varies depending on the meaning. The following are possible tag +values: + +.. code-block:: llvm + + DW_TAG_formal_parameter = 5 + DW_TAG_member = 13 + DW_TAG_pointer_type = 15 + DW_TAG_reference_type = 16 + DW_TAG_typedef = 22 + DW_TAG_ptr_to_member_type = 31 + DW_TAG_const_type = 38 + DW_TAG_volatile_type = 53 + DW_TAG_restrict_type = 55 + +``DW_TAG_member`` is used to define a member of a :ref:`composite type +` or :ref:`subprogram `. The type +of the member is the :ref:`derived type `. +``DW_TAG_formal_parameter`` is used to define a member which is a formal +argument of a subprogram. + +``DW_TAG_typedef`` is used to provide a name for the derived type. + +``DW_TAG_pointer_type``, ``DW_TAG_reference_type``, ``DW_TAG_const_type``, +``DW_TAG_volatile_type`` and ``DW_TAG_restrict_type`` are used to qualify the +:ref:`derived type `. + +:ref:`Derived type ` location can be determined from the +context and line number. The size, alignment and offset are expressed in bits +and can be 64 bit values. The alignment is used to round the offset when +embedded in a :ref:`composite type ` (example to keep +float doubles on 64 bit boundaries.) The offset is the bit offset if embedded +in a :ref:`composite type `. + +Note that the ``void *`` type is expressed as a type derived from NULL. + +.. _format_composite_type: + +Composite type descriptors +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !6 = metadata !{ + i32, ;; Tag (see below) + metadata, ;; Source directory (including trailing slash) & file pair (may be null) + metadata, ;; Reference to context + metadata, ;; Name (may be "" for anonymous types) + i32, ;; Line number where defined (may be 0) + i64, ;; Size in bits + i64, ;; Alignment in bits + i64, ;; Offset in bits + i32, ;; Flags + metadata, ;; Reference to type derived from + metadata, ;; Reference to array of member descriptors + i32, ;; Runtime languages + metadata, ;; Base type containing the vtable pointer for this type + metadata, ;; Template parameters + metadata ;; A unique identifier for type uniquing purpose (may be null) + } + +These descriptors are used to define types that are composed of 0 or more +elements. The value of the tag varies depending on the meaning. The following +are possible tag values: + +.. code-block:: llvm + + DW_TAG_array_type = 1 + DW_TAG_enumeration_type = 4 + DW_TAG_structure_type = 19 + DW_TAG_union_type = 23 + DW_TAG_subroutine_type = 21 + DW_TAG_inheritance = 28 + +The vector flag indicates that an array type is a native packed vector. + +The members of array types (tag = ``DW_TAG_array_type``) are +:ref:`subrange descriptors `, each +representing the range of subscripts at that level of indexing. + +The members of enumeration types (tag = ``DW_TAG_enumeration_type``) are +:ref:`enumerator descriptors `, each representing the +definition of enumeration value for the set. All enumeration type descriptors +are collected inside the named metadata ``!llvm.dbg.cu``. + +The members of structure (tag = ``DW_TAG_structure_type``) or union (tag = +``DW_TAG_union_type``) types are any one of the :ref:`basic +`, :ref:`derived ` or :ref:`composite +` type descriptors, each representing a field member of +the structure or union. + +For C++ classes (tag = ``DW_TAG_structure_type``), member descriptors provide +information about base classes, static members and member functions. If a +member is a :ref:`derived type descriptor ` and has a tag +of ``DW_TAG_inheritance``, then the type represents a base class. If the member +of is a :ref:`global variable descriptor ` then it +represents a static member. And, if the member is a :ref:`subprogram +descriptor ` then it represents a member function. For +static members and member functions, ``getName()`` returns the members link or +the C++ mangled name. ``getDisplayName()`` the simplied version of the name. + +The first member of subroutine (tag = ``DW_TAG_subroutine_type``) type elements +is the return type for the subroutine. The remaining elements are the formal +arguments to the subroutine. + +:ref:`Composite type ` location can be determined from +the context and line number. The size, alignment and offset are expressed in +bits and can be 64 bit values. The alignment is used to round the offset when +embedded in a :ref:`composite type ` (as an example, to +keep float doubles on 64 bit boundaries). The offset is the bit offset if +embedded in a :ref:`composite type `. + +.. _format_subrange: + +Subrange descriptors +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !42 = metadata !{ + i32, ;; Tag = 33 (DW_TAG_subrange_type) + i64, ;; Low value + i64 ;; High value + } + +These descriptors are used to define ranges of array subscripts for an array +:ref:`composite type `. The low value defines the lower +bounds typically zero for C/C++. The high value is the upper bounds. Values +are 64 bit. ``High - Low + 1`` is the size of the array. If ``Low > High`` +the array bounds are not included in generated debugging information. + +.. _format_enumerator: + +Enumerator descriptors +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !6 = metadata !{ + i32, ;; Tag = 40 (DW_TAG_enumerator) + metadata, ;; Name + i64 ;; Value + } + +These descriptors are used to define members of an enumeration :ref:`composite +type `, it associates the name to the value. + +Local variables +^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !7 = metadata !{ + i32, ;; Tag (see below) + metadata, ;; Context + metadata, ;; Name + metadata, ;; Reference to file where defined + i32, ;; 24 bit - Line number where defined + ;; 8 bit - Argument number. 1 indicates 1st argument. + metadata, ;; Type descriptor + i32, ;; flags + metadata ;; (optional) Reference to inline location + } + +These descriptors are used to define variables local to a sub program. The +value of the tag depends on the usage of the variable: + +.. code-block:: llvm + + DW_TAG_auto_variable = 256 + DW_TAG_arg_variable = 257 + +An auto variable is any variable declared in the body of the function. An +argument variable is any variable that appears as a formal argument to the +function. + +The context is either the subprogram or block where the variable is defined. +Name the source variable name. Context and line indicate where the variable +was defined. Type descriptor defines the declared type of the variable. + +.. _format_common_intrinsics: + +Debugger intrinsic functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +LLVM uses several intrinsic functions (name prefixed with "``llvm.dbg``") to +provide debug information at various points in generated code. + +``llvm.dbg.declare`` +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + void %llvm.dbg.declare(metadata, metadata) + +This intrinsic provides information about a local element (e.g., variable). +The first argument is metadata holding the alloca for the variable. The second +argument is metadata containing a description of the variable. + +``llvm.dbg.value`` +^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + void %llvm.dbg.value(metadata, i64, metadata) + +This intrinsic provides information when a user source variable is set to a new +value. The first argument is the new value (wrapped as metadata). The second +argument is the offset in the user source variable where the new value is +written. The third argument is metadata containing a description of the user +source variable. + +Object lifetimes and scoping +============================ + +In many languages, the local variables in functions can have their lifetimes or +scopes limited to a subset of a function. In the C family of languages, for +example, variables are only live (readable and writable) within the source +block that they are defined in. In functional languages, values are only +readable after they have been defined. Though this is a very obvious concept, +it is non-trivial to model in LLVM, because it has no notion of scoping in this +sense, and does not want to be tied to a language's scoping rules. + +In order to handle this, the LLVM debug format uses the metadata attached to +llvm instructions to encode line number and scoping information. Consider the +following C fragment, for example: + +.. code-block:: c + + 1. void foo() { + 2. int X = 21; + 3. int Y = 22; + 4. { + 5. int Z = 23; + 6. Z = X; + 7. } + 8. X = Y; + 9. } + +Compiled to LLVM, this function would be represented like this: + +.. code-block:: llvm + + define void @foo() #0 { + entry: + %X = alloca i32, align 4 + %Y = alloca i32, align 4 + %Z = alloca i32, align 4 + call void @llvm.dbg.declare(metadata !{i32* %X}, metadata !10), !dbg !12 + ; [debug line = 2:7] [debug variable = X] + store i32 21, i32* %X, align 4, !dbg !12 + call void @llvm.dbg.declare(metadata !{i32* %Y}, metadata !13), !dbg !14 + ; [debug line = 3:7] [debug variable = Y] + store i32 22, i32* %Y, align 4, !dbg !14 + call void @llvm.dbg.declare(metadata !{i32* %Z}, metadata !15), !dbg !17 + ; [debug line = 5:9] [debug variable = Z] + store i32 23, i32* %Z, align 4, !dbg !17 + %0 = load i32* %X, align 4, !dbg !18 + [debug line = 6:5] + store i32 %0, i32* %Z, align 4, !dbg !18 + %1 = load i32* %Y, align 4, !dbg !19 + [debug line = 8:3] + store i32 %1, i32* %X, align 4, !dbg !19 + ret void, !dbg !20 + } + + ; Function Attrs: nounwind readnone + declare void @llvm.dbg.declare(metadata, metadata) #1 + + attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" + "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" + "no-infs-fp-math"="false" "no-nans-fp-math"="false" + "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" + "use-soft-float"="false" } + attributes #1 = { nounwind readnone } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!8} + !llvm.ident = !{!9} + + !0 = metadata !{i32 786449, metadata !1, i32 12, + metadata !"clang version 3.4 (trunk 193128) (llvm/trunk 193139)", + i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, + metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] \ + [/private/tmp/foo.c] \ + [DW_LANG_C99] + !1 = metadata !{metadata !"t.c", metadata !"/private/tmp"} + !2 = metadata !{i32 0} + !3 = metadata !{metadata !4} + !4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", + metadata !"foo", metadata !"", i32 1, metadata !6, + i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, + void ()* @foo, null, null, metadata !2, i32 1} + ; [ DW_TAG_subprogram ] [line 1] [def] [foo] + !5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] \ + [/private/tmp/t.c] + !6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, + i64 0, i32 0, null, metadata !7, i32 0, null, null, null} + ; [ DW_TAG_subroutine_type ] \ + [line 0, size 0, align 0, offset 0] [from ] + !7 = metadata !{null} + !8 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} + !9 = metadata !{metadata !"clang version 3.4 (trunk 193128) (llvm/trunk 193139)"} + !10 = metadata !{i32 786688, metadata !4, metadata !"X", metadata !5, i32 2, + metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [X] \ + [line 2] + !11 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, + i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] \ + [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] + !12 = metadata !{i32 2, i32 0, metadata !4, null} + !13 = metadata !{i32 786688, metadata !4, metadata !"Y", metadata !5, i32 3, + metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [Y] \ + [line 3] + !14 = metadata !{i32 3, i32 0, metadata !4, null} + !15 = metadata !{i32 786688, metadata !16, metadata !"Z", metadata !5, i32 5, + metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [Z] \ + [line 5] + !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0} \ + ; [ DW_TAG_lexical_block ] [/private/tmp/t.c] + !17 = metadata !{i32 5, i32 0, metadata !16, null} + !18 = metadata !{i32 6, i32 0, metadata !16, null} + !19 = metadata !{i32 8, i32 0, metadata !4, null} ; [ DW_TAG_imported_declaration ] + !20 = metadata !{i32 9, i32 0, metadata !4, null} + +This example illustrates a few important details about LLVM debugging +information. In particular, it shows how the ``llvm.dbg.declare`` intrinsic and +location information, which are attached to an instruction, are applied +together to allow a debugger to analyze the relationship between statements, +variable definitions, and the code used to implement the function. + +.. code-block:: llvm + + call void @llvm.dbg.declare(metadata !{i32* %X}, metadata !10), !dbg !12 + ; [debug line = 2:7] [debug variable = X] + +The first intrinsic ``%llvm.dbg.declare`` encodes debugging information for the +variable ``X``. The metadata ``!dbg !12`` attached to the intrinsic provides +scope information for the variable ``X``. + +.. code-block:: llvm + + !12 = metadata !{i32 2, i32 0, metadata !4, null} + !4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", + metadata !"foo", metadata !"", i32 1, metadata !6, + i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, + void ()* @foo, null, null, metadata !2, i32 1} + ; [ DW_TAG_subprogram ] [line 1] [def] [foo] + +Here ``!12`` is metadata providing location information. It has four fields: +line number, column number, scope, and original scope. The original scope +represents inline location if this instruction is inlined inside a caller, and +is null otherwise. In this example, scope is encoded by ``!4``, a +:ref:`subprogram descriptor `. This way the location +information attached to the intrinsics indicates that the variable ``X`` is +declared at line number 2 at a function level scope in function ``foo``. + +Now lets take another example. + +.. code-block:: llvm + + call void @llvm.dbg.declare(metadata !{i32* %Z}, metadata !15), !dbg !17 + ; [debug line = 5:9] [debug variable = Z] + +The third intrinsic ``%llvm.dbg.declare`` encodes debugging information for +variable ``Z``. The metadata ``!dbg !17`` attached to the intrinsic provides +scope information for the variable ``Z``. + +.. code-block:: llvm + + !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0} + ; [ DW_TAG_lexical_block ] [/private/tmp/t.c] + !17 = metadata !{i32 5, i32 0, metadata !16, null} + +Here ``!15`` indicates that ``Z`` is declared at line number 5 and +column number 0 inside of lexical scope ``!16``. The lexical scope itself +resides inside of subprogram ``!4`` described above. + +The scope information attached with each instruction provides a straightforward +way to find instructions covered by a scope. + +.. _ccxx_frontend: + +C/C++ front-end specific debug information +========================================== + +The C and C++ front-ends represent information about the program in a format +that is effectively identical to `DWARF 3.0 +`_ in terms of information +content. This allows code generators to trivially support native debuggers by +generating standard dwarf information, and contains enough information for +non-dwarf targets to translate it as needed. + +This section describes the forms used to represent C and C++ programs. Other +languages could pattern themselves after this (which itself is tuned to +representing programs in the same way that DWARF 3 does), or they could choose +to provide completely different forms if they don't fit into the DWARF model. +As support for debugging information gets added to the various LLVM +source-language front-ends, the information used should be documented here. + +The following sections provide examples of various C/C++ constructs and the +debug information that would best describe those constructs. + +C/C++ source file information +----------------------------- + +Given the source files ``MySource.cpp`` and ``MyHeader.h`` located in the +directory ``/Users/mine/sources``, the following code: + +.. code-block:: c + + #include "MyHeader.h" + + int main(int argc, char *argv[]) { + return 0; + } + +a C/C++ front-end would generate the following descriptors: + +.. code-block:: llvm + + ... + ;; + ;; Define the compile unit for the main source file "/Users/mine/sources/MySource.cpp". + ;; + !0 = metadata !{ + i32 786449, ;; Tag + metadata !1, ;; File/directory name + i32 4, ;; Language Id + metadata !"clang version 3.4 ", + i1 false, ;; Optimized compile unit + metadata !"", ;; Compiler flags + i32 0, ;; Runtime version + metadata !2, ;; Enumeration types + metadata !2, ;; Retained types + metadata !3, ;; Subprograms + metadata !2, ;; Global variables + metadata !2, ;; Imported entities (declarations and namespaces) + metadata !"" ;; Split debug filename + } + + ;; + ;; Define the file for the file "/Users/mine/sources/MySource.cpp". + ;; + !1 = metadata !{ + metadata !"MySource.cpp", + metadata !"/Users/mine/sources" + } + !5 = metadata !{ + i32 786473, ;; Tag + metadata !1 + } + + ;; + ;; Define the file for the file "/Users/mine/sources/Myheader.h" + ;; + !14 = metadata !{ + i32 786473, ;; Tag + metadata !15 + } + !15 = metadata !{ + metadata !"./MyHeader.h", + metadata !"/Users/mine/sources", + } + + ... + +``llvm::Instruction`` provides easy access to metadata attached with an +instruction. One can extract line number information encoded in LLVM IR using +``Instruction::getMetadata()`` and ``DILocation::getLineNumber()``. + +.. code-block:: c++ + + if (MDNode *N = I->getMetadata("dbg")) { // Here I is an LLVM instruction + DILocation Loc(N); // DILocation is in DebugInfo.h + unsigned Line = Loc.getLineNumber(); + StringRef File = Loc.getFilename(); + StringRef Dir = Loc.getDirectory(); + } + +C/C++ global variable information +--------------------------------- + +Given an integer global variable declared as follows: + +.. code-block:: c + + int MyGlobal = 100; + +a C/C++ front-end would generate the following descriptors: + +.. code-block:: llvm + + ;; + ;; Define the global itself. + ;; + %MyGlobal = global int 100 + ... + ;; + ;; List of debug info of globals + ;; + !llvm.dbg.cu = !{!0} + + ;; Define the compile unit. + !0 = metadata !{ + i32 786449, ;; Tag + i32 0, ;; Context + i32 4, ;; Language + metadata !"foo.cpp", ;; File + metadata !"/Volumes/Data/tmp", ;; Directory + metadata !"clang version 3.1 ", ;; Producer + i1 true, ;; Deprecated field + i1 false, ;; "isOptimized"? + metadata !"", ;; Flags + i32 0, ;; Runtime Version + metadata !1, ;; Enum Types + metadata !1, ;; Retained Types + metadata !1, ;; Subprograms + metadata !3, ;; Global Variables + metadata !1, ;; Imported entities + "", ;; Split debug filename + } ; [ DW_TAG_compile_unit ] + + ;; The Array of Global Variables + !3 = metadata !{ + metadata !4 + } + + ;; + ;; Define the global variable itself. + ;; + !4 = metadata !{ + i32 786484, ;; Tag + i32 0, ;; Unused + null, ;; Unused + metadata !"MyGlobal", ;; Name + metadata !"MyGlobal", ;; Display Name + metadata !"", ;; Linkage Name + metadata !6, ;; File + i32 1, ;; Line + metadata !7, ;; Type + i32 0, ;; IsLocalToUnit + i32 1, ;; IsDefinition + i32* @MyGlobal, ;; LLVM-IR Value + null ;; Static member declaration + } ; [ DW_TAG_variable ] + + ;; + ;; Define the file + ;; + !5 = metadata !{ + metadata !"foo.cpp", ;; File + metadata !"/Volumes/Data/tmp", ;; Directory + } + !6 = metadata !{ + i32 786473, ;; Tag + metadata !5 ;; Unused + } ; [ DW_TAG_file_type ] + + ;; + ;; Define the type + ;; + !7 = metadata !{ + i32 786468, ;; Tag + null, ;; Unused + null, ;; Unused + metadata !"int", ;; Name + i32 0, ;; Line + i64 32, ;; Size in Bits + i64 32, ;; Align in Bits + i64 0, ;; Offset + i32 0, ;; Flags + i32 5 ;; Encoding + } ; [ DW_TAG_base_type ] + +C/C++ function information +-------------------------- + +Given a function declared as follows: + +.. code-block:: c + + int main(int argc, char *argv[]) { + return 0; + } + +a C/C++ front-end would generate the following descriptors: + +.. code-block:: llvm + + ;; + ;; Define the anchor for subprograms. + ;; + !6 = metadata !{ + i32 786484, ;; Tag + metadata !1, ;; File + metadata !1, ;; Context + metadata !"main", ;; Name + metadata !"main", ;; Display name + metadata !"main", ;; Linkage name + i32 1, ;; Line number + metadata !4, ;; Type + i1 false, ;; Is local + i1 true, ;; Is definition + i32 0, ;; Virtuality attribute, e.g. pure virtual function + i32 0, ;; Index into virtual table for C++ methods + i32 0, ;; Type that holds virtual table. + i32 0, ;; Flags + i1 false, ;; True if this function is optimized + Function *, ;; Pointer to llvm::Function + null, ;; Function template parameters + null, ;; List of function variables (emitted when optimizing) + 1 ;; Line number of the opening '{' of the function + } + ;; + ;; Define the subprogram itself. + ;; + define i32 @main(i32 %argc, i8** %argv) { + ... + } + +C/C++ basic types +----------------- + +The following are the basic type descriptors for C/C++ core types: + +bool +^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"bool", ;; Name + i32 0, ;; Line number + i64 8, ;; Size in Bits + i64 8, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 2 ;; Encoding + } + +char +^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"char", ;; Name + i32 0, ;; Line number + i64 8, ;; Size in Bits + i64 8, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 6 ;; Encoding + } + +unsigned char +^^^^^^^^^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"unsigned char", + i32 0, ;; Line number + i64 8, ;; Size in Bits + i64 8, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 8 ;; Encoding + } + +short +^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"short int", + i32 0, ;; Line number + i64 16, ;; Size in Bits + i64 16, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 5 ;; Encoding + } + +unsigned short +^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"short unsigned int", + i32 0, ;; Line number + i64 16, ;; Size in Bits + i64 16, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 7 ;; Encoding + } + +int +^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"int", ;; Name + i32 0, ;; Line number + i64 32, ;; Size in Bits + i64 32, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 5 ;; Encoding + } + +unsigned int +^^^^^^^^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"unsigned int", + i32 0, ;; Line number + i64 32, ;; Size in Bits + i64 32, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 7 ;; Encoding + } + +long long +^^^^^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"long long int", + i32 0, ;; Line number + i64 64, ;; Size in Bits + i64 64, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 5 ;; Encoding + } + +unsigned long long +^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"long long unsigned int", + i32 0, ;; Line number + i64 64, ;; Size in Bits + i64 64, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 7 ;; Encoding + } + +float +^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"float", + i32 0, ;; Line number + i64 32, ;; Size in Bits + i64 32, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 4 ;; Encoding + } + +double +^^^^^^ + +.. code-block:: llvm + + !2 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"double",;; Name + i32 0, ;; Line number + i64 64, ;; Size in Bits + i64 64, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 4 ;; Encoding + } + +C/C++ derived types +------------------- + +Given the following as an example of C/C++ derived type: + +.. code-block:: c + + typedef const int *IntPtr; + +a C/C++ front-end would generate the following descriptors: + +.. code-block:: llvm + + ;; + ;; Define the typedef "IntPtr". + ;; + !2 = metadata !{ + i32 786454, ;; Tag + metadata !3, ;; File + metadata !1, ;; Context + metadata !"IntPtr", ;; Name + i32 0, ;; Line number + i64 0, ;; Size in bits + i64 0, ;; Align in bits + i64 0, ;; Offset in bits + i32 0, ;; Flags + metadata !4 ;; Derived From type + } + ;; + ;; Define the pointer type. + ;; + !4 = metadata !{ + i32 786447, ;; Tag + null, ;; File + null, ;; Context + metadata !"", ;; Name + i32 0, ;; Line number + i64 64, ;; Size in bits + i64 64, ;; Align in bits + i64 0, ;; Offset in bits + i32 0, ;; Flags + metadata !5 ;; Derived From type + } + ;; + ;; Define the const type. + ;; + !5 = metadata !{ + i32 786470, ;; Tag + null, ;; File + null, ;; Context + metadata !"", ;; Name + i32 0, ;; Line number + i64 0, ;; Size in bits + i64 0, ;; Align in bits + i64 0, ;; Offset in bits + i32 0, ;; Flags + metadata !6 ;; Derived From type + } + ;; + ;; Define the int type. + ;; + !6 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"int", ;; Name + i32 0, ;; Line number + i64 32, ;; Size in bits + i64 32, ;; Align in bits + i64 0, ;; Offset in bits + i32 0, ;; Flags + i32 5 ;; Encoding + } + +C/C++ struct/union types +------------------------ + +Given the following as an example of C/C++ struct type: + +.. code-block:: c + + struct Color { + unsigned Red; + unsigned Green; + unsigned Blue; + }; + +a C/C++ front-end would generate the following descriptors: + +.. code-block:: llvm + + ;; + ;; Define basic type for unsigned int. + ;; + !5 = metadata !{ + i32 786468, ;; Tag + null, ;; File + null, ;; Context + metadata !"unsigned int", + i32 0, ;; Line number + i64 32, ;; Size in Bits + i64 32, ;; Align in Bits + i64 0, ;; Offset in Bits + i32 0, ;; Flags + i32 7 ;; Encoding + } + ;; + ;; Define composite type for struct Color. + ;; + !2 = metadata !{ + i32 786451, ;; Tag + metadata !1, ;; Compile unit + null, ;; Context + metadata !"Color", ;; Name + i32 1, ;; Line number + i64 96, ;; Size in bits + i64 32, ;; Align in bits + i64 0, ;; Offset in bits + i32 0, ;; Flags + null, ;; Derived From + metadata !3, ;; Elements + i32 0, ;; Runtime Language + null, ;; Base type containing the vtable pointer for this type + null ;; Template parameters + } + + ;; + ;; Define the Red field. + ;; + !4 = metadata !{ + i32 786445, ;; Tag + metadata !1, ;; File + metadata !1, ;; Context + metadata !"Red", ;; Name + i32 2, ;; Line number + i64 32, ;; Size in bits + i64 32, ;; Align in bits + i64 0, ;; Offset in bits + i32 0, ;; Flags + metadata !5 ;; Derived From type + } + + ;; + ;; Define the Green field. + ;; + !6 = metadata !{ + i32 786445, ;; Tag + metadata !1, ;; File + metadata !1, ;; Context + metadata !"Green", ;; Name + i32 3, ;; Line number + i64 32, ;; Size in bits + i64 32, ;; Align in bits + i64 32, ;; Offset in bits + i32 0, ;; Flags + metadata !5 ;; Derived From type + } + + ;; + ;; Define the Blue field. + ;; + !7 = metadata !{ + i32 786445, ;; Tag + metadata !1, ;; File + metadata !1, ;; Context + metadata !"Blue", ;; Name + i32 4, ;; Line number + i64 32, ;; Size in bits + i64 32, ;; Align in bits + i64 64, ;; Offset in bits + i32 0, ;; Flags + metadata !5 ;; Derived From type + } + + ;; + ;; Define the array of fields used by the composite type Color. + ;; + !3 = metadata !{metadata !4, metadata !6, metadata !7} + +C/C++ enumeration types +----------------------- + +Given the following as an example of C/C++ enumeration type: + +.. code-block:: c + + enum Trees { + Spruce = 100, + Oak = 200, + Maple = 300 + }; + +a C/C++ front-end would generate the following descriptors: + +.. code-block:: llvm + + ;; + ;; Define composite type for enum Trees + ;; + !2 = metadata !{ + i32 786436, ;; Tag + metadata !1, ;; File + metadata !1, ;; Context + metadata !"Trees", ;; Name + i32 1, ;; Line number + i64 32, ;; Size in bits + i64 32, ;; Align in bits + i64 0, ;; Offset in bits + i32 0, ;; Flags + null, ;; Derived From type + metadata !3, ;; Elements + i32 0 ;; Runtime language + } + + ;; + ;; Define the array of enumerators used by composite type Trees. + ;; + !3 = metadata !{metadata !4, metadata !5, metadata !6} + + ;; + ;; Define Spruce enumerator. + ;; + !4 = metadata !{i32 786472, metadata !"Spruce", i64 100} + + ;; + ;; Define Oak enumerator. + ;; + !5 = metadata !{i32 786472, metadata !"Oak", i64 200} + + ;; + ;; Define Maple enumerator. + ;; + !6 = metadata !{i32 786472, metadata !"Maple", i64 300} + +Debugging information format +============================ + +Debugging Information Extension for Objective C Properties +---------------------------------------------------------- + +Introduction +^^^^^^^^^^^^ + +Objective C provides a simpler way to declare and define accessor methods using +declared properties. The language provides features to declare a property and +to let compiler synthesize accessor methods. + +The debugger lets developer inspect Objective C interfaces and their instance +variables and class variables. However, the debugger does not know anything +about the properties defined in Objective C interfaces. The debugger consumes +information generated by compiler in DWARF format. The format does not support +encoding of Objective C properties. This proposal describes DWARF extensions to +encode Objective C properties, which the debugger can use to let developers +inspect Objective C properties. + +Proposal +^^^^^^^^ + +Objective C properties exist separately from class members. A property can be +defined only by "setter" and "getter" selectors, and be calculated anew on each +access. Or a property can just be a direct access to some declared ivar. +Finally it can have an ivar "automatically synthesized" for it by the compiler, +in which case the property can be referred to in user code directly using the +standard C dereference syntax as well as through the property "dot" syntax, but +there is no entry in the ``@interface`` declaration corresponding to this ivar. + +To facilitate debugging, these properties we will add a new DWARF TAG into the +``DW_TAG_structure_type`` definition for the class to hold the description of a +given property, and a set of DWARF attributes that provide said description. +The property tag will also contain the name and declared type of the property. + +If there is a related ivar, there will also be a DWARF property attribute placed +in the ``DW_TAG_member`` DIE for that ivar referring back to the property TAG +for that property. And in the case where the compiler synthesizes the ivar +directly, the compiler is expected to generate a ``DW_TAG_member`` for that +ivar (with the ``DW_AT_artificial`` set to 1), whose name will be the name used +to access this ivar directly in code, and with the property attribute pointing +back to the property it is backing. + +The following examples will serve as illustration for our discussion: + +.. code-block:: objc + + @interface I1 { + int n2; + } + + @property int p1; + @property int p2; + @end + + @implementation I1 + @synthesize p1; + @synthesize p2 = n2; + @end + +This produces the following DWARF (this is a "pseudo dwarfdump" output): + +.. code-block:: none + + 0x00000100: TAG_structure_type [7] * + AT_APPLE_runtime_class( 0x10 ) + AT_name( "I1" ) + AT_decl_file( "Objc_Property.m" ) + AT_decl_line( 3 ) + + 0x00000110 TAG_APPLE_property + AT_name ( "p1" ) + AT_type ( {0x00000150} ( int ) ) + + 0x00000120: TAG_APPLE_property + AT_name ( "p2" ) + AT_type ( {0x00000150} ( int ) ) + + 0x00000130: TAG_member [8] + AT_name( "_p1" ) + AT_APPLE_property ( {0x00000110} "p1" ) + AT_type( {0x00000150} ( int ) ) + AT_artificial ( 0x1 ) + + 0x00000140: TAG_member [8] + AT_name( "n2" ) + AT_APPLE_property ( {0x00000120} "p2" ) + AT_type( {0x00000150} ( int ) ) + + 0x00000150: AT_type( ( int ) ) + +Note, the current convention is that the name of the ivar for an +auto-synthesized property is the name of the property from which it derives +with an underscore prepended, as is shown in the example. But we actually +don't need to know this convention, since we are given the name of the ivar +directly. + +Also, it is common practice in ObjC to have different property declarations in +the @interface and @implementation - e.g. to provide a read-only property in +the interface,and a read-write interface in the implementation. In that case, +the compiler should emit whichever property declaration will be in force in the +current translation unit. + +Developers can decorate a property with attributes which are encoded using +``DW_AT_APPLE_property_attribute``. + +.. code-block:: objc + + @property (readonly, nonatomic) int pr; + +.. code-block:: none + + TAG_APPLE_property [8] + AT_name( "pr" ) + AT_type ( {0x00000147} (int) ) + AT_APPLE_property_attribute (DW_APPLE_PROPERTY_readonly, DW_APPLE_PROPERTY_nonatomic) + +The setter and getter method names are attached to the property using +``DW_AT_APPLE_property_setter`` and ``DW_AT_APPLE_property_getter`` attributes. + +.. code-block:: objc + + @interface I1 + @property (setter=myOwnP3Setter:) int p3; + -(void)myOwnP3Setter:(int)a; + @end + + @implementation I1 + @synthesize p3; + -(void)myOwnP3Setter:(int)a{ } + @end + +The DWARF for this would be: + +.. code-block:: none + + 0x000003bd: TAG_structure_type [7] * + AT_APPLE_runtime_class( 0x10 ) + AT_name( "I1" ) + AT_decl_file( "Objc_Property.m" ) + AT_decl_line( 3 ) + + 0x000003cd TAG_APPLE_property + AT_name ( "p3" ) + AT_APPLE_property_setter ( "myOwnP3Setter:" ) + AT_type( {0x00000147} ( int ) ) + + 0x000003f3: TAG_member [8] + AT_name( "_p3" ) + AT_type ( {0x00000147} ( int ) ) + AT_APPLE_property ( {0x000003cd} ) + AT_artificial ( 0x1 ) + +New DWARF Tags +^^^^^^^^^^^^^^ + ++-----------------------+--------+ +| TAG | Value | ++=======================+========+ +| DW_TAG_APPLE_property | 0x4200 | ++-----------------------+--------+ + +New DWARF Attributes +^^^^^^^^^^^^^^^^^^^^ + ++--------------------------------+--------+-----------+ +| Attribute | Value | Classes | ++================================+========+===========+ +| DW_AT_APPLE_property | 0x3fed | Reference | ++--------------------------------+--------+-----------+ +| DW_AT_APPLE_property_getter | 0x3fe9 | String | ++--------------------------------+--------+-----------+ +| DW_AT_APPLE_property_setter | 0x3fea | String | ++--------------------------------+--------+-----------+ +| DW_AT_APPLE_property_attribute | 0x3feb | Constant | ++--------------------------------+--------+-----------+ + +New DWARF Constants +^^^^^^^^^^^^^^^^^^^ + ++--------------------------------+-------+ +| Name | Value | ++================================+=======+ +| DW_AT_APPLE_PROPERTY_readonly | 0x1 | ++--------------------------------+-------+ +| DW_AT_APPLE_PROPERTY_readwrite | 0x2 | ++--------------------------------+-------+ +| DW_AT_APPLE_PROPERTY_assign | 0x4 | ++--------------------------------+-------+ +| DW_AT_APPLE_PROPERTY_retain | 0x8 | ++--------------------------------+-------+ +| DW_AT_APPLE_PROPERTY_copy | 0x10 | ++--------------------------------+-------+ +| DW_AT_APPLE_PROPERTY_nonatomic | 0x20 | ++--------------------------------+-------+ + +Name Accelerator Tables +----------------------- + +Introduction +^^^^^^^^^^^^ + +The "``.debug_pubnames``" and "``.debug_pubtypes``" formats are not what a +debugger needs. The "``pub``" in the section name indicates that the entries +in the table are publicly visible names only. This means no static or hidden +functions show up in the "``.debug_pubnames``". No static variables or private +class variables are in the "``.debug_pubtypes``". Many compilers add different +things to these tables, so we can't rely upon the contents between gcc, icc, or +clang. + +The typical query given by users tends not to match up with the contents of +these tables. For example, the DWARF spec states that "In the case of the name +of a function member or static data member of a C++ structure, class or union, +the name presented in the "``.debug_pubnames``" section is not the simple name +given by the ``DW_AT_name attribute`` of the referenced debugging information +entry, but rather the fully qualified name of the data or function member." +So the only names in these tables for complex C++ entries is a fully +qualified name. Debugger users tend not to enter their search strings as +"``a::b::c(int,const Foo&) const``", but rather as "``c``", "``b::c``" , or +"``a::b::c``". So the name entered in the name table must be demangled in +order to chop it up appropriately and additional names must be manually entered +into the table to make it effective as a name lookup table for debuggers to +se. + +All debuggers currently ignore the "``.debug_pubnames``" table as a result of +its inconsistent and useless public-only name content making it a waste of +space in the object file. These tables, when they are written to disk, are not +sorted in any way, leaving every debugger to do its own parsing and sorting. +These tables also include an inlined copy of the string values in the table +itself making the tables much larger than they need to be on disk, especially +for large C++ programs. + +Can't we just fix the sections by adding all of the names we need to this +table? No, because that is not what the tables are defined to contain and we +won't know the difference between the old bad tables and the new good tables. +At best we could make our own renamed sections that contain all of the data we +need. + +These tables are also insufficient for what a debugger like LLDB needs. LLDB +uses clang for its expression parsing where LLDB acts as a PCH. LLDB is then +often asked to look for type "``foo``" or namespace "``bar``", or list items in +namespace "``baz``". Namespaces are not included in the pubnames or pubtypes +tables. Since clang asks a lot of questions when it is parsing an expression, +we need to be very fast when looking up names, as it happens a lot. Having new +accelerator tables that are optimized for very quick lookups will benefit this +type of debugging experience greatly. + +We would like to generate name lookup tables that can be mapped into memory +from disk, and used as is, with little or no up-front parsing. We would also +be able to control the exact content of these different tables so they contain +exactly what we need. The Name Accelerator Tables were designed to fix these +issues. In order to solve these issues we need to: + +* Have a format that can be mapped into memory from disk and used as is +* Lookups should be very fast +* Extensible table format so these tables can be made by many producers +* Contain all of the names needed for typical lookups out of the box +* Strict rules for the contents of tables + +Table size is important and the accelerator table format should allow the reuse +of strings from common string tables so the strings for the names are not +duplicated. We also want to make sure the table is ready to be used as-is by +simply mapping the table into memory with minimal header parsing. + +The name lookups need to be fast and optimized for the kinds of lookups that +debuggers tend to do. Optimally we would like to touch as few parts of the +mapped table as possible when doing a name lookup and be able to quickly find +the name entry we are looking for, or discover there are no matches. In the +case of debuggers we optimized for lookups that fail most of the time. + +Each table that is defined should have strict rules on exactly what is in the +accelerator tables and documented so clients can rely on the content. + +Hash Tables +^^^^^^^^^^^ + +Standard Hash Tables +"""""""""""""""""""" + +Typical hash tables have a header, buckets, and each bucket points to the +bucket contents: + +.. code-block:: none + + .------------. + | HEADER | + |------------| + | BUCKETS | + |------------| + | DATA | + `------------' + +The BUCKETS are an array of offsets to DATA for each hash: + +.. code-block:: none + + .------------. + | 0x00001000 | BUCKETS[0] + | 0x00002000 | BUCKETS[1] + | 0x00002200 | BUCKETS[2] + | 0x000034f0 | BUCKETS[3] + | | ... + | 0xXXXXXXXX | BUCKETS[n_buckets] + '------------' + +So for ``bucket[3]`` in the example above, we have an offset into the table +0x000034f0 which points to a chain of entries for the bucket. Each bucket must +contain a next pointer, full 32 bit hash value, the string itself, and the data +for the current string value. + +.. code-block:: none + + .------------. + 0x000034f0: | 0x00003500 | next pointer + | 0x12345678 | 32 bit hash + | "erase" | string value + | data[n] | HashData for this bucket + |------------| + 0x00003500: | 0x00003550 | next pointer + | 0x29273623 | 32 bit hash + | "dump" | string value + | data[n] | HashData for this bucket + |------------| + 0x00003550: | 0x00000000 | next pointer + | 0x82638293 | 32 bit hash + | "main" | string value + | data[n] | HashData for this bucket + `------------' + +The problem with this layout for debuggers is that we need to optimize for the +negative lookup case where the symbol we're searching for is not present. So +if we were to lookup "``printf``" in the table above, we would make a 32 hash +for "``printf``", it might match ``bucket[3]``. We would need to go to the +offset 0x000034f0 and start looking to see if our 32 bit hash matches. To do +so, we need to read the next pointer, then read the hash, compare it, and skip +to the next bucket. Each time we are skipping many bytes in memory and +touching new cache pages just to do the compare on the full 32 bit hash. All +of these accesses then tell us that we didn't have a match. + +Name Hash Tables +"""""""""""""""" + +To solve the issues mentioned above we have structured the hash tables a bit +differently: a header, buckets, an array of all unique 32 bit hash values, +followed by an array of hash value data offsets, one for each hash value, then +the data for all hash values: + +.. code-block:: none + + .-------------. + | HEADER | + |-------------| + | BUCKETS | + |-------------| + | HASHES | + |-------------| + | OFFSETS | + |-------------| + | DATA | + `-------------' + +The ``BUCKETS`` in the name tables are an index into the ``HASHES`` array. By +making all of the full 32 bit hash values contiguous in memory, we allow +ourselves to efficiently check for a match while touching as little memory as +possible. Most often checking the 32 bit hash values is as far as the lookup +goes. If it does match, it usually is a match with no collisions. So for a +table with "``n_buckets``" buckets, and "``n_hashes``" unique 32 bit hash +values, we can clarify the contents of the ``BUCKETS``, ``HASHES`` and +``OFFSETS`` as: + +.. code-block:: none + + .-------------------------. + | HEADER.magic | uint32_t + | HEADER.version | uint16_t + | HEADER.hash_function | uint16_t + | HEADER.bucket_count | uint32_t + | HEADER.hashes_count | uint32_t + | HEADER.header_data_len | uint32_t + | HEADER_DATA | HeaderData + |-------------------------| + | BUCKETS | uint32_t[n_buckets] // 32 bit hash indexes + |-------------------------| + | HASHES | uint32_t[n_hashes] // 32 bit hash values + |-------------------------| + | OFFSETS | uint32_t[n_hashes] // 32 bit offsets to hash value data + |-------------------------| + | ALL HASH DATA | + `-------------------------' + +So taking the exact same data from the standard hash example above we end up +with: + +.. code-block:: none + + .------------. + | HEADER | + |------------| + | 0 | BUCKETS[0] + | 2 | BUCKETS[1] + | 5 | BUCKETS[2] + | 6 | BUCKETS[3] + | | ... + | ... | BUCKETS[n_buckets] + |------------| + | 0x........ | HASHES[0] + | 0x........ | HASHES[1] + | 0x........ | HASHES[2] + | 0x........ | HASHES[3] + | 0x........ | HASHES[4] + | 0x........ | HASHES[5] + | 0x12345678 | HASHES[6] hash for BUCKETS[3] + | 0x29273623 | HASHES[7] hash for BUCKETS[3] + | 0x82638293 | HASHES[8] hash for BUCKETS[3] + | 0x........ | HASHES[9] + | 0x........ | HASHES[10] + | 0x........ | HASHES[11] + | 0x........ | HASHES[12] + | 0x........ | HASHES[13] + | 0x........ | HASHES[n_hashes] + |------------| + | 0x........ | OFFSETS[0] + | 0x........ | OFFSETS[1] + | 0x........ | OFFSETS[2] + | 0x........ | OFFSETS[3] + | 0x........ | OFFSETS[4] + | 0x........ | OFFSETS[5] + | 0x000034f0 | OFFSETS[6] offset for BUCKETS[3] + | 0x00003500 | OFFSETS[7] offset for BUCKETS[3] + | 0x00003550 | OFFSETS[8] offset for BUCKETS[3] + | 0x........ | OFFSETS[9] + | 0x........ | OFFSETS[10] + | 0x........ | OFFSETS[11] + | 0x........ | OFFSETS[12] + | 0x........ | OFFSETS[13] + | 0x........ | OFFSETS[n_hashes] + |------------| + | | + | | + | | + | | + | | + |------------| + 0x000034f0: | 0x00001203 | .debug_str ("erase") + | 0x00000004 | A 32 bit array count - number of HashData with name "erase" + | 0x........ | HashData[0] + | 0x........ | HashData[1] + | 0x........ | HashData[2] + | 0x........ | HashData[3] + | 0x00000000 | String offset into .debug_str (terminate data for hash) + |------------| + 0x00003500: | 0x00001203 | String offset into .debug_str ("collision") + | 0x00000002 | A 32 bit array count - number of HashData with name "collision" + | 0x........ | HashData[0] + | 0x........ | HashData[1] + | 0x00001203 | String offset into .debug_str ("dump") + | 0x00000003 | A 32 bit array count - number of HashData with name "dump" + | 0x........ | HashData[0] + | 0x........ | HashData[1] + | 0x........ | HashData[2] + | 0x00000000 | String offset into .debug_str (terminate data for hash) + |------------| + 0x00003550: | 0x00001203 | String offset into .debug_str ("main") + | 0x00000009 | A 32 bit array count - number of HashData with name "main" + | 0x........ | HashData[0] + | 0x........ | HashData[1] + | 0x........ | HashData[2] + | 0x........ | HashData[3] + | 0x........ | HashData[4] + | 0x........ | HashData[5] + | 0x........ | HashData[6] + | 0x........ | HashData[7] + | 0x........ | HashData[8] + | 0x00000000 | String offset into .debug_str (terminate data for hash) + `------------' + +So we still have all of the same data, we just organize it more efficiently for +debugger lookup. If we repeat the same "``printf``" lookup from above, we +would hash "``printf``" and find it matches ``BUCKETS[3]`` by taking the 32 bit +hash value and modulo it by ``n_buckets``. ``BUCKETS[3]`` contains "6" which +is the index into the ``HASHES`` table. We would then compare any consecutive +32 bit hashes values in the ``HASHES`` array as long as the hashes would be in +``BUCKETS[3]``. We do this by verifying that each subsequent hash value modulo +``n_buckets`` is still 3. In the case of a failed lookup we would access the +memory for ``BUCKETS[3]``, and then compare a few consecutive 32 bit hashes +before we know that we have no match. We don't end up marching through +multiple words of memory and we really keep the number of processor data cache +lines being accessed as small as possible. + +The string hash that is used for these lookup tables is the Daniel J. +Bernstein hash which is also used in the ELF ``GNU_HASH`` sections. It is a +very good hash for all kinds of names in programs with very few hash +collisions. + +Empty buckets are designated by using an invalid hash index of ``UINT32_MAX``. + +Details +^^^^^^^ + +These name hash tables are designed to be generic where specializations of the +table get to define additional data that goes into the header ("``HeaderData``"), +how the string value is stored ("``KeyType``") and the content of the data for each +hash value. + +Header Layout +""""""""""""" + +The header has a fixed part, and the specialized part. The exact format of the +header is: + +.. code-block:: c + + struct Header + { + uint32_t magic; // 'HASH' magic value to allow endian detection + uint16_t version; // Version number + uint16_t hash_function; // The hash function enumeration that was used + uint32_t bucket_count; // The number of buckets in this hash table + uint32_t hashes_count; // The total number of unique hash values and hash data offsets in this table + uint32_t header_data_len; // The bytes to skip to get to the hash indexes (buckets) for correct alignment + // Specifically the length of the following HeaderData field - this does not + // include the size of the preceding fields + HeaderData header_data; // Implementation specific header data + }; + +The header starts with a 32 bit "``magic``" value which must be ``'HASH'`` +encoded as an ASCII integer. This allows the detection of the start of the +hash table and also allows the table's byte order to be determined so the table +can be correctly extracted. The "``magic``" value is followed by a 16 bit +``version`` number which allows the table to be revised and modified in the +future. The current version number is 1. ``hash_function`` is a ``uint16_t`` +enumeration that specifies which hash function was used to produce this table. +The current values for the hash function enumerations include: + +.. code-block:: c + + enum HashFunctionType + { + eHashFunctionDJB = 0u, // Daniel J Bernstein hash function + }; + +``bucket_count`` is a 32 bit unsigned integer that represents how many buckets +are in the ``BUCKETS`` array. ``hashes_count`` is the number of unique 32 bit +hash values that are in the ``HASHES`` array, and is the same number of offsets +are contained in the ``OFFSETS`` array. ``header_data_len`` specifies the size +in bytes of the ``HeaderData`` that is filled in by specialized versions of +this table. + +Fixed Lookup +"""""""""""" + +The header is followed by the buckets, hashes, offsets, and hash value data. + +.. code-block:: c + + struct FixedTable + { + uint32_t buckets[Header.bucket_count]; // An array of hash indexes into the "hashes[]" array below + uint32_t hashes [Header.hashes_count]; // Every unique 32 bit hash for the entire table is in this table + uint32_t offsets[Header.hashes_count]; // An offset that corresponds to each item in the "hashes[]" array above + }; + +``buckets`` is an array of 32 bit indexes into the ``hashes`` array. The +``hashes`` array contains all of the 32 bit hash values for all names in the +hash table. Each hash in the ``hashes`` table has an offset in the ``offsets`` +array that points to the data for the hash value. + +This table setup makes it very easy to repurpose these tables to contain +different data, while keeping the lookup mechanism the same for all tables. +This layout also makes it possible to save the table to disk and map it in +later and do very efficient name lookups with little or no parsing. + +DWARF lookup tables can be implemented in a variety of ways and can store a lot +of information for each name. We want to make the DWARF tables extensible and +able to store the data efficiently so we have used some of the DWARF features +that enable efficient data storage to define exactly what kind of data we store +for each name. + +The ``HeaderData`` contains a definition of the contents of each HashData chunk. +We might want to store an offset to all of the debug information entries (DIEs) +for each name. To keep things extensible, we create a list of items, or +Atoms, that are contained in the data for each name. First comes the type of +the data in each atom: + +.. code-block:: c + + enum AtomType + { + eAtomTypeNULL = 0u, + eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding + eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question + eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 + eAtomTypeNameFlags = 4u, // Flags from enum NameFlags + eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags + }; + +The enumeration values and their meanings are: + +.. code-block:: none + + eAtomTypeNULL - a termination atom that specifies the end of the atom list + eAtomTypeDIEOffset - an offset into the .debug_info section for the DWARF DIE for this name + eAtomTypeCUOffset - an offset into the .debug_info section for the CU that contains the DIE + eAtomTypeDIETag - The DW_TAG_XXX enumeration value so you don't have to parse the DWARF to see what it is + eAtomTypeNameFlags - Flags for functions and global variables (isFunction, isInlined, isExternal...) + eAtomTypeTypeFlags - Flags for types (isCXXClass, isObjCClass, ...) + +Then we allow each atom type to define the atom type and how the data for each +atom type data is encoded: + +.. code-block:: c + + struct Atom + { + uint16_t type; // AtomType enum value + uint16_t form; // DWARF DW_FORM_XXX defines + }; + +The ``form`` type above is from the DWARF specification and defines the exact +encoding of the data for the Atom type. See the DWARF specification for the +``DW_FORM_`` definitions. + +.. code-block:: c + + struct HeaderData + { + uint32_t die_offset_base; + uint32_t atom_count; + Atoms atoms[atom_count0]; + }; + +``HeaderData`` defines the base DIE offset that should be added to any atoms +that are encoded using the ``DW_FORM_ref1``, ``DW_FORM_ref2``, +``DW_FORM_ref4``, ``DW_FORM_ref8`` or ``DW_FORM_ref_udata``. It also defines +what is contained in each ``HashData`` object -- ``Atom.form`` tells us how large +each field will be in the ``HashData`` and the ``Atom.type`` tells us how this data +should be interpreted. + +For the current implementations of the "``.apple_names``" (all functions + +globals), the "``.apple_types``" (names of all types that are defined), and +the "``.apple_namespaces``" (all namespaces), we currently set the ``Atom`` +array to be: + +.. code-block:: c + + HeaderData.atom_count = 1; + HeaderData.atoms[0].type = eAtomTypeDIEOffset; + HeaderData.atoms[0].form = DW_FORM_data4; + +This defines the contents to be the DIE offset (eAtomTypeDIEOffset) that is +encoded as a 32 bit value (DW_FORM_data4). This allows a single name to have +multiple matching DIEs in a single file, which could come up with an inlined +function for instance. Future tables could include more information about the +DIE such as flags indicating if the DIE is a function, method, block, +or inlined. + +The KeyType for the DWARF table is a 32 bit string table offset into the +".debug_str" table. The ".debug_str" is the string table for the DWARF which +may already contain copies of all of the strings. This helps make sure, with +help from the compiler, that we reuse the strings between all of the DWARF +sections and keeps the hash table size down. Another benefit to having the +compiler generate all strings as DW_FORM_strp in the debug info, is that +DWARF parsing can be made much faster. + +After a lookup is made, we get an offset into the hash data. The hash data +needs to be able to deal with 32 bit hash collisions, so the chunk of data +at the offset in the hash data consists of a triple: + +.. code-block:: c + + uint32_t str_offset + uint32_t hash_data_count + HashData[hash_data_count] + +If "str_offset" is zero, then the bucket contents are done. 99.9% of the +hash data chunks contain a single item (no 32 bit hash collision): + +.. code-block:: none + + .------------. + | 0x00001023 | uint32_t KeyType (.debug_str[0x0001023] => "main") + | 0x00000004 | uint32_t HashData count + | 0x........ | uint32_t HashData[0] DIE offset + | 0x........ | uint32_t HashData[1] DIE offset + | 0x........ | uint32_t HashData[2] DIE offset + | 0x........ | uint32_t HashData[3] DIE offset + | 0x00000000 | uint32_t KeyType (end of hash chain) + `------------' + +If there are collisions, you will have multiple valid string offsets: + +.. code-block:: none + + .------------. + | 0x00001023 | uint32_t KeyType (.debug_str[0x0001023] => "main") + | 0x00000004 | uint32_t HashData count + | 0x........ | uint32_t HashData[0] DIE offset + | 0x........ | uint32_t HashData[1] DIE offset + | 0x........ | uint32_t HashData[2] DIE offset + | 0x........ | uint32_t HashData[3] DIE offset + | 0x00002023 | uint32_t KeyType (.debug_str[0x0002023] => "print") + | 0x00000002 | uint32_t HashData count + | 0x........ | uint32_t HashData[0] DIE offset + | 0x........ | uint32_t HashData[1] DIE offset + | 0x00000000 | uint32_t KeyType (end of hash chain) + `------------' + +Current testing with real world C++ binaries has shown that there is around 1 +32 bit hash collision per 100,000 name entries. + +Contents +^^^^^^^^ + +As we said, we want to strictly define exactly what is included in the +different tables. For DWARF, we have 3 tables: "``.apple_names``", +"``.apple_types``", and "``.apple_namespaces``". + +"``.apple_names``" sections should contain an entry for each DWARF DIE whose +``DW_TAG`` is a ``DW_TAG_label``, ``DW_TAG_inlined_subroutine``, or +``DW_TAG_subprogram`` that has address attributes: ``DW_AT_low_pc``, +``DW_AT_high_pc``, ``DW_AT_ranges`` or ``DW_AT_entry_pc``. It also contains +``DW_TAG_variable`` DIEs that have a ``DW_OP_addr`` in the location (global and +static variables). All global and static variables should be included, +including those scoped within functions and classes. For example using the +following code: + +.. code-block:: c + + static int var = 0; + + void f () + { + static int var = 0; + } + +Both of the static ``var`` variables would be included in the table. All +functions should emit both their full names and their basenames. For C or C++, +the full name is the mangled name (if available) which is usually in the +``DW_AT_MIPS_linkage_name`` attribute, and the ``DW_AT_name`` contains the +function basename. If global or static variables have a mangled name in a +``DW_AT_MIPS_linkage_name`` attribute, this should be emitted along with the +simple name found in the ``DW_AT_name`` attribute. + +"``.apple_types``" sections should contain an entry for each DWARF DIE whose +tag is one of: + +* DW_TAG_array_type +* DW_TAG_class_type +* DW_TAG_enumeration_type +* DW_TAG_pointer_type +* DW_TAG_reference_type +* DW_TAG_string_type +* DW_TAG_structure_type +* DW_TAG_subroutine_type +* DW_TAG_typedef +* DW_TAG_union_type +* DW_TAG_ptr_to_member_type +* DW_TAG_set_type +* DW_TAG_subrange_type +* DW_TAG_base_type +* DW_TAG_const_type +* DW_TAG_constant +* DW_TAG_file_type +* DW_TAG_namelist +* DW_TAG_packed_type +* DW_TAG_volatile_type +* DW_TAG_restrict_type +* DW_TAG_interface_type +* DW_TAG_unspecified_type +* DW_TAG_shared_type + +Only entries with a ``DW_AT_name`` attribute are included, and the entry must +not be a forward declaration (``DW_AT_declaration`` attribute with a non-zero +value). For example, using the following code: + +.. code-block:: c + + int main () + { + int *b = 0; + return *b; + } + +We get a few type DIEs: + +.. code-block:: none + + 0x00000067: TAG_base_type [5] + AT_encoding( DW_ATE_signed ) + AT_name( "int" ) + AT_byte_size( 0x04 ) + + 0x0000006e: TAG_pointer_type [6] + AT_type( {0x00000067} ( int ) ) + AT_byte_size( 0x08 ) + +The DW_TAG_pointer_type is not included because it does not have a ``DW_AT_name``. + +"``.apple_namespaces``" section should contain all ``DW_TAG_namespace`` DIEs. +If we run into a namespace that has no name this is an anonymous namespace, and +the name should be output as "``(anonymous namespace)``" (without the quotes). +Why? This matches the output of the ``abi::cxa_demangle()`` that is in the +standard C++ library that demangles mangled names. + + +Language Extensions and File Format Changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Objective-C Extensions +"""""""""""""""""""""" + +"``.apple_objc``" section should contain all ``DW_TAG_subprogram`` DIEs for an +Objective-C class. The name used in the hash table is the name of the +Objective-C class itself. If the Objective-C class has a category, then an +entry is made for both the class name without the category, and for the class +name with the category. So if we have a DIE at offset 0x1234 with a name of +method "``-[NSString(my_additions) stringWithSpecialString:]``", we would add +an entry for "``NSString``" that points to DIE 0x1234, and an entry for +"``NSString(my_additions)``" that points to 0x1234. This allows us to quickly +track down all Objective-C methods for an Objective-C class when doing +expressions. It is needed because of the dynamic nature of Objective-C where +anyone can add methods to a class. The DWARF for Objective-C methods is also +emitted differently from C++ classes where the methods are not usually +contained in the class definition, they are scattered about across one or more +compile units. Categories can also be defined in different shared libraries. +So we need to be able to quickly find all of the methods and class functions +given the Objective-C class name, or quickly find all methods and class +functions for a class + category name. This table does not contain any +selector names, it just maps Objective-C class names (or class names + +category) to all of the methods and class functions. The selectors are added +as function basenames in the "``.debug_names``" section. + +In the "``.apple_names``" section for Objective-C functions, the full name is +the entire function name with the brackets ("``-[NSString +stringWithCString:]``") and the basename is the selector only +("``stringWithCString:``"). + +Mach-O Changes +"""""""""""""" + +The sections names for the apple hash tables are for non mach-o files. For +mach-o files, the sections should be contained in the ``__DWARF`` segment with +names as follows: + +* "``.apple_names``" -> "``__apple_names``" +* "``.apple_types``" -> "``__apple_types``" +* "``.apple_namespaces``" -> "``__apple_namespac``" (16 character limit) +* "``.apple_objc``" -> "``__apple_objc``" + diff --git a/docs/SphinxQuickstartTemplate.rst b/docs/SphinxQuickstartTemplate.rst new file mode 100644 index 00000000..fe6e44a2 --- /dev/null +++ b/docs/SphinxQuickstartTemplate.rst @@ -0,0 +1,160 @@ +========================== +Sphinx Quickstart Template +========================== + +Introduction and Quickstart +=========================== + +This document is meant to get you writing documentation as fast as possible +even if you have no previous experience with Sphinx. The goal is to take +someone in the state of "I want to write documentation and get it added to +LLVM's docs" and turn that into useful documentation mailed to llvm-commits +with as little nonsense as possible. + +You can find this document in ``docs/SphinxQuickstartTemplate.rst``. You +should copy it, open the new file in your text editor, write your docs, and +then send the new document to llvm-commits for review. + +Focus on *content*. It is easy to fix the Sphinx (reStructuredText) syntax +later if necessary, although reStructuredText tries to imitate common +plain-text conventions so it should be quite natural. A basic knowledge of +reStructuredText syntax is useful when writing the document, so the last +~half of this document (starting with `Example Section`_) gives examples +which should cover 99% of use cases. + +Let me say that again: focus on *content*. But if you really need to verify +Sphinx's output, see ``docs/README.txt`` for information. + +Once you have finished with the content, please send the ``.rst`` file to +llvm-commits for review. + +Guidelines +========== + +Try to answer the following questions in your first section: + +#. Why would I want to read this document? + +#. What should I know to be able to follow along with this document? + +#. What will I have learned by the end of this document? + +Common names for the first section are ``Introduction``, ``Overview``, or +``Background``. + +If possible, make your document a "how to". Give it a name ``HowTo*.rst`` +like the other "how to" documents. This format is usually the easiest +for another person to understand and also the most useful. + +You generally should not be writing documentation other than a "how to" +unless there is already a "how to" about your topic. The reason for this +is that without a "how to" document to read first, it is difficult for a +person to understand a more advanced document. + +Focus on content (yes, I had to say it again). + +The rest of this document shows example reStructuredText markup constructs +that are meant to be read by you in your text editor after you have copied +this file into a new file for the documentation you are about to write. + +Example Section +=============== + +Your text can be *emphasized*, **bold**, or ``monospace``. + +Use blank lines to separate paragraphs. + +Headings (like ``Example Section`` just above) give your document its +structure. Use the same kind of adornments (e.g. ``======`` vs. ``------``) +as are used in this document. The adornment must be the same length as the +text above it. For Vim users, variations of ``yypVr=`` might be handy. + +Example Subsection +------------------ + +Make a link `like this `_. There is also a more +sophisticated syntax which `can be more readable`_ for longer links since +it disrupts the flow less. You can put the ``.. _`link text`: `` block +pretty much anywhere later in the document. + +.. _`can be more readable`: http://en.wikipedia.org/wiki/LLVM + +Lists can be made like this: + +#. A list starting with ``#.`` will be automatically numbered. + +#. This is a second list element. + + #. Use indentation to create nested lists. + +You can also use unordered lists. + +* Stuff. + + + Deeper stuff. + +* More stuff. + +Example Subsubsection +^^^^^^^^^^^^^^^^^^^^^ + +You can make blocks of code like this: + +.. code-block:: c++ + + int main() { + return 0; + } + +For a shell session, use a ``console`` code block (some existing docs use +``bash``): + +.. code-block:: console + + $ echo "Goodbye cruel world!" + $ rm -rf / + +If you need to show LLVM IR use the ``llvm`` code block. + +.. code-block:: llvm + + define i32 @test1() { + entry: + ret i32 0 + } + +Some other common code blocks you might need are ``c``, ``objc``, ``make``, +and ``cmake``. If you need something beyond that, you can look at the `full +list`_ of supported code blocks. + +.. _`full list`: http://pygments.org/docs/lexers/ + +However, don't waste time fiddling with syntax highlighting when you could +be adding meaningful content. When in doubt, show preformatted text +without any syntax highlighting like this: + +:: + + . + +:. + ..:: :: + .++:+:: ::+:.:. + .:+ : + ::.::..:: .+. + ..:+ :: : + ......+:. .. + :++. .. : + .+:::+:: : + .. . .+ :: + +.: .::+. + ...+. .: . + .++:.. + ... + +Hopefully you won't need to be this deep +"""""""""""""""""""""""""""""""""""""""" + +If you need to do fancier things than what has been shown in this document, +you can mail the list or check Sphinx's `reStructuredText Primer`_. + +.. _`reStructuredText Primer`: http://sphinx.pocoo.org/rest.html diff --git a/docs/SystemLibrary.rst b/docs/SystemLibrary.rst new file mode 100644 index 00000000..0d0f4fa9 --- /dev/null +++ b/docs/SystemLibrary.rst @@ -0,0 +1,247 @@ +============== +System Library +============== + +Abstract +======== + +This document provides some details on LLVM's System Library, located in the +source at ``lib/System`` and ``include/llvm/System``. The library's purpose is +to shield LLVM from the differences between operating systems for the few +services LLVM needs from the operating system. Much of LLVM is written using +portability features of standard C++. However, in a few areas, system dependent +facilities are needed and the System Library is the wrapper around those system +calls. + +By centralizing LLVM's use of operating system interfaces, we make it possible +for the LLVM tool chain and runtime libraries to be more easily ported to new +platforms since (theoretically) only ``lib/System`` needs to be ported. This +library also unclutters the rest of LLVM from #ifdef use and special cases for +specific operating systems. Such uses are replaced with simple calls to the +interfaces provided in ``include/llvm/System``. + +Note that the System Library is not intended to be a complete operating system +wrapper (such as the Adaptive Communications Environment (ACE) or Apache +Portable Runtime (APR)), but only provides the functionality necessary to +support LLVM. + +The System Library was written by Reid Spencer who formulated the design based +on similar work originating from the eXtensible Programming System (XPS). +Several people helped with the effort; especially, Jeff Cohen and Henrik Bach +on the Win32 port. + +Keeping LLVM Portable +===================== + +In order to keep LLVM portable, LLVM developers should adhere to a set of +portability rules associated with the System Library. Adherence to these rules +should help the System Library achieve its goal of shielding LLVM from the +variations in operating system interfaces and doing so efficiently. The +following sections define the rules needed to fulfill this objective. + +Don't Include System Headers +---------------------------- + +Except in ``lib/System``, no LLVM source code should directly ``#include`` a +system header. Care has been taken to remove all such ``#includes`` from LLVM +while ``lib/System`` was being developed. Specifically this means that header +files like "``unistd.h``", "``windows.h``", "``stdio.h``", and "``string.h``" +are forbidden to be included by LLVM source code outside the implementation of +``lib/System``. + +To obtain system-dependent functionality, existing interfaces to the system +found in ``include/llvm/System`` should be used. If an appropriate interface is +not available, it should be added to ``include/llvm/System`` and implemented in +``lib/System`` for all supported platforms. + +Don't Expose System Headers +--------------------------- + +The System Library must shield LLVM from **all** system headers. To obtain +system level functionality, LLVM source must ``#include "llvm/System/Thing.h"`` +and nothing else. This means that ``Thing.h`` cannot expose any system header +files. This protects LLVM from accidentally using system specific functionality +and only allows it via the ``lib/System`` interface. + +Use Standard C Headers +---------------------- + +The **standard** C headers (the ones beginning with "c") are allowed to be +exposed through the ``lib/System`` interface. These headers and the things they +declare are considered to be platform agnostic. LLVM source files may include +them directly or obtain their inclusion through ``lib/System`` interfaces. + +Use Standard C++ Headers +------------------------ + +The **standard** C++ headers from the standard C++ library and standard +template library may be exposed through the ``lib/System`` interface. These +headers and the things they declare are considered to be platform agnostic. +LLVM source files may include them or obtain their inclusion through +``lib/System`` interfaces. + +High Level Interface +-------------------- + +The entry points specified in the interface of ``lib/System`` must be aimed at +completing some reasonably high level task needed by LLVM. We do not want to +simply wrap each operating system call. It would be preferable to wrap several +operating system calls that are always used in conjunction with one another by +LLVM. + +For example, consider what is needed to execute a program, wait for it to +complete, and return its result code. On Unix, this involves the following +operating system calls: ``getenv``, ``fork``, ``execve``, and ``wait``. The +correct thing for ``lib/System`` to provide is a function, say +``ExecuteProgramAndWait``, that implements the functionality completely. what +we don't want is wrappers for the operating system calls involved. + +There must **not** be a one-to-one relationship between operating system +calls and the System library's interface. Any such interface function will be +suspicious. + +No Unused Functionality +----------------------- + +There must be no functionality specified in the interface of ``lib/System`` +that isn't actually used by LLVM. We're not writing a general purpose operating +system wrapper here, just enough to satisfy LLVM's needs. And, LLVM doesn't +need much. This design goal aims to keep the ``lib/System`` interface small and +understandable which should foster its actual use and adoption. + +No Duplicate Implementations +---------------------------- + +The implementation of a function for a given platform must be written exactly +once. This implies that it must be possible to apply a function's +implementation to multiple operating systems if those operating systems can +share the same implementation. This rule applies to the set of operating +systems supported for a given class of operating system (e.g. Unix, Win32). + +No Virtual Methods +------------------ + +The System Library interfaces can be called quite frequently by LLVM. In order +to make those calls as efficient as possible, we discourage the use of virtual +methods. There is no need to use inheritance for implementation differences, it +just adds complexity. The ``#include`` mechanism works just fine. + +No Exposed Functions +-------------------- + +Any functions defined by system libraries (i.e. not defined by ``lib/System``) +must not be exposed through the ``lib/System`` interface, even if the header +file for that function is not exposed. This prevents inadvertent use of system +specific functionality. + +For example, the ``stat`` system call is notorious for having variations in the +data it provides. ``lib/System`` must not declare ``stat`` nor allow it to be +declared. Instead it should provide its own interface to discovering +information about files and directories. Those interfaces may be implemented in +terms of ``stat`` but that is strictly an implementation detail. The interface +provided by the System Library must be implemented on all platforms (even those +without ``stat``). + +No Exposed Data +--------------- + +Any data defined by system libraries (i.e. not defined by ``lib/System``) must +not be exposed through the ``lib/System`` interface, even if the header file +for that function is not exposed. As with functions, this prevents inadvertent +use of data that might not exist on all platforms. + +Minimize Soft Errors +-------------------- + +Operating system interfaces will generally provide error results for every +little thing that could go wrong. In almost all cases, you can divide these +error results into two groups: normal/good/soft and abnormal/bad/hard. That is, +some of the errors are simply information like "file not found", "insufficient +privileges", etc. while other errors are much harder like "out of space", "bad +disk sector", or "system call interrupted". We'll call the first group "*soft*" +errors and the second group "*hard*" errors. + +``lib/System`` must always attempt to minimize soft errors. This is a design +requirement because the minimization of soft errors can affect the granularity +and the nature of the interface. In general, if you find that you're wanting to +throw soft errors, you must review the granularity of the interface because it +is likely you're trying to implement something that is too low level. The rule +of thumb is to provide interface functions that **can't** fail, except when +faced with hard errors. + +For a trivial example, suppose we wanted to add an "``OpenFileForWriting``" +function. For many operating systems, if the file doesn't exist, attempting to +open the file will produce an error. However, ``lib/System`` should not simply +throw that error if it occurs because its a soft error. The problem is that the +interface function, ``OpenFileForWriting`` is too low level. It should be +``OpenOrCreateFileForWriting``. In the case of the soft "doesn't exist" error, +this function would just create it and then open it for writing. + +This design principle needs to be maintained in ``lib/System`` because it +avoids the propagation of soft error handling throughout the rest of LLVM. +Hard errors will generally just cause a termination for an LLVM tool so don't +be bashful about throwing them. + +Rules of thumb: + +#. Don't throw soft errors, only hard errors. + +#. If you're tempted to throw a soft error, re-think the interface. + +#. Handle internally the most common normal/good/soft error conditions + so the rest of LLVM doesn't have to. + +No throw Specifications +----------------------- + +None of the ``lib/System`` interface functions may be declared with C++ +``throw()`` specifications on them. This requirement makes sure that the +compiler does not insert additional exception handling code into the interface +functions. This is a performance consideration: ``lib/System`` functions are at +the bottom of many call chains and as such can be frequently called. We need +them to be as efficient as possible. However, no routines in the system +library should actually throw exceptions. + +Code Organization +----------------- + +Implementations of the System Library interface are separated by their general +class of operating system. Currently only Unix and Win32 classes are defined +but more could be added for other operating system classifications. To +distinguish which implementation to compile, the code in ``lib/System`` uses +the ``LLVM_ON_UNIX`` and ``LLVM_ON_WIN32`` ``#defines`` provided via configure +through the ``llvm/Config/config.h`` file. Each source file in ``lib/System``, +after implementing the generic (operating system independent) functionality +needs to include the correct implementation using a set of +``#if defined(LLVM_ON_XYZ)`` directives. For example, if we had +``lib/System/File.cpp``, we'd expect to see in that file: + +.. code-block:: c++ + + #if defined(LLVM_ON_UNIX) + #include "Unix/File.cpp" + #endif + #if defined(LLVM_ON_WIN32) + #include "Win32/File.cpp" + #endif + +The implementation in ``lib/System/Unix/File.cpp`` should handle all Unix +variants. The implementation in ``lib/System/Win32/File.cpp`` should handle all +Win32 variants. What this does is quickly differentiate the basic class of +operating system that will provide the implementation. The specific details for +a given platform must still be determined through the use of ``#ifdef``. + +Consistent Semantics +-------------------- + +The implementation of a ``lib/System`` interface can vary drastically between +platforms. That's okay as long as the end result of the interface function is +the same. For example, a function to create a directory is pretty straight +forward on all operating system. System V IPC on the other hand isn't even +supported on all platforms. Instead of "supporting" System V IPC, +``lib/System`` should provide an interface to the basic concept of +inter-process communications. The implementations might use System V IPC if +that was available or named pipes, or whatever gets the job done effectively +for a given operating system. In all cases, the interface and the +implementation must be semantically consistent. + diff --git a/docs/TableGen/LangRef.rst b/docs/TableGen/LangRef.rst new file mode 100644 index 00000000..bd28a903 --- /dev/null +++ b/docs/TableGen/LangRef.rst @@ -0,0 +1,383 @@ +=========================== +TableGen Language Reference +=========================== + +.. sectionauthor:: Sean Silva + +.. contents:: + :local: + +.. warning:: + This document is extremely rough. If you find something lacking, please + fix it, file a documentation bug, or ask about it on llvmdev. + +Introduction +============ + +This document is meant to be a normative spec about the TableGen language +in and of itself (i.e. how to understand a given construct in terms of how +it affects the final set of records represented by the TableGen file). If +you are unsure if this document is really what you are looking for, please +read :doc:`/TableGenFundamentals` first. + +Notation +======== + +The lexical and syntax notation used here is intended to imitate +`Python's`_. In particular, for lexical definitions, the productions +operate at the character level and there is no implied whitespace between +elements. The syntax definitions operate at the token level, so there is +implied whitespace between tokens. + +.. _`Python's`: http://docs.python.org/py3k/reference/introduction.html#notation + +Lexical Analysis +================ + +TableGen supports BCPL (``// ...``) and nestable C-style (``/* ... */``) +comments. + +The following is a listing of the basic punctuation tokens:: + + - + [ ] { } ( ) < > : ; . = ? # + +Numeric literals take one of the following forms: + +.. TableGen actually will lex some pretty strange sequences an interpret + them as numbers. What is shown here is an attempt to approximate what it + "should" accept. + +.. productionlist:: + TokInteger: `DecimalInteger` | `HexInteger` | `BinInteger` + DecimalInteger: ["+" | "-"] ("0"..."9")+ + HexInteger: "0x" ("0"..."9" | "a"..."f" | "A"..."F")+ + BinInteger: "0b" ("0" | "1")+ + +One aspect to note is that the :token:`DecimalInteger` token *includes* the +``+`` or ``-``, as opposed to having ``+`` and ``-`` be unary operators as +most languages do. + +TableGen has identifier-like tokens: + +.. productionlist:: + ualpha: "a"..."z" | "A"..."Z" | "_" + TokIdentifier: ("0"..."9")* `ualpha` (`ualpha` | "0"..."9")* + TokVarName: "$" `ualpha` (`ualpha` | "0"..."9")* + +Note that unlike most languages, TableGen allows :token:`TokIdentifier` to +begin with a number. In case of ambiguity, a token will be interpreted as a +numeric literal rather than an identifier. + +TableGen also has two string-like literals: + +.. productionlist:: + TokString: '"' '"' + TokCodeFragment: "[{" "}]" + +.. note:: + The current implementation accepts the following C-like escapes:: + + \\ \' \" \t \n + +TableGen also has the following keywords:: + + bit bits class code dag + def foreach defm field in + int let list multiclass string + +TableGen also has "bang operators" which have a +wide variety of meanings: + +.. productionlist:: + BangOperator: one of + :!eq !if !head !tail !con + :!add !shl !sra !srl + :!cast !empty !subst !foreach !strconcat + +Syntax +====== + +TableGen has an ``include`` mechanism. It does not play a role in the +syntax per se, since it is lexically replaced with the contents of the +included file. + +.. productionlist:: + IncludeDirective: "include" `TokString` + +TableGen's top-level production consists of "objects". + +.. productionlist:: + TableGenFile: `Object`* + Object: `Class` | `Def` | `Defm` | `Let` | `MultiClass` | `Foreach` + +``class``\es +------------ + +.. productionlist:: + Class: "class" `TokIdentifier` [`TemplateArgList`] `ObjectBody` + +A ``class`` declaration creates a record which other records can inherit +from. A class can be parametrized by a list of "template arguments", whose +values can be used in the class body. + +A given class can only be defined once. A ``class`` declaration is +considered to define the class if any of the following is true: + +.. break ObjectBody into its consituents so that they are present here? + +#. The :token:`TemplateArgList` is present. +#. The :token:`Body` in the :token:`ObjectBody` is present and is not empty. +#. The :token:`BaseClassList` in the :token:`ObjectBody` is present. + +You can declare an empty class by giving and empty :token:`TemplateArgList` +and an empty :token:`ObjectBody`. This can serve as a restricted form of +forward declaration: note that records deriving from the forward-declared +class will inherit no fields from it since the record expansion is done +when the record is parsed. + +.. productionlist:: + TemplateArgList: "<" `Declaration` ("," `Declaration`)* ">" + +Declarations +------------ + +.. Omitting mention of arcane "field" prefix to discourage its use. + +The declaration syntax is pretty much what you would expect as a C++ +programmer. + +.. productionlist:: + Declaration: `Type` `TokIdentifier` ["=" `Value`] + +It assigns the value to the identifer. + +Types +----- + +.. productionlist:: + Type: "string" | "code" | "bit" | "int" | "dag" + :| "bits" "<" `TokInteger` ">" + :| "list" "<" `Type` ">" + :| `ClassID` + ClassID: `TokIdentifier` + +Both ``string`` and ``code`` correspond to the string type; the difference +is purely to indicate programmer intention. + +The :token:`ClassID` must identify a class that has been previously +declared or defined. + +Values +------ + +.. productionlist:: + Value: `SimpleValue` `ValueSuffix`* + ValueSuffix: "{" `RangeList` "}" + :| "[" `RangeList` "]" + :| "." `TokIdentifier` + RangeList: `RangePiece` ("," `RangePiece`)* + RangePiece: `TokInteger` + :| `TokInteger` "-" `TokInteger` + :| `TokInteger` `TokInteger` + +The peculiar last form of :token:`RangePiece` is due to the fact that the +"``-``" is included in the :token:`TokInteger`, hence ``1-5`` gets lexed as +two consecutive :token:`TokInteger`'s, with values ``1`` and ``-5``, +instead of "1", "-", and "5". +The :token:`RangeList` can be thought of as specifying "list slice" in some +contexts. + + +:token:`SimpleValue` has a number of forms: + + +.. productionlist:: + SimpleValue: `TokIdentifier` + +The value will be the variable referenced by the identifier. It can be one +of: + +.. The code for this is exceptionally abstruse. These examples are a + best-effort attempt. + +* name of a ``def``, such as the use of ``Bar`` in:: + + def Bar : SomeClass { + int X = 5; + } + + def Foo { + SomeClass Baz = Bar; + } + +* value local to a ``def``, such as the use of ``Bar`` in:: + + def Foo { + int Bar = 5; + int Baz = Bar; + } + +* a template arg of a ``class``, such as the use of ``Bar`` in:: + + class Foo { + int Baz = Bar; + } + +* value local to a ``multiclass``, such as the use of ``Bar`` in:: + + multiclass Foo { + int Bar = 5; + int Baz = Bar; + } + +* a template arg to a ``multiclass``, such as the use of ``Bar`` in:: + + multiclass Foo { + int Baz = Bar; + } + +.. productionlist:: + SimpleValue: `TokInteger` + +This represents the numeric value of the integer. + +.. productionlist:: + SimpleValue: `TokString`+ + +Multiple adjacent string literals are concatenated like in C/C++. The value +is the concatenation of the strings. + +.. productionlist:: + SimpleValue: `TokCodeFragment` + +The value is the string value of the code fragment. + +.. productionlist:: + SimpleValue: "?" + +``?`` represents an "unset" initializer. + +.. productionlist:: + SimpleValue: "{" `ValueList` "}" + ValueList: [`ValueListNE`] + ValueListNE: `Value` ("," `Value`)* + +This represents a sequence of bits, as would be used to initialize a +``bits`` field (where ``n`` is the number of bits). + +.. productionlist:: + SimpleValue: `ClassID` "<" `ValueListNE` ">" + +This generates a new anonymous record definition (as would be created by an +unnamed ``def`` inheriting from the given class with the given template +arguments) and the value is the value of that record definition. + +.. productionlist:: + SimpleValue: "[" `ValueList` "]" ["<" `Type` ">"] + +A list initializer. The optional :token:`Type` can be used to indicate a +specific element type, otherwise the element type will be deduced from the +given values. + +.. The initial `DagArg` of the dag must start with an identifier or + !cast, but this is more of an implementation detail and so for now just + leave it out. + +.. productionlist:: + SimpleValue: "(" `DagArg` `DagArgList` ")" + DagArgList: `DagArg` ("," `DagArg`)* + DagArg: `Value` [":" `TokVarName`] | `TokVarName` + +The initial :token:`DagArg` is called the "operator" of the dag. + +.. productionlist:: + SimpleValue: `BangOperator` ["<" `Type` ">"] "(" `ValueListNE` ")" + +Bodies +------ + +.. productionlist:: + ObjectBody: `BaseClassList` `Body` + BaseClassList: [":" `BaseClassListNE`] + BaseClassListNE: `SubClassRef` ("," `SubClassRef`)* + SubClassRef: (`ClassID` | `MultiClassID`) ["<" `ValueList` ">"] + DefmID: `TokIdentifier` + +The version with the :token:`MultiClassID` is only valid in the +:token:`BaseClassList` of a ``defm``. +The :token:`MultiClassID` should be the name of a ``multiclass``. + +.. put this somewhere else + +It is after parsing the base class list that the "let stack" is applied. + +.. productionlist:: + Body: ";" | "{" BodyList "}" + BodyList: BodyItem* + BodyItem: `Declaration` ";" + :| "let" `TokIdentifier` [`RangeList`] "=" `Value` ";" + +The ``let`` form allows overriding the value of an inherited field. + +``def`` +------- + +.. TODO:: + There can be pastes in the names here, like ``#NAME#``. Look into that + and document it (it boils down to ParseIDValue with IDParseMode == + ParseNameMode). ParseObjectName calls into the general ParseValue, with + the only different from "arbitrary expression parsing" being IDParseMode + == Mode. + +.. productionlist:: + Def: "def" `TokIdentifier` `ObjectBody` + +Defines a record whose name is given by the :token:`TokIdentifier`. The +fields of the record are inherited from the base classes and defined in the +body. + +Special handling occurs if this ``def`` appears inside a ``multiclass`` or +a ``foreach``. + +``defm`` +-------- + +.. productionlist:: + Defm: "defm" `TokIdentifier` ":" `BaseClassListNE` ";" + +Note that in the :token:`BaseClassList`, all of the ``multiclass``'s must +precede any ``class``'s that appear. + +``foreach`` +----------- + +.. productionlist:: + Foreach: "foreach" `Declaration` "in" "{" `Object`* "}" + :| "foreach" `Declaration` "in" `Object` + +The value assigned to the variable in the declaration is iterated over and +the object or object list is reevaluated with the variable set at each +iterated value. + +Top-Level ``let`` +----------------- + +.. productionlist:: + Let: "let" `LetList` "in" "{" `Object`* "}" + :| "let" `LetList` "in" `Object` + LetList: `LetItem` ("," `LetItem`)* + LetItem: `TokIdentifier` [`RangeList`] "=" `Value` + +This is effectively equivalent to ``let`` inside the body of a record +except that it applies to multiple records at a time. The bindings are +applied at the end of parsing the base classes of a record. + +``multiclass`` +-------------- + +.. productionlist:: + MultiClass: "multiclass" `TokIdentifier` [`TemplateArgList`] + : [":" `BaseMultiClassList`] "{" `MultiClassObject`+ "}" + BaseMultiClassList: `MultiClassID` ("," `MultiClassID`)* + MultiClassID: `TokIdentifier` + MultiClassObject: `Def` | `Defm` | `Let` | `Foreach` diff --git a/docs/TableGenFundamentals.rst b/docs/TableGenFundamentals.rst new file mode 100644 index 00000000..4fe4bb98 --- /dev/null +++ b/docs/TableGenFundamentals.rst @@ -0,0 +1,800 @@ +===================== +TableGen Fundamentals +===================== + +.. contents:: + :local: + +Introduction +============ + +TableGen's purpose is to help a human develop and maintain records of +domain-specific information. Because there may be a large number of these +records, it is specifically designed to allow writing flexible descriptions and +for common features of these records to be factored out. This reduces the +amount of duplication in the description, reduces the chance of error, and makes +it easier to structure domain specific information. + +The core part of TableGen `parses a file`_, instantiates the declarations, and +hands the result off to a domain-specific `TableGen backend`_ for processing. +The current major user of TableGen is the `LLVM code +generator `_. + +Note that if you work on TableGen much, and use emacs or vim, that you can find +an emacs "TableGen mode" and a vim language file in the ``llvm/utils/emacs`` and +``llvm/utils/vim`` directories of your LLVM distribution, respectively. + +.. _intro: + +Basic concepts +-------------- + +TableGen files consist of two key parts: 'classes' and 'definitions', both of +which are considered 'records'. + +**TableGen records** have a unique name, a list of values, and a list of +superclasses. The list of values is the main data that TableGen builds for each +record; it is this that holds the domain specific information for the +application. The interpretation of this data is left to a specific `TableGen +backend`_, but the structure and format rules are taken care of and are fixed by +TableGen. + +**TableGen definitions** are the concrete form of 'records'. These generally do +not have any undefined values, and are marked with the '``def``' keyword. + +**TableGen classes** are abstract records that are used to build and describe +other records. These 'classes' allow the end-user to build abstractions for +either the domain they are targeting (such as "Register", "RegisterClass", and +"Instruction" in the LLVM code generator) or for the implementor to help factor +out common properties of records (such as "FPInst", which is used to represent +floating point instructions in the X86 backend). TableGen keeps track of all of +the classes that are used to build up a definition, so the backend can find all +definitions of a particular class, such as "Instruction". + +**TableGen multiclasses** are groups of abstract records that are instantiated +all at once. Each instantiation can result in multiple TableGen definitions. +If a multiclass inherits from another multiclass, the definitions in the +sub-multiclass become part of the current multiclass, as if they were declared +in the current multiclass. + +.. _described above: + +An example record +----------------- + +With no other arguments, TableGen parses the specified file and prints out all +of the classes, then all of the definitions. This is a good way to see what the +various definitions expand to fully. Running this on the ``X86.td`` file prints +this (at the time of this writing): + +.. code-block:: llvm + + ... + def ADD32rr { // Instruction X86Inst I + string Namespace = "X86"; + dag OutOperandList = (outs GR32:$dst); + dag InOperandList = (ins GR32:$src1, GR32:$src2); + string AsmString = "add{l}\t{$src2, $dst|$dst, $src2}"; + list Pattern = [(set GR32:$dst, (add GR32:$src1, GR32:$src2))]; + list Uses = []; + list Defs = [EFLAGS]; + list Predicates = []; + int CodeSize = 3; + int AddedComplexity = 0; + bit isReturn = 0; + bit isBranch = 0; + bit isIndirectBranch = 0; + bit isBarrier = 0; + bit isCall = 0; + bit canFoldAsLoad = 0; + bit mayLoad = 0; + bit mayStore = 0; + bit isImplicitDef = 0; + bit isConvertibleToThreeAddress = 1; + bit isCommutable = 1; + bit isTerminator = 0; + bit isReMaterializable = 0; + bit isPredicable = 0; + bit hasDelaySlot = 0; + bit usesCustomInserter = 0; + bit hasCtrlDep = 0; + bit isNotDuplicable = 0; + bit hasSideEffects = 0; + bit neverHasSideEffects = 0; + InstrItinClass Itinerary = NoItinerary; + string Constraints = ""; + string DisableEncoding = ""; + bits<8> Opcode = { 0, 0, 0, 0, 0, 0, 0, 1 }; + Format Form = MRMDestReg; + bits<6> FormBits = { 0, 0, 0, 0, 1, 1 }; + ImmType ImmT = NoImm; + bits<3> ImmTypeBits = { 0, 0, 0 }; + bit hasOpSizePrefix = 0; + bit hasAdSizePrefix = 0; + bits<4> Prefix = { 0, 0, 0, 0 }; + bit hasREX_WPrefix = 0; + FPFormat FPForm = ?; + bits<3> FPFormBits = { 0, 0, 0 }; + } + ... + +This definition corresponds to the 32-bit register-register ``add`` instruction +of the x86 architecture. ``def ADD32rr`` defines a record named +``ADD32rr``, and the comment at the end of the line indicates the superclasses +of the definition. The body of the record contains all of the data that +TableGen assembled for the record, indicating that the instruction is part of +the "X86" namespace, the pattern indicating how the instruction should be +emitted into the assembly file, that it is a two-address instruction, has a +particular encoding, etc. The contents and semantics of the information in the +record are specific to the needs of the X86 backend, and are only shown as an +example. + +As you can see, a lot of information is needed for every instruction supported +by the code generator, and specifying it all manually would be unmaintainable, +prone to bugs, and tiring to do in the first place. Because we are using +TableGen, all of the information was derived from the following definition: + +.. code-block:: llvm + + let Defs = [EFLAGS], + isCommutable = 1, // X = ADD Y,Z --> X = ADD Z,Y + isConvertibleToThreeAddress = 1 in // Can transform into LEA. + def ADD32rr : I<0x01, MRMDestReg, (outs GR32:$dst), + (ins GR32:$src1, GR32:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (add GR32:$src1, GR32:$src2))]>; + +This definition makes use of the custom class ``I`` (extended from the custom +class ``X86Inst``), which is defined in the X86-specific TableGen file, to +factor out the common features that instructions of its class share. A key +feature of TableGen is that it allows the end-user to define the abstractions +they prefer to use when describing their information. + +Each ``def`` record has a special entry called "NAME". This is the name of the +record ("``ADD32rr``" above). In the general case ``def`` names can be formed +from various kinds of string processing expressions and ``NAME`` resolves to the +final value obtained after resolving all of those expressions. The user may +refer to ``NAME`` anywhere she desires to use the ultimate name of the ``def``. +``NAME`` should not be defined anywhere else in user code to avoid conflicts. + +Running TableGen +---------------- + +TableGen runs just like any other LLVM tool. The first (optional) argument +specifies the file to read. If a filename is not specified, ``llvm-tblgen`` +reads from standard input. + +To be useful, one of the `TableGen backends`_ must be used. These backends are +selectable on the command line (type '``llvm-tblgen -help``' for a list). For +example, to get a list of all of the definitions that subclass a particular type +(which can be useful for building up an enum list of these records), use the +``-print-enums`` option: + +.. code-block:: bash + + $ llvm-tblgen X86.td -print-enums -class=Register + AH, AL, AX, BH, BL, BP, BPL, BX, CH, CL, CX, DH, DI, DIL, DL, DX, EAX, EBP, EBX, + ECX, EDI, EDX, EFLAGS, EIP, ESI, ESP, FP0, FP1, FP2, FP3, FP4, FP5, FP6, IP, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, R10, R10B, R10D, R10W, R11, R11B, R11D, + R11W, R12, R12B, R12D, R12W, R13, R13B, R13D, R13W, R14, R14B, R14D, R14W, R15, + R15B, R15D, R15W, R8, R8B, R8D, R8W, R9, R9B, R9D, R9W, RAX, RBP, RBX, RCX, RDI, + RDX, RIP, RSI, RSP, SI, SIL, SP, SPL, ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, + XMM0, XMM1, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM2, XMM3, XMM4, XMM5, + XMM6, XMM7, XMM8, XMM9, + + $ llvm-tblgen X86.td -print-enums -class=Instruction + ABS_F, ABS_Fp32, ABS_Fp64, ABS_Fp80, ADC32mi, ADC32mi8, ADC32mr, ADC32ri, + ADC32ri8, ADC32rm, ADC32rr, ADC64mi32, ADC64mi8, ADC64mr, ADC64ri32, ADC64ri8, + ADC64rm, ADC64rr, ADD16mi, ADD16mi8, ADD16mr, ADD16ri, ADD16ri8, ADD16rm, + ADD16rr, ADD32mi, ADD32mi8, ADD32mr, ADD32ri, ADD32ri8, ADD32rm, ADD32rr, + ADD64mi32, ADD64mi8, ADD64mr, ADD64ri32, ... + +The default backend prints out all of the records, as `described above`_. + +If you plan to use TableGen, you will most likely have to `write a backend`_ +that extracts the information specific to what you need and formats it in the +appropriate way. + +.. _parses a file: + +TableGen syntax +=============== + +TableGen doesn't care about the meaning of data (that is up to the backend to +define), but it does care about syntax, and it enforces a simple type system. +This section describes the syntax and the constructs allowed in a TableGen file. + +TableGen primitives +------------------- + +TableGen comments +^^^^^^^^^^^^^^^^^ + +TableGen supports BCPL style "``//``" comments, which run to the end of the +line, and it also supports **nestable** "``/* */``" comments. + +.. _TableGen type: + +The TableGen type system +^^^^^^^^^^^^^^^^^^^^^^^^ + +TableGen files are strongly typed, in a simple (but complete) type-system. +These types are used to perform automatic conversions, check for errors, and to +help interface designers constrain the input that they allow. Every `value +definition`_ is required to have an associated type. + +TableGen supports a mixture of very low-level types (such as ``bit``) and very +high-level types (such as ``dag``). This flexibility is what allows it to +describe a wide range of information conveniently and compactly. The TableGen +types are: + +``bit`` + A 'bit' is a boolean value that can hold either 0 or 1. + +``int`` + The 'int' type represents a simple 32-bit integer value, such as 5. + +``string`` + The 'string' type represents an ordered sequence of characters of arbitrary + length. + +``bits`` + A 'bits' type is an arbitrary, but fixed, size integer that is broken up + into individual bits. This type is useful because it can handle some bits + being defined while others are undefined. + +``list`` + This type represents a list whose elements are some other type. The + contained type is arbitrary: it can even be another list type. + +Class type + Specifying a class name in a type context means that the defined value must + be a subclass of the specified class. This is useful in conjunction with + the ``list`` type, for example, to constrain the elements of the list to a + common base class (e.g., a ``list`` can only contain definitions + derived from the "``Register``" class). + +``dag`` + This type represents a nestable directed graph of elements. + +``code`` + This represents a big hunk of text. This is lexically distinct from string + values because it doesn't require escaping double quotes and other common + characters that occur in code. + +To date, these types have been sufficient for describing things that TableGen +has been used for, but it is straight-forward to extend this list if needed. + +.. _TableGen expressions: + +TableGen values and expressions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TableGen allows for a pretty reasonable number of different expression forms +when building up values. These forms allow the TableGen file to be written in a +natural syntax and flavor for the application. The current expression forms +supported include: + +``?`` + uninitialized field + +``0b1001011`` + binary integer value + +``07654321`` + octal integer value (indicated by a leading 0) + +``7`` + decimal integer value + +``0x7F`` + hexadecimal integer value + +``"foo"`` + string value + +``[{ ... }]`` + code fragment + +``[ X, Y, Z ]`` + list value. is the type of the list element and is usually optional. + In rare cases, TableGen is unable to deduce the element type in which case + the user must specify it explicitly. + +``{ a, b, c }`` + initializer for a "bits<3>" value + +``value`` + value reference + +``value{17}`` + access to one bit of a value + +``value{15-17}`` + access to multiple bits of a value + +``DEF`` + reference to a record definition + +``CLASS`` + reference to a new anonymous definition of CLASS with the specified template + arguments. + +``X.Y`` + reference to the subfield of a value + +``list[4-7,17,2-3]`` + A slice of the 'list' list, including elements 4,5,6,7,17,2, and 3 from it. + Elements may be included multiple times. + +``foreach = [ ] in { }`` + +``foreach = [ ] in `` + Replicate or , replacing instances of with each value + in . is scoped at the level of the ``foreach`` loop and must + not conflict with any other object introduced in or . Currently + only ``def``\s are expanded within . + +``foreach = 0-15 in ...`` + +``foreach = {0-15,32-47} in ...`` + Loop over ranges of integers. The braces are required for multiple ranges. + +``(DEF a, b)`` + a dag value. The first element is required to be a record definition, the + remaining elements in the list may be arbitrary other values, including + nested ```dag``' values. + +``!strconcat(a, b)`` + A string value that is the result of concatenating the 'a' and 'b' strings. + +``str1#str2`` + "#" (paste) is a shorthand for !strconcat. It may concatenate things that + are not quoted strings, in which case an implicit !cast is done on + the operand of the paste. + +``!cast(a)`` + A symbol of type *type* obtained by looking up the string 'a' in the symbol + table. If the type of 'a' does not match *type*, TableGen aborts with an + error. !cast is a special case in that the argument must be an + object defined by a 'def' construct. + +``!subst(a, b, c)`` + If 'a' and 'b' are of string type or are symbol references, substitute 'b' + for 'a' in 'c.' This operation is analogous to $(subst) in GNU make. + +``!foreach(a, b, c)`` + For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a dummy + variable that should be declared as a member variable of an instantiated + class. This operation is analogous to $(foreach) in GNU make. + +``!head(a)`` + The first element of list 'a.' + +``!tail(a)`` + The 2nd-N elements of list 'a.' + +``!empty(a)`` + An integer {0,1} indicating whether list 'a' is empty. + +``!if(a,b,c)`` + 'b' if the result of 'int' or 'bit' operator 'a' is nonzero, 'c' otherwise. + +``!eq(a,b)`` + 'bit 1' if string a is equal to string b, 0 otherwise. This only operates + on string, int and bit objects. Use !cast to compare other types of + objects. + +Note that all of the values have rules specifying how they convert to values +for different types. These rules allow you to assign a value like "``7``" +to a "``bits<4>``" value, for example. + +Classes and definitions +----------------------- + +As mentioned in the `intro`_, classes and definitions (collectively known as +'records') in TableGen are the main high-level unit of information that TableGen +collects. Records are defined with a ``def`` or ``class`` keyword, the record +name, and an optional list of "`template arguments`_". If the record has +superclasses, they are specified as a comma separated list that starts with a +colon character ("``:``"). If `value definitions`_ or `let expressions`_ are +needed for the class, they are enclosed in curly braces ("``{}``"); otherwise, +the record ends with a semicolon. + +Here is a simple TableGen file: + +.. code-block:: llvm + + class C { bit V = 1; } + def X : C; + def Y : C { + string Greeting = "hello"; + } + +This example defines two definitions, ``X`` and ``Y``, both of which derive from +the ``C`` class. Because of this, they both get the ``V`` bit value. The ``Y`` +definition also gets the Greeting member as well. + +In general, classes are useful for collecting together the commonality between a +group of records and isolating it in a single place. Also, classes permit the +specification of default values for their subclasses, allowing the subclasses to +override them as they wish. + +.. _value definition: +.. _value definitions: + +Value definitions +^^^^^^^^^^^^^^^^^ + +Value definitions define named entries in records. A value must be defined +before it can be referred to as the operand for another value definition or +before the value is reset with a `let expression`_. A value is defined by +specifying a `TableGen type`_ and a name. If an initial value is available, it +may be specified after the type with an equal sign. Value definitions require +terminating semicolons. + +.. _let expression: +.. _let expressions: +.. _"let" expressions within a record: + +'let' expressions +^^^^^^^^^^^^^^^^^ + +A record-level let expression is used to change the value of a value definition +in a record. This is primarily useful when a superclass defines a value that a +derived class or definition wants to override. Let expressions consist of the +'``let``' keyword followed by a value name, an equal sign ("``=``"), and a new +value. For example, a new class could be added to the example above, redefining +the ``V`` field for all of its subclasses: + +.. code-block:: llvm + + class D : C { let V = 0; } + def Z : D; + +In this case, the ``Z`` definition will have a zero value for its ``V`` value, +despite the fact that it derives (indirectly) from the ``C`` class, because the +``D`` class overrode its value. + +.. _template arguments: + +Class template arguments +^^^^^^^^^^^^^^^^^^^^^^^^ + +TableGen permits the definition of parameterized classes as well as normal +concrete classes. Parameterized TableGen classes specify a list of variable +bindings (which may optionally have defaults) that are bound when used. Here is +a simple example: + +.. code-block:: llvm + + class FPFormat val> { + bits<3> Value = val; + } + def NotFP : FPFormat<0>; + def ZeroArgFP : FPFormat<1>; + def OneArgFP : FPFormat<2>; + def OneArgFPRW : FPFormat<3>; + def TwoArgFP : FPFormat<4>; + def CompareFP : FPFormat<5>; + def CondMovFP : FPFormat<6>; + def SpecialFP : FPFormat<7>; + +In this case, template arguments are used as a space efficient way to specify a +list of "enumeration values", each with a "``Value``" field set to the specified +integer. + +The more esoteric forms of `TableGen expressions`_ are useful in conjunction +with template arguments. As an example: + +.. code-block:: llvm + + class ModRefVal val> { + bits<2> Value = val; + } + + def None : ModRefVal<0>; + def Mod : ModRefVal<1>; + def Ref : ModRefVal<2>; + def ModRef : ModRefVal<3>; + + class Value { + // Decode some information into a more convenient format, while providing + // a nice interface to the user of the "Value" class. + bit isMod = MR.Value{0}; + bit isRef = MR.Value{1}; + + // other stuff... + } + + // Example uses + def bork : Value; + def zork : Value; + def hork : Value; + +This is obviously a contrived example, but it shows how template arguments can +be used to decouple the interface provided to the user of the class from the +actual internal data representation expected by the class. In this case, +running ``llvm-tblgen`` on the example prints the following definitions: + +.. code-block:: llvm + + def bork { // Value + bit isMod = 1; + bit isRef = 0; + } + def hork { // Value + bit isMod = 1; + bit isRef = 1; + } + def zork { // Value + bit isMod = 0; + bit isRef = 1; + } + +This shows that TableGen was able to dig into the argument and extract a piece +of information that was requested by the designer of the "Value" class. For +more realistic examples, please see existing users of TableGen, such as the X86 +backend. + +Multiclass definitions and instances +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While classes with template arguments are a good way to factor commonality +between two instances of a definition, multiclasses allow a convenient notation +for defining multiple definitions at once (instances of implicitly constructed +classes). For example, consider an 3-address instruction set whose instructions +come in two forms: "``reg = reg op reg``" and "``reg = reg op imm``" +(e.g. SPARC). In this case, you'd like to specify in one place that this +commonality exists, then in a separate place indicate what all the ops are. + +Here is an example TableGen fragment that shows this idea: + +.. code-block:: llvm + + def ops; + def GPR; + def Imm; + class inst; + + multiclass ri_inst { + def _rr : inst; + def _ri : inst; + } + + // Instantiations of the ri_inst multiclass. + defm ADD : ri_inst<0b111, "add">; + defm SUB : ri_inst<0b101, "sub">; + defm MUL : ri_inst<0b100, "mul">; + ... + +The name of the resultant definitions has the multidef fragment names appended +to them, so this defines ``ADD_rr``, ``ADD_ri``, ``SUB_rr``, etc. A defm may +inherit from multiple multiclasses, instantiating definitions from each +multiclass. Using a multiclass this way is exactly equivalent to instantiating +the classes multiple times yourself, e.g. by writing: + +.. code-block:: llvm + + def ops; + def GPR; + def Imm; + class inst; + + class rrinst + : inst; + + class riinst + : inst; + + // Instantiations of the ri_inst multiclass. + def ADD_rr : rrinst<0b111, "add">; + def ADD_ri : riinst<0b111, "add">; + def SUB_rr : rrinst<0b101, "sub">; + def SUB_ri : riinst<0b101, "sub">; + def MUL_rr : rrinst<0b100, "mul">; + def MUL_ri : riinst<0b100, "mul">; + ... + +A ``defm`` can also be used inside a multiclass providing several levels of +multiclass instanciations. + +.. code-block:: llvm + + class Instruction opc, string Name> { + bits<4> opcode = opc; + string name = Name; + } + + multiclass basic_r opc> { + def rr : Instruction; + def rm : Instruction; + } + + multiclass basic_s opc> { + defm SS : basic_r; + defm SD : basic_r; + def X : Instruction; + } + + multiclass basic_p opc> { + defm PS : basic_r; + defm PD : basic_r; + def Y : Instruction; + } + + defm ADD : basic_s<0xf>, basic_p<0xf>; + ... + + // Results + def ADDPDrm { ... + def ADDPDrr { ... + def ADDPSrm { ... + def ADDPSrr { ... + def ADDSDrm { ... + def ADDSDrr { ... + def ADDY { ... + def ADDX { ... + +``defm`` declarations can inherit from classes too, the rule to follow is that +the class list must start after the last multiclass, and there must be at least +one multiclass before them. + +.. code-block:: llvm + + class XD { bits<4> Prefix = 11; } + class XS { bits<4> Prefix = 12; } + + class I op> { + bits<4> opcode = op; + } + + multiclass R { + def rr : I<4>; + def rm : I<2>; + } + + multiclass Y { + defm SS : R, XD; + defm SD : R, XS; + } + + defm Instr : Y; + + // Results + def InstrSDrm { + bits<4> opcode = { 0, 0, 1, 0 }; + bits<4> Prefix = { 1, 1, 0, 0 }; + } + ... + def InstrSSrr { + bits<4> opcode = { 0, 1, 0, 0 }; + bits<4> Prefix = { 1, 0, 1, 1 }; + } + +File scope entities +------------------- + +File inclusion +^^^^^^^^^^^^^^ + +TableGen supports the '``include``' token, which textually substitutes the +specified file in place of the include directive. The filename should be +specified as a double quoted string immediately after the '``include``' keyword. +Example: + +.. code-block:: llvm + + include "foo.td" + +'let' expressions +^^^^^^^^^^^^^^^^^ + +"Let" expressions at file scope are similar to `"let" expressions within a +record`_, except they can specify a value binding for multiple records at a +time, and may be useful in certain other cases. File-scope let expressions are +really just another way that TableGen allows the end-user to factor out +commonality from the records. + +File-scope "let" expressions take a comma-separated list of bindings to apply, +and one or more records to bind the values in. Here are some examples: + +.. code-block:: llvm + + let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in + def RET : I<0xC3, RawFrm, (outs), (ins), "ret", [(X86retflag 0)]>; + + let isCall = 1 in + // All calls clobber the non-callee saved registers... + let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, EFLAGS] in { + def CALLpcrel32 : Ii32<0xE8, RawFrm, (outs), (ins i32imm:$dst,variable_ops), + "call\t${dst:call}", []>; + def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops), + "call\t{*}$dst", [(X86call GR32:$dst)]>; + def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst, variable_ops), + "call\t{*}$dst", []>; + } + +File-scope "let" expressions are often useful when a couple of definitions need +to be added to several records, and the records do not otherwise need to be +opened, as in the case with the ``CALL*`` instructions above. + +It's also possible to use "let" expressions inside multiclasses, providing more +ways to factor out commonality from the records, specially if using several +levels of multiclass instanciations. This also avoids the need of using "let" +expressions within subsequent records inside a multiclass. + +.. code-block:: llvm + + multiclass basic_r opc> { + let Predicates = [HasSSE2] in { + def rr : Instruction; + def rm : Instruction; + } + let Predicates = [HasSSE3] in + def rx : Instruction; + } + + multiclass basic_ss opc> { + let IsDouble = 0 in + defm SS : basic_r; + + let IsDouble = 1 in + defm SD : basic_r; + } + + defm ADD : basic_ss<0xf>; + +Looping +^^^^^^^ + +TableGen supports the '``foreach``' block, which textually replicates the loop +body, substituting iterator values for iterator references in the body. +Example: + +.. code-block:: llvm + + foreach i = [0, 1, 2, 3] in { + def R#i : Register<...>; + def F#i : Register<...>; + } + +This will create objects ``R0``, ``R1``, ``R2`` and ``R3``. ``foreach`` blocks +may be nested. If there is only one item in the body the braces may be +elided: + +.. code-block:: llvm + + foreach i = [0, 1, 2, 3] in + def R#i : Register<...>; + +Code Generator backend info +=========================== + +Expressions used by code generator to describe instructions and isel patterns: + +``(implicit a)`` + an implicitly defined physical register. This tells the dag instruction + selection emitter the input pattern's extra definitions matches implicit + physical register definitions. + +.. _TableGen backend: +.. _TableGen backends: +.. _write a backend: + +TableGen backends +================= + +Until we get a step-by-step HowTo for writing TableGen backends, you can at +least grab the boilerplate (build system, new files, etc.) from Clang's +r173931. + +TODO: How they work, how to write one. This section should not contain details +about any particular backend, except maybe ``-print-enums`` as an example. This +should highlight the APIs in ``TableGen/Record.h``. diff --git a/docs/TestSuiteMakefileGuide.rst b/docs/TestSuiteMakefileGuide.rst new file mode 100644 index 00000000..e2852a07 --- /dev/null +++ b/docs/TestSuiteMakefileGuide.rst @@ -0,0 +1,276 @@ +============================== +LLVM test-suite Makefile Guide +============================== + +.. contents:: + :local: + +Overview +======== + +This document describes the features of the Makefile-based LLVM +test-suite. This way of interacting with the test-suite is deprecated in +favor of running the test-suite using LNT, but may continue to prove +useful for some users. See the Testing Guide's :ref:`test-suite Quickstart +` section for more information. + +Test suite Structure +==================== + +The ``test-suite`` module contains a number of programs that can be +compiled with LLVM and executed. These programs are compiled using the +native compiler and various LLVM backends. The output from the program +compiled with the native compiler is assumed correct; the results from +the other programs are compared to the native program output and pass if +they match. + +When executing tests, it is usually a good idea to start out with a +subset of the available tests or programs. This makes test run times +smaller at first and later on this is useful to investigate individual +test failures. To run some test only on a subset of programs, simply +change directory to the programs you want tested and run ``gmake`` +there. Alternatively, you can run a different test using the ``TEST`` +variable to change what tests or run on the selected programs (see below +for more info). + +In addition for testing correctness, the ``test-suite`` directory also +performs timing tests of various LLVM optimizations. It also records +compilation times for the compilers and the JIT. This information can be +used to compare the effectiveness of LLVM's optimizations and code +generation. + +``test-suite`` tests are divided into three types of tests: MultiSource, +SingleSource, and External. + +- ``test-suite/SingleSource`` + + The SingleSource directory contains test programs that are only a + single source file in size. These are usually small benchmark + programs or small programs that calculate a particular value. Several + such programs are grouped together in each directory. + +- ``test-suite/MultiSource`` + + The MultiSource directory contains subdirectories which contain + entire programs with multiple source files. Large benchmarks and + whole applications go here. + +- ``test-suite/External`` + + The External directory contains Makefiles for building code that is + external to (i.e., not distributed with) LLVM. The most prominent + members of this directory are the SPEC 95 and SPEC 2000 benchmark + suites. The ``External`` directory does not contain these actual + tests, but only the Makefiles that know how to properly compile these + programs from somewhere else. The presence and location of these + external programs is configured by the test-suite ``configure`` + script. + +Each tree is then subdivided into several categories, including +applications, benchmarks, regression tests, code that is strange +grammatically, etc. These organizations should be relatively self +explanatory. + +Some tests are known to fail. Some are bugs that we have not fixed yet; +others are features that we haven't added yet (or may never add). In the +regression tests, the result for such tests will be XFAIL (eXpected +FAILure). In this way, you can tell the difference between an expected +and unexpected failure. + +The tests in the test suite have no such feature at this time. If the +test passes, only warnings and other miscellaneous output will be +generated. If a test fails, a large FAILED message will be +displayed. This will help you separate benign warnings from actual test +failures. + +Running the test suite +====================== + +First, all tests are executed within the LLVM object directory tree. +They *are not* executed inside of the LLVM source tree. This is because +the test suite creates temporary files during execution. + +To run the test suite, you need to use the following steps: + +#. ``cd`` into the ``llvm/projects`` directory in your source tree. +#. Check out the ``test-suite`` module with: + + .. code-block:: bash + + % svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite + + This will get the test suite into ``llvm/projects/test-suite``. + +#. Configure and build ``llvm``. + +#. Configure and build ``llvm-gcc``. + +#. Install ``llvm-gcc`` somewhere. + +#. *Re-configure* ``llvm`` from the top level of each build tree (LLVM + object directory tree) in which you want to run the test suite, just + as you do before building LLVM. + + During the *re-configuration*, you must either: (1) have ``llvm-gcc`` + you just built in your path, or (2) specify the directory where your + just-built ``llvm-gcc`` is installed using + ``--with-llvmgccdir=$LLVM_GCC_DIR``. + + You must also tell the configure machinery that the test suite is + available so it can be configured for your build tree: + + .. code-block:: bash + + % cd $LLVM_OBJ_ROOT ; $LLVM_SRC_ROOT/configure [--with-llvmgccdir=$LLVM_GCC_DIR] + + [Remember that ``$LLVM_GCC_DIR`` is the directory where you + *installed* llvm-gcc, not its src or obj directory.] + +#. You can now run the test suite from your build tree as follows: + + .. code-block:: bash + + % cd $LLVM_OBJ_ROOT/projects/test-suite + % make + +Note that the second and third steps only need to be done once. After +you have the suite checked out and configured, you don't need to do it +again (unless the test code or configure script changes). + +Configuring External Tests +-------------------------- + +In order to run the External tests in the ``test-suite`` module, you +must specify *--with-externals*. This must be done during the +*re-configuration* step (see above), and the ``llvm`` re-configuration +must recognize the previously-built ``llvm-gcc``. If any of these is +missing or neglected, the External tests won't work. + +* *--with-externals* + +* *--with-externals=* + +This tells LLVM where to find any external tests. They are expected to +be in specifically named subdirectories of <``directory``>. If +``directory`` is left unspecified, ``configure`` uses the default value +``/home/vadve/shared/benchmarks/speccpu2000/benchspec``. Subdirectory +names known to LLVM include: + +* spec95 + +* speccpu2000 + +* speccpu2006 + +* povray31 + +Others are added from time to time, and can be determined from +``configure``. + +Running different tests +----------------------- + +In addition to the regular "whole program" tests, the ``test-suite`` +module also provides a mechanism for compiling the programs in different +ways. If the variable TEST is defined on the ``gmake`` command line, the +test system will include a Makefile named +``TEST..Makefile``. This Makefile can modify +build rules to yield different results. + +For example, the LLVM nightly tester uses ``TEST.nightly.Makefile`` to +create the nightly test reports. To run the nightly tests, run +``gmake TEST=nightly``. + +There are several TEST Makefiles available in the tree. Some of them are +designed for internal LLVM research and will not work outside of the +LLVM research group. They may still be valuable, however, as a guide to +writing your own TEST Makefile for any optimization or analysis passes +that you develop with LLVM. + +Generating test output +---------------------- + +There are a number of ways to run the tests and generate output. The +most simple one is simply running ``gmake`` with no arguments. This will +compile and run all programs in the tree using a number of different +methods and compare results. Any failures are reported in the output, +but are likely drowned in the other output. Passes are not reported +explicitly. + +Somewhat better is running ``gmake TEST=sometest test``, which runs the +specified test and usually adds per-program summaries to the output +(depending on which sometest you use). For example, the ``nightly`` test +explicitly outputs TEST-PASS or TEST-FAIL for every test after each +program. Though these lines are still drowned in the output, it's easy +to grep the output logs in the Output directories. + +Even better are the ``report`` and ``report.format`` targets (where +``format`` is one of ``html``, ``csv``, ``text`` or ``graphs``). The +exact contents of the report are dependent on which ``TEST`` you are +running, but the text results are always shown at the end of the run and +the results are always stored in the ``report..format`` file (when +running with ``TEST=``). The ``report`` also generate a file +called ``report..raw.out`` containing the output of the entire +test run. + +Writing custom tests for the test suite +--------------------------------------- + +Assuming you can run the test suite, (e.g. +"``gmake TEST=nightly report``" should work), it is really easy to run +optimizations or code generator components against every program in the +tree, collecting statistics or running custom checks for correctness. At +base, this is how the nightly tester works, it's just one example of a +general framework. + +Lets say that you have an LLVM optimization pass, and you want to see +how many times it triggers. First thing you should do is add an LLVM +`statistic `_ to your pass, which will +tally counts of things you care about. + +Following this, you can set up a test and a report that collects these +and formats them for easy viewing. This consists of two files, a +"``test-suite/TEST.XXX.Makefile``" fragment (where XXX is the name of +your test) and a "``test-suite/TEST.XXX.report``" file that indicates +how to format the output into a table. There are many example reports of +various levels of sophistication included with the test suite, and the +framework is very general. + +If you are interested in testing an optimization pass, check out the +"libcalls" test as an example. It can be run like this: + +.. code-block:: bash + + % cd llvm/projects/test-suite/MultiSource/Benchmarks # or some other level + % make TEST=libcalls report + +This will do a bunch of stuff, then eventually print a table like this: + +:: + + Name | total | #exit | + ... + FreeBench/analyzer/analyzer | 51 | 6 | + FreeBench/fourinarow/fourinarow | 1 | 1 | + FreeBench/neural/neural | 19 | 9 | + FreeBench/pifft/pifft | 5 | 3 | + MallocBench/cfrac/cfrac | 1 | * | + MallocBench/espresso/espresso | 52 | 12 | + MallocBench/gs/gs | 4 | * | + Prolangs-C/TimberWolfMC/timberwolfmc | 302 | * | + Prolangs-C/agrep/agrep | 33 | 12 | + Prolangs-C/allroots/allroots | * | * | + Prolangs-C/assembler/assembler | 47 | * | + Prolangs-C/bison/mybison | 74 | * | + ... + +This basically is grepping the -stats output and displaying it in a +table. You can also use the "TEST=libcalls report.html" target to get +the table in HTML form, similarly for report.csv and report.tex. + +The source for this is in ``test-suite/TEST.libcalls.*``. The format is +pretty simple: the Makefile indicates how to run the test (in this case, +"``opt -simplify-libcalls -stats``"), and the report contains one line +for each column of the output. The first value is the header for the +column and the second is the regex to grep the output of the command +for. There are lots of example reports that can do fancy stuff. diff --git a/docs/TestingGuide.rst b/docs/TestingGuide.rst new file mode 100644 index 00000000..c9a35cd7 --- /dev/null +++ b/docs/TestingGuide.rst @@ -0,0 +1,517 @@ +================================= +LLVM Testing Infrastructure Guide +================================= + +.. contents:: + :local: + +.. toctree:: + :hidden: + + TestSuiteMakefileGuide + +Overview +======== + +This document is the reference manual for the LLVM testing +infrastructure. It documents the structure of the LLVM testing +infrastructure, the tools needed to use it, and how to add and run +tests. + +Requirements +============ + +In order to use the LLVM testing infrastructure, you will need all of the +software required to build LLVM, as well as `Python `_ 2.5 or +later. + +LLVM testing infrastructure organization +======================================== + +The LLVM testing infrastructure contains two major categories of tests: +regression tests and whole programs. The regression tests are contained +inside the LLVM repository itself under ``llvm/test`` and are expected +to always pass -- they should be run before every commit. + +The whole programs tests are referred to as the "LLVM test suite" (or +"test-suite") and are in the ``test-suite`` module in subversion. For +historical reasons, these tests are also referred to as the "nightly +tests" in places, which is less ambiguous than "test-suite" and remains +in use although we run them much more often than nightly. + +Regression tests +---------------- + +The regression tests are small pieces of code that test a specific +feature of LLVM or trigger a specific bug in LLVM. The language they are +written in depends on the part of LLVM being tested. These tests are driven by +the :doc:`Lit ` testing tool (which is part of LLVM), and +are located in the ``llvm/test`` directory. + +Typically when a bug is found in LLVM, a regression test containing just +enough code to reproduce the problem should be written and placed +somewhere underneath this directory. For example, it can be a small +piece of LLVM IR distilled from an actual application or benchmark. + +``test-suite`` +-------------- + +The test suite contains whole programs, which are pieces of code which +can be compiled and linked into a stand-alone program that can be +executed. These programs are generally written in high level languages +such as C or C++. + +These programs are compiled using a user specified compiler and set of +flags, and then executed to capture the program output and timing +information. The output of these programs is compared to a reference +output to ensure that the program is being compiled correctly. + +In addition to compiling and executing programs, whole program tests +serve as a way of benchmarking LLVM performance, both in terms of the +efficiency of the programs generated as well as the speed with which +LLVM compiles, optimizes, and generates code. + +The test-suite is located in the ``test-suite`` Subversion module. + +Debugging Information tests +--------------------------- + +The test suite contains tests to check quality of debugging information. +The test are written in C based languages or in LLVM assembly language. + +These tests are compiled and run under a debugger. The debugger output +is checked to validate of debugging information. See README.txt in the +test suite for more information . This test suite is located in the +``debuginfo-tests`` Subversion module. + +Quick start +=========== + +The tests are located in two separate Subversion modules. The +regressions tests are in the main "llvm" module under the directory +``llvm/test`` (so you get these tests for free with the main LLVM tree). +Use ``make check-all`` to run the regression tests after building LLVM. + +The more comprehensive test suite that includes whole programs in C and C++ +is in the ``test-suite`` module. See :ref:`test-suite Quickstart +` for more information on running these tests. + +Regression tests +---------------- + +To run all of the LLVM regression tests, use the master Makefile in the +``llvm/test`` directory. LLVM Makefiles require GNU Make (read the :doc:`LLVM +Makefile Guide ` for more details): + +.. code-block:: bash + + % make -C llvm/test + +or: + +.. code-block:: bash + + % make check + +If you have `Clang `_ checked out and built, you +can run the LLVM and Clang tests simultaneously using: + +.. code-block:: bash + + % make check-all + +To run the tests with Valgrind (Memcheck by default), use the ``LIT_ARGS`` make +variable to pass the required options to lit. For example, you can use: + +.. code-block:: bash + + % make check LIT_ARGS="-v --vg --vg-leak" + +to enable testing with valgrind and with leak checking enabled. + +To run individual tests or subsets of tests, you can use the ``llvm-lit`` +script which is built as part of LLVM. For example, to run the +``Integer/BitPacked.ll`` test by itself you can run: + +.. code-block:: bash + + % llvm-lit ~/llvm/test/Integer/BitPacked.ll + +or to run all of the ARM CodeGen tests: + +.. code-block:: bash + + % llvm-lit ~/llvm/test/CodeGen/ARM + +For more information on using the :program:`lit` tool, see ``llvm-lit --help`` +or the :doc:`lit man page `. + +Debugging Information tests +--------------------------- + +To run debugging information tests simply checkout the tests inside +clang/test directory. + +.. code-block:: bash + + % cd clang/test + % svn co http://llvm.org/svn/llvm-project/debuginfo-tests/trunk debuginfo-tests + +These tests are already set up to run as part of clang regression tests. + +Regression test structure +========================= + +The LLVM regression tests are driven by :program:`lit` and are located in the +``llvm/test`` directory. + +This directory contains a large array of small tests that exercise +various features of LLVM and to ensure that regressions do not occur. +The directory is broken into several sub-directories, each focused on a +particular area of LLVM. + +Writing new regression tests +---------------------------- + +The regression test structure is very simple, but does require some +information to be set. This information is gathered via ``configure`` +and is written to a file, ``test/lit.site.cfg`` in the build directory. +The ``llvm/test`` Makefile does this work for you. + +In order for the regression tests to work, each directory of tests must +have a ``lit.local.cfg`` file. :program:`lit` looks for this file to determine +how to run the tests. This file is just Python code and thus is very +flexible, but we've standardized it for the LLVM regression tests. If +you're adding a directory of tests, just copy ``lit.local.cfg`` from +another directory to get running. The standard ``lit.local.cfg`` simply +specifies which files to look in for tests. Any directory that contains +only directories does not need the ``lit.local.cfg`` file. Read the :doc:`Lit +documentation ` for more information. + +Each test file must contain lines starting with "RUN:" that tell :program:`lit` +how to run it. If there are no RUN lines, :program:`lit` will issue an error +while running a test. + +RUN lines are specified in the comments of the test program using the +keyword ``RUN`` followed by a colon, and lastly the command (pipeline) +to execute. Together, these lines form the "script" that :program:`lit` +executes to run the test case. The syntax of the RUN lines is similar to a +shell's syntax for pipelines including I/O redirection and variable +substitution. However, even though these lines may *look* like a shell +script, they are not. RUN lines are interpreted by :program:`lit`. +Consequently, the syntax differs from shell in a few ways. You can specify +as many RUN lines as needed. + +:program:`lit` performs substitution on each RUN line to replace LLVM tool names +with the full paths to the executable built for each tool (in +``$(LLVM_OBJ_ROOT)/$(BuildMode)/bin)``. This ensures that :program:`lit` does +not invoke any stray LLVM tools in the user's path during testing. + +Each RUN line is executed on its own, distinct from other lines unless +its last character is ``\``. This continuation character causes the RUN +line to be concatenated with the next one. In this way you can build up +long pipelines of commands without making huge line lengths. The lines +ending in ``\`` are concatenated until a RUN line that doesn't end in +``\`` is found. This concatenated set of RUN lines then constitutes one +execution. :program:`lit` will substitute variables and arrange for the pipeline +to be executed. If any process in the pipeline fails, the entire line (and +test case) fails too. + +Below is an example of legal RUN lines in a ``.ll`` file: + +.. code-block:: llvm + + ; RUN: llvm-as < %s | llvm-dis > %t1 + ; RUN: llvm-dis < %s.bc-13 > %t2 + ; RUN: diff %t1 %t2 + +As with a Unix shell, the RUN lines permit pipelines and I/O +redirection to be used. + +There are some quoting rules that you must pay attention to when writing +your RUN lines. In general nothing needs to be quoted. :program:`lit` won't +strip off any quote characters so they will get passed to the invoked program. +To avoid this use curly braces to tell :program:`lit` that it should treat +everything enclosed as one value. + +In general, you should strive to keep your RUN lines as simple as possible, +using them only to run tools that generate textual output you can then examine. +The recommended way to examine output to figure out if the test passes is using +the :doc:`FileCheck tool `. *[The usage of grep in RUN +lines is deprecated - please do not send or commit patches that use it.]* + +Fragile tests +------------- + +It is easy to write a fragile test that would fail spuriously if the tool being +tested outputs a full path to the input file. For example, :program:`opt` by +default outputs a ``ModuleID``: + +.. code-block:: console + + $ cat example.ll + define i32 @main() nounwind { + ret i32 0 + } + + $ opt -S /path/to/example.ll + ; ModuleID = '/path/to/example.ll' + + define i32 @main() nounwind { + ret i32 0 + } + +``ModuleID`` can unexpetedly match against ``CHECK`` lines. For example: + +.. code-block:: llvm + + ; RUN: opt -S %s | FileCheck + + define i32 @main() nounwind { + ; CHECK-NOT: load + ret i32 0 + } + +This test will fail if placed into a ``download`` directory. + +To make your tests robust, always use ``opt ... < %s`` in the RUN line. +:program:`opt` does not output a ``ModuleID`` when input comes from stdin. + +Platform-Specific Tests +----------------------- + +Whenever adding tests that require the knowledge of a specific platform, +either related to code generated, specific output or back-end features, +you must make sure to isolate the features, so that buildbots that +run on different architectures (and don't even compile all back-ends), +don't fail. + +The first problem is to check for target-specific output, for example sizes +of structures, paths and architecture names, for example: + +* Tests containing Windows paths will fail on Linux and vice-versa. +* Tests that check for ``x86_64`` somewhere in the text will fail anywhere else. +* Tests where the debug information calculates the size of types and structures. + +Also, if the test rely on any behaviour that is coded in any back-end, it must +go in its own directory. So, for instance, code generator tests for ARM go +into ``test/CodeGen/ARM`` and so on. Those directories contain a special +``lit`` configuration file that ensure all tests in that directory will +only run if a specific back-end is compiled and available. + +For instance, on ``test/CodeGen/ARM``, the ``lit.local.cfg`` is: + +.. code-block:: python + + config.suffixes = ['.ll', '.c', '.cpp', '.test'] + targets = set(config.root.targets_to_build.split()) + if not 'ARM' in targets: + config.unsupported = True + +Other platform-specific tests are those that depend on a specific feature +of a specific sub-architecture, for example only to Intel chips that support ``AVX2``. + +For instance, ``test/CodeGen/X86/psubus.ll`` tests three sub-architecture +variants: + +.. code-block:: llvm + + ; RUN: llc -mcpu=core2 < %s | FileCheck %s -check-prefix=SSE2 + ; RUN: llc -mcpu=corei7-avx < %s | FileCheck %s -check-prefix=AVX1 + ; RUN: llc -mcpu=core-avx2 < %s | FileCheck %s -check-prefix=AVX2 + +And the checks are different: + +.. code-block:: llvm + + ; SSE2: @test1 + ; SSE2: psubusw LCPI0_0(%rip), %xmm0 + ; AVX1: @test1 + ; AVX1: vpsubusw LCPI0_0(%rip), %xmm0, %xmm0 + ; AVX2: @test1 + ; AVX2: vpsubusw LCPI0_0(%rip), %xmm0, %xmm0 + +So, if you're testing for a behaviour that you know is platform-specific or +depends on special features of sub-architectures, you must add the specific +triple, test with the specific FileCheck and put it into the specific +directory that will filter out all other architectures. + + +Variables and substitutions +--------------------------- + +With a RUN line there are a number of substitutions that are permitted. +To make a substitution just write the variable's name preceded by a ``$``. +Additionally, for compatibility reasons with previous versions of the +test library, certain names can be accessed with an alternate syntax: a +% prefix. These alternates are deprecated and may go away in a future +version. + +Here are the available variable names. The alternate syntax is listed in +parentheses. + +``$test`` (``%s``) + The full path to the test case's source. This is suitable for passing on + the command line as the input to an LLVM tool. + +``%(line)``, ``%(line+)``, ``%(line-)`` + The number of the line where this variable is used, with an optional + integer offset. This can be used in tests with multiple RUN lines, + which reference test file's line numbers. + +``$srcdir`` + The source directory from where the ``make check`` was run. + +``objdir`` + The object directory that corresponds to the ``$srcdir``. + +``subdir`` + A partial path from the ``test`` directory that contains the + sub-directory that contains the test source being executed. + +``srcroot`` + The root directory of the LLVM src tree. + +``objroot`` + The root directory of the LLVM object tree. This could be the same as + the srcroot. + +``path`` + The path to the directory that contains the test case source. This is + for locating any supporting files that are not generated by the test, + but used by the test. + +``tmp`` + The path to a temporary file name that could be used for this test case. + The file name won't conflict with other test cases. You can append to it + if you need multiple temporaries. This is useful as the destination of + some redirected output. + +``target_triplet`` (``%target_triplet``) + The target triplet that corresponds to the current host machine (the one + running the test cases). This should probably be called "host". + +``link`` (``%link``) + This full link command used to link LLVM executables. This has all the + configured ``-I``, ``-L`` and ``-l`` options. + +``shlibext`` (``%shlibext``) + The suffix for the host platforms shared library (DLL) files. This + includes the period as the first character. + +To add more variables, look at ``test/lit.cfg``. + +Other Features +-------------- + +To make RUN line writing easier, there are several helper scripts and programs +in the ``llvm/test/Scripts`` directory. This directory is in the PATH +when running tests, so you can just call these scripts using their name. +For example: + +``ignore`` + This script runs its arguments and then always returns 0. This is useful + in cases where the test needs to cause a tool to generate an error (e.g. + to check the error output). However, any program in a pipeline that + returns a non-zero result will cause the test to fail. This script + overcomes that issue and nicely documents that the test case is + purposefully ignoring the result code of the tool +``not`` + This script runs its arguments and then inverts the result code from it. + Zero result codes become 1. Non-zero result codes become 0. + +Sometimes it is necessary to mark a test case as "expected fail" or +XFAIL. You can easily mark a test as XFAIL just by including ``XFAIL:`` +on a line near the top of the file. This signals that the test case +should succeed if the test fails. Such test cases are counted separately +by the testing tool. To specify an expected fail, use the XFAIL keyword +in the comments of the test program followed by a colon and one or more +failure patterns. Each failure pattern can be either ``*`` (to specify +fail everywhere), or a part of a target triple (indicating the test +should fail on that platform), or the name of a configurable feature +(for example, ``loadable_module``). If there is a match, the test is +expected to fail. If not, the test is expected to succeed. To XFAIL +everywhere just specify ``XFAIL: *``. Here is an example of an ``XFAIL`` +line: + +.. code-block:: llvm + + ; XFAIL: darwin,sun + +To make the output more useful, :program:`lit` will scan +the lines of the test case for ones that contain a pattern that matches +``PR[0-9]+``. This is the syntax for specifying a PR (Problem Report) number +that is related to the test case. The number after "PR" specifies the +LLVM bugzilla number. When a PR number is specified, it will be used in +the pass/fail reporting. This is useful to quickly get some context when +a test fails. + +Finally, any line that contains "END." will cause the special +interpretation of lines to terminate. This is generally done right after +the last RUN: line. This has two side effects: + +(a) it prevents special interpretation of lines that are part of the test + program, not the instructions to the test case, and + +(b) it speeds things up for really big test cases by avoiding + interpretation of the remainder of the file. + +``test-suite`` Overview +======================= + +The ``test-suite`` module contains a number of programs that can be +compiled and executed. The ``test-suite`` includes reference outputs for +all of the programs, so that the output of the executed program can be +checked for correctness. + +``test-suite`` tests are divided into three types of tests: MultiSource, +SingleSource, and External. + +- ``test-suite/SingleSource`` + + The SingleSource directory contains test programs that are only a + single source file in size. These are usually small benchmark + programs or small programs that calculate a particular value. Several + such programs are grouped together in each directory. + +- ``test-suite/MultiSource`` + + The MultiSource directory contains subdirectories which contain + entire programs with multiple source files. Large benchmarks and + whole applications go here. + +- ``test-suite/External`` + + The External directory contains Makefiles for building code that is + external to (i.e., not distributed with) LLVM. The most prominent + members of this directory are the SPEC 95 and SPEC 2000 benchmark + suites. The ``External`` directory does not contain these actual + tests, but only the Makefiles that know how to properly compile these + programs from somewhere else. When using ``LNT``, use the + ``--test-externals`` option to include these tests in the results. + +.. _test-suite-quickstart: + +``test-suite`` Quickstart +------------------------- + +The modern way of running the ``test-suite`` is focused on testing and +benchmarking complete compilers using the +`LNT `_ testing infrastructure. + +For more information on using LNT to execute the ``test-suite``, please +see the `LNT Quickstart `_ +documentation. + +``test-suite`` Makefiles +------------------------ + +Historically, the ``test-suite`` was executed using a complicated setup +of Makefiles. The LNT based approach above is recommended for most +users, but there are some testing scenarios which are not supported by +the LNT approach. In addition, LNT currently uses the Makefile setup +under the covers and so developers who are interested in how LNT works +under the hood may want to understand the Makefile based setup. + +For more information on the ``test-suite`` Makefile setup, please see +the :doc:`Test Suite Makefile Guide `. diff --git a/docs/Vectorizers.rst b/docs/Vectorizers.rst new file mode 100644 index 00000000..61ebca2b --- /dev/null +++ b/docs/Vectorizers.rst @@ -0,0 +1,340 @@ +========================== +Auto-Vectorization in LLVM +========================== + +.. contents:: + :local: + +LLVM has two vectorizers: The :ref:`Loop Vectorizer `, +which operates on Loops, and the :ref:`SLP Vectorizer +`. These vectorizers +focus on different optimization opportunities and use different techniques. +The SLP vectorizer merges multiple scalars that are found in the code into +vectors while the Loop Vectorizer widens instructions in loops +to operate on multiple consecutive iterations. + +Both the Loop Vectorizer and the SLP Vectorizer are enabled by default. + +.. _loop-vectorizer: + +The Loop Vectorizer +=================== + +Usage +----- + +The Loop Vectorizer is enabled by default, but it can be disabled +through clang using the command line flag: + +.. code-block:: console + + $ clang ... -fno-vectorize file.c + +Command line flags +^^^^^^^^^^^^^^^^^^ + +The loop vectorizer uses a cost model to decide on the optimal vectorization factor +and unroll factor. However, users of the vectorizer can force the vectorizer to use +specific values. Both 'clang' and 'opt' support the flags below. + +Users can control the vectorization SIMD width using the command line flag "-force-vector-width". + +.. code-block:: console + + $ clang -mllvm -force-vector-width=8 ... + $ opt -loop-vectorize -force-vector-width=8 ... + +Users can control the unroll factor using the command line flag "-force-vector-unroll" + +.. code-block:: console + + $ clang -mllvm -force-vector-unroll=2 ... + $ opt -loop-vectorize -force-vector-unroll=2 ... + +Features +-------- + +The LLVM Loop Vectorizer has a number of features that allow it to vectorize +complex loops. + +Loops with unknown trip count +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Loop Vectorizer supports loops with an unknown trip count. +In the loop below, the iteration ``start`` and ``finish`` points are unknown, +and the Loop Vectorizer has a mechanism to vectorize loops that do not start +at zero. In this example, 'n' may not be a multiple of the vector width, and +the vectorizer has to execute the last few iterations as scalar code. Keeping +a scalar copy of the loop increases the code size. + +.. code-block:: c++ + + void bar(float *A, float* B, float K, int start, int end) { + for (int i = start; i < end; ++i) + A[i] *= B[i] + K; + } + +Runtime Checks of Pointers +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the example below, if the pointers A and B point to consecutive addresses, +then it is illegal to vectorize the code because some elements of A will be +written before they are read from array B. + +Some programmers use the 'restrict' keyword to notify the compiler that the +pointers are disjointed, but in our example, the Loop Vectorizer has no way of +knowing that the pointers A and B are unique. The Loop Vectorizer handles this +loop by placing code that checks, at runtime, if the arrays A and B point to +disjointed memory locations. If arrays A and B overlap, then the scalar version +of the loop is executed. + +.. code-block:: c++ + + void bar(float *A, float* B, float K, int n) { + for (int i = 0; i < n; ++i) + A[i] *= B[i] + K; + } + + +Reductions +^^^^^^^^^^ + +In this example the ``sum`` variable is used by consecutive iterations of +the loop. Normally, this would prevent vectorization, but the vectorizer can +detect that 'sum' is a reduction variable. The variable 'sum' becomes a vector +of integers, and at the end of the loop the elements of the array are added +together to create the correct result. We support a number of different +reduction operations, such as addition, multiplication, XOR, AND and OR. + +.. code-block:: c++ + + int foo(int *A, int *B, int n) { + unsigned sum = 0; + for (int i = 0; i < n; ++i) + sum += A[i] + 5; + return sum; + } + +We support floating point reduction operations when `-ffast-math` is used. + +Inductions +^^^^^^^^^^ + +In this example the value of the induction variable ``i`` is saved into an +array. The Loop Vectorizer knows to vectorize induction variables. + +.. code-block:: c++ + + void bar(float *A, float* B, float K, int n) { + for (int i = 0; i < n; ++i) + A[i] = i; + } + +If Conversion +^^^^^^^^^^^^^ + +The Loop Vectorizer is able to "flatten" the IF statement in the code and +generate a single stream of instructions. The Loop Vectorizer supports any +control flow in the innermost loop. The innermost loop may contain complex +nesting of IFs, ELSEs and even GOTOs. + +.. code-block:: c++ + + int foo(int *A, int *B, int n) { + unsigned sum = 0; + for (int i = 0; i < n; ++i) + if (A[i] > B[i]) + sum += A[i] + 5; + return sum; + } + +Pointer Induction Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example uses the "accumulate" function of the standard c++ library. This +loop uses C++ iterators, which are pointers, and not integer indices. +The Loop Vectorizer detects pointer induction variables and can vectorize +this loop. This feature is important because many C++ programs use iterators. + +.. code-block:: c++ + + int baz(int *A, int n) { + return std::accumulate(A, A + n, 0); + } + +Reverse Iterators +^^^^^^^^^^^^^^^^^ + +The Loop Vectorizer can vectorize loops that count backwards. + +.. code-block:: c++ + + int foo(int *A, int *B, int n) { + for (int i = n; i > 0; --i) + A[i] +=1; + } + +Scatter / Gather +^^^^^^^^^^^^^^^^ + +The Loop Vectorizer can vectorize code that becomes a sequence of scalar instructions +that scatter/gathers memory. + +.. code-block:: c++ + + int foo(int *A, int *B, int n, int k) { + for (int i = 0; i < n; ++i) + A[i*7] += B[i*k]; + } + +Vectorization of Mixed Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Loop Vectorizer can vectorize programs with mixed types. The Vectorizer +cost model can estimate the cost of the type conversion and decide if +vectorization is profitable. + +.. code-block:: c++ + + int foo(int *A, char *B, int n, int k) { + for (int i = 0; i < n; ++i) + A[i] += 4 * B[i]; + } + +Global Structures Alias Analysis +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Access to global structures can also be vectorized, with alias analysis being +used to make sure accesses don't alias. Run-time checks can also be added on +pointer access to structure members. + +Many variations are supported, but some that rely on undefined behaviour being +ignored (as other compilers do) are still being left un-vectorized. + +.. code-block:: c++ + + struct { int A[100], K, B[100]; } Foo; + + int foo() { + for (int i = 0; i < 100; ++i) + Foo.A[i] = Foo.B[i] + 100; + } + +Vectorization of function calls +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Loop Vectorize can vectorize intrinsic math functions. +See the table below for a list of these functions. + ++-----+-----+---------+ +| pow | exp | exp2 | ++-----+-----+---------+ +| sin | cos | sqrt | ++-----+-----+---------+ +| log |log2 | log10 | ++-----+-----+---------+ +|fabs |floor| ceil | ++-----+-----+---------+ +|fma |trunc|nearbyint| ++-----+-----+---------+ +| | | fmuladd | ++-----+-----+---------+ + +The loop vectorizer knows about special instructions on the target and will +vectorize a loop containing a function call that maps to the instructions. For +example, the loop below will be vectorized on Intel x86 if the SSE4.1 roundps +instruction is available. + +.. code-block:: c++ + + void foo(float *f) { + for (int i = 0; i != 1024; ++i) + f[i] = floorf(f[i]); + } + +Partial unrolling during vectorization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Modern processors feature multiple execution units, and only programs that contain a +high degree of parallelism can fully utilize the entire width of the machine. +The Loop Vectorizer increases the instruction level parallelism (ILP) by +performing partial-unrolling of loops. + +In the example below the entire array is accumulated into the variable 'sum'. +This is inefficient because only a single execution port can be used by the processor. +By unrolling the code the Loop Vectorizer allows two or more execution ports +to be used simultaneously. + +.. code-block:: c++ + + int foo(int *A, int *B, int n) { + unsigned sum = 0; + for (int i = 0; i < n; ++i) + sum += A[i]; + return sum; + } + +The Loop Vectorizer uses a cost model to decide when it is profitable to unroll loops. +The decision to unroll the loop depends on the register pressure and the generated code size. + +Performance +----------- + +This section shows the the execution time of Clang on a simple benchmark: +`gcc-loops `_. +This benchmarks is a collection of loops from the GCC autovectorization +`page `_ by Dorit Nuzman. + +The chart below compares GCC-4.7, ICC-13, and Clang-SVN with and without loop vectorization at -O3, tuned for "corei7-avx", running on a Sandybridge iMac. +The Y-axis shows the time in msec. Lower is better. The last column shows the geomean of all the kernels. + +.. image:: gcc-loops.png + +And Linpack-pc with the same configuration. Result is Mflops, higher is better. + +.. image:: linpack-pc.png + +.. _slp-vectorizer: + +The SLP Vectorizer +================== + +Details +------- + +The goal of SLP vectorization (a.k.a. superword-level parallelism) is +to combine similar independent instructions +into vector instructions. Memory accesses, arithmetic operations, comparison +operations, PHI-nodes, can all be vectorized using this technique. + +For example, the following function performs very similar operations on its +inputs (a1, b1) and (a2, b2). The basic-block vectorizer may combine these +into vector operations. + +.. code-block:: c++ + + void foo(int a1, int a2, int b1, int b2, int *A) { + A[0] = a1*(a1 + b1)/b1 + 50*b1/a1; + A[1] = a2*(a2 + b2)/b2 + 50*b2/a2; + } + +The SLP-vectorizer processes the code bottom-up, across basic blocks, in search of scalars to combine. + +Usage +------ + +The SLP Vectorizer is enabled by default, but it can be disabled +through clang using the command line flag: + +.. code-block:: console + + $ clang -fno-slp-vectorize file.c + +LLVM has a second basic block vectorization phase +which is more compile-time intensive (The BB vectorizer). This optimization +can be enabled through clang using the command line flag: + +.. code-block:: console + + $ clang -fslp-vectorize-aggressive file.c + diff --git a/docs/WritingAnLLVMBackend.rst b/docs/WritingAnLLVMBackend.rst new file mode 100644 index 00000000..35a2d164 --- /dev/null +++ b/docs/WritingAnLLVMBackend.rst @@ -0,0 +1,1935 @@ +======================= +Writing an LLVM Backend +======================= + +.. toctree:: + :hidden: + + HowToUseInstrMappings + +.. contents:: + :local: + +Introduction +============ + +This document describes techniques for writing compiler backends that convert +the LLVM Intermediate Representation (IR) to code for a specified machine or +other languages. Code intended for a specific machine can take the form of +either assembly code or binary code (usable for a JIT compiler). + +The backend of LLVM features a target-independent code generator that may +create output for several types of target CPUs --- including X86, PowerPC, +ARM, and SPARC. The backend may also be used to generate code targeted at SPUs +of the Cell processor or GPUs to support the execution of compute kernels. + +The document focuses on existing examples found in subdirectories of +``llvm/lib/Target`` in a downloaded LLVM release. In particular, this document +focuses on the example of creating a static compiler (one that emits text +assembly) for a SPARC target, because SPARC has fairly standard +characteristics, such as a RISC instruction set and straightforward calling +conventions. + +Audience +-------- + +The audience for this document is anyone who needs to write an LLVM backend to +generate code for a specific hardware or software target. + +Prerequisite Reading +-------------------- + +These essential documents must be read before reading this document: + +* `LLVM Language Reference Manual `_ --- a reference manual for + the LLVM assembly language. + +* :doc:`CodeGenerator` --- a guide to the components (classes and code + generation algorithms) for translating the LLVM internal representation into + machine code for a specified target. Pay particular attention to the + descriptions of code generation stages: Instruction Selection, Scheduling and + Formation, SSA-based Optimization, Register Allocation, Prolog/Epilog Code + Insertion, Late Machine Code Optimizations, and Code Emission. + +* :doc:`TableGenFundamentals` --- a document that describes the TableGen + (``tblgen``) application that manages domain-specific information to support + LLVM code generation. TableGen processes input from a target description + file (``.td`` suffix) and generates C++ code that can be used for code + generation. + +* :doc:`WritingAnLLVMPass` --- The assembly printer is a ``FunctionPass``, as + are several ``SelectionDAG`` processing steps. + +To follow the SPARC examples in this document, have a copy of `The SPARC +Architecture Manual, Version 8 `_ for +reference. For details about the ARM instruction set, refer to the `ARM +Architecture Reference Manual `_. For more about +the GNU Assembler format (``GAS``), see `Using As +`_, especially for the +assembly printer. "Using As" contains a list of target machine dependent +features. + +Basic Steps +----------- + +To write a compiler backend for LLVM that converts the LLVM IR to code for a +specified target (machine or other language), follow these steps: + +* Create a subclass of the ``TargetMachine`` class that describes + characteristics of your target machine. Copy existing examples of specific + ``TargetMachine`` class and header files; for example, start with + ``SparcTargetMachine.cpp`` and ``SparcTargetMachine.h``, but change the file + names for your target. Similarly, change code that references "``Sparc``" to + reference your target. + +* Describe the register set of the target. Use TableGen to generate code for + register definition, register aliases, and register classes from a + target-specific ``RegisterInfo.td`` input file. You should also write + additional code for a subclass of the ``TargetRegisterInfo`` class that + represents the class register file data used for register allocation and also + describes the interactions between registers. + +* Describe the instruction set of the target. Use TableGen to generate code + for target-specific instructions from target-specific versions of + ``TargetInstrFormats.td`` and ``TargetInstrInfo.td``. You should write + additional code for a subclass of the ``TargetInstrInfo`` class to represent + machine instructions supported by the target machine. + +* Describe the selection and conversion of the LLVM IR from a Directed Acyclic + Graph (DAG) representation of instructions to native target-specific + instructions. Use TableGen to generate code that matches patterns and + selects instructions based on additional information in a target-specific + version of ``TargetInstrInfo.td``. Write code for ``XXXISelDAGToDAG.cpp``, + where ``XXX`` identifies the specific target, to perform pattern matching and + DAG-to-DAG instruction selection. Also write code in ``XXXISelLowering.cpp`` + to replace or remove operations and data types that are not supported + natively in a SelectionDAG. + +* Write code for an assembly printer that converts LLVM IR to a GAS format for + your target machine. You should add assembly strings to the instructions + defined in your target-specific version of ``TargetInstrInfo.td``. You + should also write code for a subclass of ``AsmPrinter`` that performs the + LLVM-to-assembly conversion and a trivial subclass of ``TargetAsmInfo``. + +* Optionally, add support for subtargets (i.e., variants with different + capabilities). You should also write code for a subclass of the + ``TargetSubtarget`` class, which allows you to use the ``-mcpu=`` and + ``-mattr=`` command-line options. + +* Optionally, add JIT support and create a machine code emitter (subclass of + ``TargetJITInfo``) that is used to emit binary code directly into memory. + +In the ``.cpp`` and ``.h``. files, initially stub up these methods and then +implement them later. Initially, you may not know which private members that +the class will need and which components will need to be subclassed. + +Preliminaries +------------- + +To actually create your compiler backend, you need to create and modify a few +files. The absolute minimum is discussed here. But to actually use the LLVM +target-independent code generator, you must perform the steps described in the +:doc:`LLVM Target-Independent Code Generator ` document. + +First, you should create a subdirectory under ``lib/Target`` to hold all the +files related to your target. If your target is called "Dummy", create the +directory ``lib/Target/Dummy``. + +In this new directory, create a ``Makefile``. It is easiest to copy a +``Makefile`` of another target and modify it. It should at least contain the +``LEVEL``, ``LIBRARYNAME`` and ``TARGET`` variables, and then include +``$(LEVEL)/Makefile.common``. The library can be named ``LLVMDummy`` (for +example, see the MIPS target). Alternatively, you can split the library into +``LLVMDummyCodeGen`` and ``LLVMDummyAsmPrinter``, the latter of which should be +implemented in a subdirectory below ``lib/Target/Dummy`` (for example, see the +PowerPC target). + +Note that these two naming schemes are hardcoded into ``llvm-config``. Using +any other naming scheme will confuse ``llvm-config`` and produce a lot of +(seemingly unrelated) linker errors when linking ``llc``. + +To make your target actually do something, you need to implement a subclass of +``TargetMachine``. This implementation should typically be in the file +``lib/Target/DummyTargetMachine.cpp``, but any file in the ``lib/Target`` +directory will be built and should work. To use LLVM's target independent code +generator, you should do what all current machine backends do: create a +subclass of ``LLVMTargetMachine``. (To create a target from scratch, create a +subclass of ``TargetMachine``.) + +To get LLVM to actually build and link your target, you need to add it to the +``TARGETS_TO_BUILD`` variable. To do this, you modify the configure script to +know about your target when parsing the ``--enable-targets`` option. Search +the configure script for ``TARGETS_TO_BUILD``, add your target to the lists +there (some creativity required), and then reconfigure. Alternatively, you can +change ``autotools/configure.ac`` and regenerate configure by running +``./autoconf/AutoRegen.sh``. + +Target Machine +============== + +``LLVMTargetMachine`` is designed as a base class for targets implemented with +the LLVM target-independent code generator. The ``LLVMTargetMachine`` class +should be specialized by a concrete target class that implements the various +virtual methods. ``LLVMTargetMachine`` is defined as a subclass of +``TargetMachine`` in ``include/llvm/Target/TargetMachine.h``. The +``TargetMachine`` class implementation (``TargetMachine.cpp``) also processes +numerous command-line options. + +To create a concrete target-specific subclass of ``LLVMTargetMachine``, start +by copying an existing ``TargetMachine`` class and header. You should name the +files that you create to reflect your specific target. For instance, for the +SPARC target, name the files ``SparcTargetMachine.h`` and +``SparcTargetMachine.cpp``. + +For a target machine ``XXX``, the implementation of ``XXXTargetMachine`` must +have access methods to obtain objects that represent target components. These +methods are named ``get*Info``, and are intended to obtain the instruction set +(``getInstrInfo``), register set (``getRegisterInfo``), stack frame layout +(``getFrameInfo``), and similar information. ``XXXTargetMachine`` must also +implement the ``getDataLayout`` method to access an object with target-specific +data characteristics, such as data type size and alignment requirements. + +For instance, for the SPARC target, the header file ``SparcTargetMachine.h`` +declares prototypes for several ``get*Info`` and ``getDataLayout`` methods that +simply return a class member. + +.. code-block:: c++ + + namespace llvm { + + class Module; + + class SparcTargetMachine : public LLVMTargetMachine { + const DataLayout DataLayout; // Calculates type size & alignment + SparcSubtarget Subtarget; + SparcInstrInfo InstrInfo; + TargetFrameInfo FrameInfo; + + protected: + virtual const TargetAsmInfo *createTargetAsmInfo() const; + + public: + SparcTargetMachine(const Module &M, const std::string &FS); + + virtual const SparcInstrInfo *getInstrInfo() const {return &InstrInfo; } + virtual const TargetFrameInfo *getFrameInfo() const {return &FrameInfo; } + virtual const TargetSubtarget *getSubtargetImpl() const{return &Subtarget; } + virtual const TargetRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + virtual const DataLayout *getDataLayout() const { return &DataLayout; } + static unsigned getModuleMatchQuality(const Module &M); + + // Pass Pipeline Configuration + virtual bool addInstSelector(PassManagerBase &PM, bool Fast); + virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast); + }; + + } // end namespace llvm + +* ``getInstrInfo()`` +* ``getRegisterInfo()`` +* ``getFrameInfo()`` +* ``getDataLayout()`` +* ``getSubtargetImpl()`` + +For some targets, you also need to support the following methods: + +* ``getTargetLowering()`` +* ``getJITInfo()`` + +In addition, the ``XXXTargetMachine`` constructor should specify a +``TargetDescription`` string that determines the data layout for the target +machine, including characteristics such as pointer size, alignment, and +endianness. For example, the constructor for ``SparcTargetMachine`` contains +the following: + +.. code-block:: c++ + + SparcTargetMachine::SparcTargetMachine(const Module &M, const std::string &FS) + : DataLayout("E-p:32:32-f128:128:128"), + Subtarget(M, FS), InstrInfo(Subtarget), + FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) { + } + +Hyphens separate portions of the ``TargetDescription`` string. + +* An upper-case "``E``" in the string indicates a big-endian target data model. + A lower-case "``e``" indicates little-endian. + +* "``p:``" is followed by pointer information: size, ABI alignment, and + preferred alignment. If only two figures follow "``p:``", then the first + value is pointer size, and the second value is both ABI and preferred + alignment. + +* Then a letter for numeric type alignment: "``i``", "``f``", "``v``", or + "``a``" (corresponding to integer, floating point, vector, or aggregate). + "``i``", "``v``", or "``a``" are followed by ABI alignment and preferred + alignment. "``f``" is followed by three values: the first indicates the size + of a long double, then ABI alignment, and then ABI preferred alignment. + +Target Registration +=================== + +You must also register your target with the ``TargetRegistry``, which is what +other LLVM tools use to be able to lookup and use your target at runtime. The +``TargetRegistry`` can be used directly, but for most targets there are helper +templates which should take care of the work for you. + +All targets should declare a global ``Target`` object which is used to +represent the target during registration. Then, in the target's ``TargetInfo`` +library, the target should define that object and use the ``RegisterTarget`` +template to register the target. For example, the Sparc registration code +looks like this: + +.. code-block:: c++ + + Target llvm::TheSparcTarget; + + extern "C" void LLVMInitializeSparcTargetInfo() { + RegisterTarget + X(TheSparcTarget, "sparc", "Sparc"); + } + +This allows the ``TargetRegistry`` to look up the target by name or by target +triple. In addition, most targets will also register additional features which +are available in separate libraries. These registration steps are separate, +because some clients may wish to only link in some parts of the target --- the +JIT code generator does not require the use of the assembler printer, for +example. Here is an example of registering the Sparc assembly printer: + +.. code-block:: c++ + + extern "C" void LLVMInitializeSparcAsmPrinter() { + RegisterAsmPrinter X(TheSparcTarget); + } + +For more information, see "`llvm/Target/TargetRegistry.h +`_". + +Register Set and Register Classes +================================= + +You should describe a concrete target-specific class that represents the +register file of a target machine. This class is called ``XXXRegisterInfo`` +(where ``XXX`` identifies the target) and represents the class register file +data that is used for register allocation. It also describes the interactions +between registers. + +You also need to define register classes to categorize related registers. A +register class should be added for groups of registers that are all treated the +same way for some instruction. Typical examples are register classes for +integer, floating-point, or vector registers. A register allocator allows an +instruction to use any register in a specified register class to perform the +instruction in a similar manner. Register classes allocate virtual registers +to instructions from these sets, and register classes let the +target-independent register allocator automatically choose the actual +registers. + +Much of the code for registers, including register definition, register +aliases, and register classes, is generated by TableGen from +``XXXRegisterInfo.td`` input files and placed in ``XXXGenRegisterInfo.h.inc`` +and ``XXXGenRegisterInfo.inc`` output files. Some of the code in the +implementation of ``XXXRegisterInfo`` requires hand-coding. + +Defining a Register +------------------- + +The ``XXXRegisterInfo.td`` file typically starts with register definitions for +a target machine. The ``Register`` class (specified in ``Target.td``) is used +to define an object for each register. The specified string ``n`` becomes the +``Name`` of the register. The basic ``Register`` object does not have any +subregisters and does not specify any aliases. + +.. code-block:: llvm + + class Register { + string Namespace = ""; + string AsmName = n; + string Name = n; + int SpillSize = 0; + int SpillAlignment = 0; + list Aliases = []; + list SubRegs = []; + list DwarfNumbers = []; + } + +For example, in the ``X86RegisterInfo.td`` file, there are register definitions +that utilize the ``Register`` class, such as: + +.. code-block:: llvm + + def AL : Register<"AL">, DwarfRegNum<[0, 0, 0]>; + +This defines the register ``AL`` and assigns it values (with ``DwarfRegNum``) +that are used by ``gcc``, ``gdb``, or a debug information writer to identify a +register. For register ``AL``, ``DwarfRegNum`` takes an array of 3 values +representing 3 different modes: the first element is for X86-64, the second for +exception handling (EH) on X86-32, and the third is generic. -1 is a special +Dwarf number that indicates the gcc number is undefined, and -2 indicates the +register number is invalid for this mode. + +From the previously described line in the ``X86RegisterInfo.td`` file, TableGen +generates this code in the ``X86GenRegisterInfo.inc`` file: + +.. code-block:: c++ + + static const unsigned GR8[] = { X86::AL, ... }; + + const unsigned AL_AliasSet[] = { X86::AX, X86::EAX, X86::RAX, 0 }; + + const TargetRegisterDesc RegisterDescriptors[] = { + ... + { "AL", "AL", AL_AliasSet, Empty_SubRegsSet, Empty_SubRegsSet, AL_SuperRegsSet }, ... + +From the register info file, TableGen generates a ``TargetRegisterDesc`` object +for each register. ``TargetRegisterDesc`` is defined in +``include/llvm/Target/TargetRegisterInfo.h`` with the following fields: + +.. code-block:: c++ + + struct TargetRegisterDesc { + const char *AsmName; // Assembly language name for the register + const char *Name; // Printable name for the reg (for debugging) + const unsigned *AliasSet; // Register Alias Set + const unsigned *SubRegs; // Sub-register set + const unsigned *ImmSubRegs; // Immediate sub-register set + const unsigned *SuperRegs; // Super-register set + }; + +TableGen uses the entire target description file (``.td``) to determine text +names for the register (in the ``AsmName`` and ``Name`` fields of +``TargetRegisterDesc``) and the relationships of other registers to the defined +register (in the other ``TargetRegisterDesc`` fields). In this example, other +definitions establish the registers "``AX``", "``EAX``", and "``RAX``" as +aliases for one another, so TableGen generates a null-terminated array +(``AL_AliasSet``) for this register alias set. + +The ``Register`` class is commonly used as a base class for more complex +classes. In ``Target.td``, the ``Register`` class is the base for the +``RegisterWithSubRegs`` class that is used to define registers that need to +specify subregisters in the ``SubRegs`` list, as shown here: + +.. code-block:: llvm + + class RegisterWithSubRegs subregs> : Register { + let SubRegs = subregs; + } + +In ``SparcRegisterInfo.td``, additional register classes are defined for SPARC: +a ``Register`` subclass, ``SparcReg``, and further subclasses: ``Ri``, ``Rf``, +and ``Rd``. SPARC registers are identified by 5-bit ID numbers, which is a +feature common to these subclasses. Note the use of "``let``" expressions to +override values that are initially defined in a superclass (such as ``SubRegs`` +field in the ``Rd`` class). + +.. code-block:: llvm + + class SparcReg : Register { + field bits<5> Num; + let Namespace = "SP"; + } + // Ri - 32-bit integer registers + class Ri num, string n> : + SparcReg { + let Num = num; + } + // Rf - 32-bit floating-point registers + class Rf num, string n> : + SparcReg { + let Num = num; + } + // Rd - Slots in the FP register file for 64-bit floating-point values. + class Rd num, string n, list subregs> : SparcReg { + let Num = num; + let SubRegs = subregs; + } + +In the ``SparcRegisterInfo.td`` file, there are register definitions that +utilize these subclasses of ``Register``, such as: + +.. code-block:: llvm + + def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>; + def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>; + ... + def F0 : Rf< 0, "F0">, DwarfRegNum<[32]>; + def F1 : Rf< 1, "F1">, DwarfRegNum<[33]>; + ... + def D0 : Rd< 0, "F0", [F0, F1]>, DwarfRegNum<[32]>; + def D1 : Rd< 2, "F2", [F2, F3]>, DwarfRegNum<[34]>; + +The last two registers shown above (``D0`` and ``D1``) are double-precision +floating-point registers that are aliases for pairs of single-precision +floating-point sub-registers. In addition to aliases, the sub-register and +super-register relationships of the defined register are in fields of a +register's ``TargetRegisterDesc``. + +Defining a Register Class +------------------------- + +The ``RegisterClass`` class (specified in ``Target.td``) is used to define an +object that represents a group of related registers and also defines the +default allocation order of the registers. A target description file +``XXXRegisterInfo.td`` that uses ``Target.td`` can construct register classes +using the following class: + +.. code-block:: llvm + + class RegisterClass regTypes, int alignment, dag regList> { + string Namespace = namespace; + list RegTypes = regTypes; + int Size = 0; // spill size, in bits; zero lets tblgen pick the size + int Alignment = alignment; + + // CopyCost is the cost of copying a value between two registers + // default value 1 means a single instruction + // A negative value means copying is extremely expensive or impossible + int CopyCost = 1; + dag MemberList = regList; + + // for register classes that are subregisters of this class + list SubRegClassList = []; + + code MethodProtos = [{}]; // to insert arbitrary code + code MethodBodies = [{}]; + } + +To define a ``RegisterClass``, use the following 4 arguments: + +* The first argument of the definition is the name of the namespace. + +* The second argument is a list of ``ValueType`` register type values that are + defined in ``include/llvm/CodeGen/ValueTypes.td``. Defined values include + integer types (such as ``i16``, ``i32``, and ``i1`` for Boolean), + floating-point types (``f32``, ``f64``), and vector types (for example, + ``v8i16`` for an ``8 x i16`` vector). All registers in a ``RegisterClass`` + must have the same ``ValueType``, but some registers may store vector data in + different configurations. For example a register that can process a 128-bit + vector may be able to handle 16 8-bit integer elements, 8 16-bit integers, 4 + 32-bit integers, and so on. + +* The third argument of the ``RegisterClass`` definition specifies the + alignment required of the registers when they are stored or loaded to + memory. + +* The final argument, ``regList``, specifies which registers are in this class. + If an alternative allocation order method is not specified, then ``regList`` + also defines the order of allocation used by the register allocator. Besides + simply listing registers with ``(add R0, R1, ...)``, more advanced set + operators are available. See ``include/llvm/Target/Target.td`` for more + information. + +In ``SparcRegisterInfo.td``, three ``RegisterClass`` objects are defined: +``FPRegs``, ``DFPRegs``, and ``IntRegs``. For all three register classes, the +first argument defines the namespace with the string "``SP``". ``FPRegs`` +defines a group of 32 single-precision floating-point registers (``F0`` to +``F31``); ``DFPRegs`` defines a group of 16 double-precision registers +(``D0-D15``). + +.. code-block:: llvm + + // F0, F1, F2, ..., F31 + def FPRegs : RegisterClass<"SP", [f32], 32, (sequence "F%u", 0, 31)>; + + def DFPRegs : RegisterClass<"SP", [f64], 64, + (add D0, D1, D2, D3, D4, D5, D6, D7, D8, + D9, D10, D11, D12, D13, D14, D15)>; + + def IntRegs : RegisterClass<"SP", [i32], 32, + (add L0, L1, L2, L3, L4, L5, L6, L7, + I0, I1, I2, I3, I4, I5, + O0, O1, O2, O3, O4, O5, O7, + G1, + // Non-allocatable regs: + G2, G3, G4, + O6, // stack ptr + I6, // frame ptr + I7, // return address + G0, // constant zero + G5, G6, G7 // reserved for kernel + )>; + +Using ``SparcRegisterInfo.td`` with TableGen generates several output files +that are intended for inclusion in other source code that you write. +``SparcRegisterInfo.td`` generates ``SparcGenRegisterInfo.h.inc``, which should +be included in the header file for the implementation of the SPARC register +implementation that you write (``SparcRegisterInfo.h``). In +``SparcGenRegisterInfo.h.inc`` a new structure is defined called +``SparcGenRegisterInfo`` that uses ``TargetRegisterInfo`` as its base. It also +specifies types, based upon the defined register classes: ``DFPRegsClass``, +``FPRegsClass``, and ``IntRegsClass``. + +``SparcRegisterInfo.td`` also generates ``SparcGenRegisterInfo.inc``, which is +included at the bottom of ``SparcRegisterInfo.cpp``, the SPARC register +implementation. The code below shows only the generated integer registers and +associated register classes. The order of registers in ``IntRegs`` reflects +the order in the definition of ``IntRegs`` in the target description file. + +.. code-block:: c++ + + // IntRegs Register Class... + static const unsigned IntRegs[] = { + SP::L0, SP::L1, SP::L2, SP::L3, SP::L4, SP::L5, + SP::L6, SP::L7, SP::I0, SP::I1, SP::I2, SP::I3, + SP::I4, SP::I5, SP::O0, SP::O1, SP::O2, SP::O3, + SP::O4, SP::O5, SP::O7, SP::G1, SP::G2, SP::G3, + SP::G4, SP::O6, SP::I6, SP::I7, SP::G0, SP::G5, + SP::G6, SP::G7, + }; + + // IntRegsVTs Register Class Value Types... + static const MVT::ValueType IntRegsVTs[] = { + MVT::i32, MVT::Other + }; + + namespace SP { // Register class instances + DFPRegsClass DFPRegsRegClass; + FPRegsClass FPRegsRegClass; + IntRegsClass IntRegsRegClass; + ... + // IntRegs Sub-register Classess... + static const TargetRegisterClass* const IntRegsSubRegClasses [] = { + NULL + }; + ... + // IntRegs Super-register Classess... + static const TargetRegisterClass* const IntRegsSuperRegClasses [] = { + NULL + }; + ... + // IntRegs Register Class sub-classes... + static const TargetRegisterClass* const IntRegsSubclasses [] = { + NULL + }; + ... + // IntRegs Register Class super-classes... + static const TargetRegisterClass* const IntRegsSuperclasses [] = { + NULL + }; + + IntRegsClass::IntRegsClass() : TargetRegisterClass(IntRegsRegClassID, + IntRegsVTs, IntRegsSubclasses, IntRegsSuperclasses, IntRegsSubRegClasses, + IntRegsSuperRegClasses, 4, 4, 1, IntRegs, IntRegs + 32) {} + } + +The register allocators will avoid using reserved registers, and callee saved +registers are not used until all the volatile registers have been used. That +is usually good enough, but in some cases it may be necessary to provide custom +allocation orders. + +Implement a subclass of ``TargetRegisterInfo`` +---------------------------------------------- + +The final step is to hand code portions of ``XXXRegisterInfo``, which +implements the interface described in ``TargetRegisterInfo.h`` (see +:ref:`TargetRegisterInfo`). These functions return ``0``, ``NULL``, or +``false``, unless overridden. Here is a list of functions that are overridden +for the SPARC implementation in ``SparcRegisterInfo.cpp``: + +* ``getCalleeSavedRegs`` --- Returns a list of callee-saved registers in the + order of the desired callee-save stack frame offset. + +* ``getReservedRegs`` --- Returns a bitset indexed by physical register + numbers, indicating if a particular register is unavailable. + +* ``hasFP`` --- Return a Boolean indicating if a function should have a + dedicated frame pointer register. + +* ``eliminateCallFramePseudoInstr`` --- If call frame setup or destroy pseudo + instructions are used, this can be called to eliminate them. + +* ``eliminateFrameIndex`` --- Eliminate abstract frame indices from + instructions that may use them. + +* ``emitPrologue`` --- Insert prologue code into the function. + +* ``emitEpilogue`` --- Insert epilogue code into the function. + +.. _instruction-set: + +Instruction Set +=============== + +During the early stages of code generation, the LLVM IR code is converted to a +``SelectionDAG`` with nodes that are instances of the ``SDNode`` class +containing target instructions. An ``SDNode`` has an opcode, operands, type +requirements, and operation properties. For example, is an operation +commutative, does an operation load from memory. The various operation node +types are described in the ``include/llvm/CodeGen/SelectionDAGNodes.h`` file +(values of the ``NodeType`` enum in the ``ISD`` namespace). + +TableGen uses the following target description (``.td``) input files to +generate much of the code for instruction definition: + +* ``Target.td`` --- Where the ``Instruction``, ``Operand``, ``InstrInfo``, and + other fundamental classes are defined. + +* ``TargetSelectionDAG.td`` --- Used by ``SelectionDAG`` instruction selection + generators, contains ``SDTC*`` classes (selection DAG type constraint), + definitions of ``SelectionDAG`` nodes (such as ``imm``, ``cond``, ``bb``, + ``add``, ``fadd``, ``sub``), and pattern support (``Pattern``, ``Pat``, + ``PatFrag``, ``PatLeaf``, ``ComplexPattern``. + +* ``XXXInstrFormats.td`` --- Patterns for definitions of target-specific + instructions. + +* ``XXXInstrInfo.td`` --- Target-specific definitions of instruction templates, + condition codes, and instructions of an instruction set. For architecture + modifications, a different file name may be used. For example, for Pentium + with SSE instruction, this file is ``X86InstrSSE.td``, and for Pentium with + MMX, this file is ``X86InstrMMX.td``. + +There is also a target-specific ``XXX.td`` file, where ``XXX`` is the name of +the target. The ``XXX.td`` file includes the other ``.td`` input files, but +its contents are only directly important for subtargets. + +You should describe a concrete target-specific class ``XXXInstrInfo`` that +represents machine instructions supported by a target machine. +``XXXInstrInfo`` contains an array of ``XXXInstrDescriptor`` objects, each of +which describes one instruction. An instruction descriptor defines: + +* Opcode mnemonic +* Number of operands +* List of implicit register definitions and uses +* Target-independent properties (such as memory access, is commutable) +* Target-specific flags + +The Instruction class (defined in ``Target.td``) is mostly used as a base for +more complex instruction classes. + +.. code-block:: llvm + + class Instruction { + string Namespace = ""; + dag OutOperandList; // A dag containing the MI def operand list. + dag InOperandList; // A dag containing the MI use operand list. + string AsmString = ""; // The .s format to print the instruction with. + list Pattern; // Set to the DAG pattern for this instruction. + list Uses = []; + list Defs = []; + list Predicates = []; // predicates turned into isel match code + ... remainder not shown for space ... + } + +A ``SelectionDAG`` node (``SDNode``) should contain an object representing a +target-specific instruction that is defined in ``XXXInstrInfo.td``. The +instruction objects should represent instructions from the architecture manual +of the target machine (such as the SPARC Architecture Manual for the SPARC +target). + +A single instruction from the architecture manual is often modeled as multiple +target instructions, depending upon its operands. For example, a manual might +describe an add instruction that takes a register or an immediate operand. An +LLVM target could model this with two instructions named ``ADDri`` and +``ADDrr``. + +You should define a class for each instruction category and define each opcode +as a subclass of the category with appropriate parameters such as the fixed +binary encoding of opcodes and extended opcodes. You should map the register +bits to the bits of the instruction in which they are encoded (for the JIT). +Also you should specify how the instruction should be printed when the +automatic assembly printer is used. + +As is described in the SPARC Architecture Manual, Version 8, there are three +major 32-bit formats for instructions. Format 1 is only for the ``CALL`` +instruction. Format 2 is for branch on condition codes and ``SETHI`` (set high +bits of a register) instructions. Format 3 is for other instructions. + +Each of these formats has corresponding classes in ``SparcInstrFormat.td``. +``InstSP`` is a base class for other instruction classes. Additional base +classes are specified for more precise formats: for example in +``SparcInstrFormat.td``, ``F2_1`` is for ``SETHI``, and ``F2_2`` is for +branches. There are three other base classes: ``F3_1`` for register/register +operations, ``F3_2`` for register/immediate operations, and ``F3_3`` for +floating-point operations. ``SparcInstrInfo.td`` also adds the base class +``Pseudo`` for synthetic SPARC instructions. + +``SparcInstrInfo.td`` largely consists of operand and instruction definitions +for the SPARC target. In ``SparcInstrInfo.td``, the following target +description file entry, ``LDrr``, defines the Load Integer instruction for a +Word (the ``LD`` SPARC opcode) from a memory address to a register. The first +parameter, the value 3 (``11``\ :sub:`2`), is the operation value for this +category of operation. The second parameter (``000000``\ :sub:`2`) is the +specific operation value for ``LD``/Load Word. The third parameter is the +output destination, which is a register operand and defined in the ``Register`` +target description file (``IntRegs``). + +.. code-block:: llvm + + def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$dst), (ins MEMrr:$addr), + "ld [$addr], $dst", + [(set i32:$dst, (load ADDRrr:$addr))]>; + +The fourth parameter is the input source, which uses the address operand +``MEMrr`` that is defined earlier in ``SparcInstrInfo.td``: + +.. code-block:: llvm + + def MEMrr : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops IntRegs, IntRegs); + } + +The fifth parameter is a string that is used by the assembly printer and can be +left as an empty string until the assembly printer interface is implemented. +The sixth and final parameter is the pattern used to match the instruction +during the SelectionDAG Select Phase described in :doc:`CodeGenerator`. +This parameter is detailed in the next section, :ref:`instruction-selector`. + +Instruction class definitions are not overloaded for different operand types, +so separate versions of instructions are needed for register, memory, or +immediate value operands. For example, to perform a Load Integer instruction +for a Word from an immediate operand to a register, the following instruction +class is defined: + +.. code-block:: llvm + + def LDri : F3_2 <3, 0b000000, (outs IntRegs:$dst), (ins MEMri:$addr), + "ld [$addr], $dst", + [(set i32:$dst, (load ADDRri:$addr))]>; + +Writing these definitions for so many similar instructions can involve a lot of +cut and paste. In ``.td`` files, the ``multiclass`` directive enables the +creation of templates to define several instruction classes at once (using the +``defm`` directive). For example in ``SparcInstrInfo.td``, the ``multiclass`` +pattern ``F3_12`` is defined to create 2 instruction classes each time +``F3_12`` is invoked: + +.. code-block:: llvm + + multiclass F3_12 Op3Val, SDNode OpNode> { + def rr : F3_1 <2, Op3Val, + (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + !strconcat(OpcStr, " $b, $c, $dst"), + [(set i32:$dst, (OpNode i32:$b, i32:$c))]>; + def ri : F3_2 <2, Op3Val, + (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), + !strconcat(OpcStr, " $b, $c, $dst"), + [(set i32:$dst, (OpNode i32:$b, simm13:$c))]>; + } + +So when the ``defm`` directive is used for the ``XOR`` and ``ADD`` +instructions, as seen below, it creates four instruction objects: ``XORrr``, +``XORri``, ``ADDrr``, and ``ADDri``. + +.. code-block:: llvm + + defm XOR : F3_12<"xor", 0b000011, xor>; + defm ADD : F3_12<"add", 0b000000, add>; + +``SparcInstrInfo.td`` also includes definitions for condition codes that are +referenced by branch instructions. The following definitions in +``SparcInstrInfo.td`` indicate the bit location of the SPARC condition code. +For example, the 10\ :sup:`th` bit represents the "greater than" condition for +integers, and the 22\ :sup:`nd` bit represents the "greater than" condition for +floats. + +.. code-block:: llvm + + def ICC_NE : ICC_VAL< 9>; // Not Equal + def ICC_E : ICC_VAL< 1>; // Equal + def ICC_G : ICC_VAL<10>; // Greater + ... + def FCC_U : FCC_VAL<23>; // Unordered + def FCC_G : FCC_VAL<22>; // Greater + def FCC_UG : FCC_VAL<21>; // Unordered or Greater + ... + +(Note that ``Sparc.h`` also defines enums that correspond to the same SPARC +condition codes. Care must be taken to ensure the values in ``Sparc.h`` +correspond to the values in ``SparcInstrInfo.td``. I.e., ``SPCC::ICC_NE = 9``, +``SPCC::FCC_U = 23`` and so on.) + +Instruction Operand Mapping +--------------------------- + +The code generator backend maps instruction operands to fields in the +instruction. Operands are assigned to unbound fields in the instruction in the +order they are defined. Fields are bound when they are assigned a value. For +example, the Sparc target defines the ``XNORrr`` instruction as a ``F3_1`` +format instruction having three operands. + +.. code-block:: llvm + + def XNORrr : F3_1<2, 0b000111, + (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + "xnor $b, $c, $dst", + [(set i32:$dst, (not (xor i32:$b, i32:$c)))]>; + +The instruction templates in ``SparcInstrFormats.td`` show the base class for +``F3_1`` is ``InstSP``. + +.. code-block:: llvm + + class InstSP pattern> : Instruction { + field bits<32> Inst; + let Namespace = "SP"; + bits<2> op; + let Inst{31-30} = op; + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; + } + +``InstSP`` leaves the ``op`` field unbound. + +.. code-block:: llvm + + class F3 pattern> + : InstSP { + bits<5> rd; + bits<6> op3; + bits<5> rs1; + let op{1} = 1; // Op = 2 or 3 + let Inst{29-25} = rd; + let Inst{24-19} = op3; + let Inst{18-14} = rs1; + } + +``F3`` binds the ``op`` field and defines the ``rd``, ``op3``, and ``rs1`` +fields. ``F3`` format instructions will bind the operands ``rd``, ``op3``, and +``rs1`` fields. + +.. code-block:: llvm + + class F3_1 opVal, bits<6> op3val, dag outs, dag ins, + string asmstr, list pattern> : F3 { + bits<8> asi = 0; // asi not currently used + bits<5> rs2; + let op = opVal; + let op3 = op3val; + let Inst{13} = 0; // i field = 0 + let Inst{12-5} = asi; // address space identifier + let Inst{4-0} = rs2; + } + +``F3_1`` binds the ``op3`` field and defines the ``rs2`` fields. ``F3_1`` +format instructions will bind the operands to the ``rd``, ``rs1``, and ``rs2`` +fields. This results in the ``XNORrr`` instruction binding ``$dst``, ``$b``, +and ``$c`` operands to the ``rd``, ``rs1``, and ``rs2`` fields respectively. + +Instruction Operand Name Mapping +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TableGen will also generate a function called getNamedOperandIdx() which +can be used to look up an operand's index in a MachineInstr based on its +TableGen name. Setting the UseNamedOperandTable bit in an instruction's +TableGen definition will add all of its operands to an enumeration in the +llvm::XXX:OpName namespace and also add an entry for it into the OperandMap +table, which can be queried using getNamedOperandIdx() + +.. code-block:: llvm + + int DstIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::dst); // => 0 + int BIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::b); // => 1 + int CIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::c); // => 2 + int DIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::d); // => -1 + + ... + +The entries in the OpName enum are taken verbatim from the TableGen definitions, +so operands with lowercase names will have lower case entries in the enum. + +To include the getNamedOperandIdx() function in your backend, you will need +to define a few preprocessor macros in XXXInstrInfo.cpp and XXXInstrInfo.h. +For example: + +XXXInstrInfo.cpp: + +.. code-block:: c++ + + #define GET_INSTRINFO_NAMED_OPS // For getNamedOperandIdx() function + #include "XXXGenInstrInfo.inc" + +XXXInstrInfo.h: + +.. code-block:: c++ + + #define GET_INSTRINFO_OPERAND_ENUM // For OpName enum + #include "XXXGenInstrInfo.inc" + + namespace XXX { + int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex); + } // End namespace XXX + +Instruction Operand Types +^^^^^^^^^^^^^^^^^^^^^^^^^ + +TableGen will also generate an enumeration consisting of all named Operand +types defined in the backend, in the llvm::XXX::OpTypes namespace. +Some common immediate Operand types (for instance i8, i32, i64, f32, f64) +are defined for all targets in ``include/llvm/Target/Target.td``, and are +available in each Target's OpTypes enum. Also, only named Operand types appear +in the enumeration: anonymous types are ignored. +For example, the X86 backend defines ``brtarget`` and ``brtarget8``, both +instances of the TableGen ``Operand`` class, which represent branch target +operands: + +.. code-block:: llvm + + def brtarget : Operand; + def brtarget8 : Operand; + +This results in: + +.. code-block:: c++ + + namespace X86 { + namespace OpTypes { + enum OperandType { + ... + brtarget, + brtarget8, + ... + i32imm, + i64imm, + ... + OPERAND_TYPE_LIST_END + } // End namespace OpTypes + } // End namespace X86 + +In typical TableGen fashion, to use the enum, you will need to define a +preprocessor macro: + +.. code-block:: c++ + + #define GET_INSTRINFO_OPERAND_TYPES_ENUM // For OpTypes enum + #include "XXXGenInstrInfo.inc" + + +Instruction Scheduling +---------------------- + +Instruction itineraries can be queried using MCDesc::getSchedClass(). The +value can be named by an enumemation in llvm::XXX::Sched namespace generated +by TableGen in XXXGenInstrInfo.inc. The name of the schedule classes are +the same as provided in XXXSchedule.td plus a default NoItinerary class. + +Instruction Relation Mapping +---------------------------- + +This TableGen feature is used to relate instructions with each other. It is +particularly useful when you have multiple instruction formats and need to +switch between them after instruction selection. This entire feature is driven +by relation models which can be defined in ``XXXInstrInfo.td`` files +according to the target-specific instruction set. Relation models are defined +using ``InstrMapping`` class as a base. TableGen parses all the models +and generates instruction relation maps using the specified information. +Relation maps are emitted as tables in the ``XXXGenInstrInfo.inc`` file +along with the functions to query them. For the detailed information on how to +use this feature, please refer to :doc:`HowToUseInstrMappings`. + +Implement a subclass of ``TargetInstrInfo`` +------------------------------------------- + +The final step is to hand code portions of ``XXXInstrInfo``, which implements +the interface described in ``TargetInstrInfo.h`` (see :ref:`TargetInstrInfo`). +These functions return ``0`` or a Boolean or they assert, unless overridden. +Here's a list of functions that are overridden for the SPARC implementation in +``SparcInstrInfo.cpp``: + +* ``isLoadFromStackSlot`` --- If the specified machine instruction is a direct + load from a stack slot, return the register number of the destination and the + ``FrameIndex`` of the stack slot. + +* ``isStoreToStackSlot`` --- If the specified machine instruction is a direct + store to a stack slot, return the register number of the destination and the + ``FrameIndex`` of the stack slot. + +* ``copyPhysReg`` --- Copy values between a pair of physical registers. + +* ``storeRegToStackSlot`` --- Store a register value to a stack slot. + +* ``loadRegFromStackSlot`` --- Load a register value from a stack slot. + +* ``storeRegToAddr`` --- Store a register value to memory. + +* ``loadRegFromAddr`` --- Load a register value from memory. + +* ``foldMemoryOperand`` --- Attempt to combine instructions of any load or + store instruction for the specified operand(s). + +Branch Folding and If Conversion +-------------------------------- + +Performance can be improved by combining instructions or by eliminating +instructions that are never reached. The ``AnalyzeBranch`` method in +``XXXInstrInfo`` may be implemented to examine conditional instructions and +remove unnecessary instructions. ``AnalyzeBranch`` looks at the end of a +machine basic block (MBB) for opportunities for improvement, such as branch +folding and if conversion. The ``BranchFolder`` and ``IfConverter`` machine +function passes (see the source files ``BranchFolding.cpp`` and +``IfConversion.cpp`` in the ``lib/CodeGen`` directory) call ``AnalyzeBranch`` +to improve the control flow graph that represents the instructions. + +Several implementations of ``AnalyzeBranch`` (for ARM, Alpha, and X86) can be +examined as models for your own ``AnalyzeBranch`` implementation. Since SPARC +does not implement a useful ``AnalyzeBranch``, the ARM target implementation is +shown below. + +``AnalyzeBranch`` returns a Boolean value and takes four parameters: + +* ``MachineBasicBlock &MBB`` --- The incoming block to be examined. + +* ``MachineBasicBlock *&TBB`` --- A destination block that is returned. For a + conditional branch that evaluates to true, ``TBB`` is the destination. + +* ``MachineBasicBlock *&FBB`` --- For a conditional branch that evaluates to + false, ``FBB`` is returned as the destination. + +* ``std::vector &Cond`` --- List of operands to evaluate a + condition for a conditional branch. + +In the simplest case, if a block ends without a branch, then it falls through +to the successor block. No destination blocks are specified for either ``TBB`` +or ``FBB``, so both parameters return ``NULL``. The start of the +``AnalyzeBranch`` (see code below for the ARM target) shows the function +parameters and the code for the simplest case. + +.. code-block:: c++ + + bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + std::vector &Cond) const + { + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) + return false; + +If a block ends with a single unconditional branch instruction, then +``AnalyzeBranch`` (shown below) should return the destination of that branch in +the ``TBB`` parameter. + +.. code-block:: c++ + + if (LastOpc == ARM::B || LastOpc == ARM::tB) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } + +If a block ends with two unconditional branches, then the second branch is +never reached. In that situation, as shown below, remove the last branch +instruction and return the penultimate branch in the ``TBB`` parameter. + +.. code-block:: c++ + + if ((SecondLastOpc == ARM::B || SecondLastOpc == ARM::tB) && + (LastOpc == ARM::B || LastOpc == ARM::tB)) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + I->eraseFromParent(); + return false; + } + +A block may end with a single conditional branch instruction that falls through +to successor block if the condition evaluates to false. In that case, +``AnalyzeBranch`` (shown below) should return the destination of that +conditional branch in the ``TBB`` parameter and a list of operands in the +``Cond`` parameter to evaluate the condition. + +.. code-block:: c++ + + if (LastOpc == ARM::Bcc || LastOpc == ARM::tBcc) { + // Block ends with fall-through condbranch. + TBB = LastInst->getOperand(0).getMBB(); + Cond.push_back(LastInst->getOperand(1)); + Cond.push_back(LastInst->getOperand(2)); + return false; + } + +If a block ends with both a conditional branch and an ensuing unconditional +branch, then ``AnalyzeBranch`` (shown below) should return the conditional +branch destination (assuming it corresponds to a conditional evaluation of +"``true``") in the ``TBB`` parameter and the unconditional branch destination +in the ``FBB`` (corresponding to a conditional evaluation of "``false``"). A +list of operands to evaluate the condition should be returned in the ``Cond`` +parameter. + +.. code-block:: c++ + + unsigned SecondLastOpc = SecondLastInst->getOpcode(); + + if ((SecondLastOpc == ARM::Bcc && LastOpc == ARM::B) || + (SecondLastOpc == ARM::tBcc && LastOpc == ARM::tB)) { + TBB = SecondLastInst->getOperand(0).getMBB(); + Cond.push_back(SecondLastInst->getOperand(1)); + Cond.push_back(SecondLastInst->getOperand(2)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + +For the last two cases (ending with a single conditional branch or ending with +one conditional and one unconditional branch), the operands returned in the +``Cond`` parameter can be passed to methods of other instructions to create new +branches or perform other operations. An implementation of ``AnalyzeBranch`` +requires the helper methods ``RemoveBranch`` and ``InsertBranch`` to manage +subsequent operations. + +``AnalyzeBranch`` should return false indicating success in most circumstances. +``AnalyzeBranch`` should only return true when the method is stumped about what +to do, for example, if a block has three terminating branches. +``AnalyzeBranch`` may return true if it encounters a terminator it cannot +handle, such as an indirect branch. + +.. _instruction-selector: + +Instruction Selector +==================== + +LLVM uses a ``SelectionDAG`` to represent LLVM IR instructions, and nodes of +the ``SelectionDAG`` ideally represent native target instructions. During code +generation, instruction selection passes are performed to convert non-native +DAG instructions into native target-specific instructions. The pass described +in ``XXXISelDAGToDAG.cpp`` is used to match patterns and perform DAG-to-DAG +instruction selection. Optionally, a pass may be defined (in +``XXXBranchSelector.cpp``) to perform similar DAG-to-DAG operations for branch +instructions. Later, the code in ``XXXISelLowering.cpp`` replaces or removes +operations and data types not supported natively (legalizes) in a +``SelectionDAG``. + +TableGen generates code for instruction selection using the following target +description input files: + +* ``XXXInstrInfo.td`` --- Contains definitions of instructions in a + target-specific instruction set, generates ``XXXGenDAGISel.inc``, which is + included in ``XXXISelDAGToDAG.cpp``. + +* ``XXXCallingConv.td`` --- Contains the calling and return value conventions + for the target architecture, and it generates ``XXXGenCallingConv.inc``, + which is included in ``XXXISelLowering.cpp``. + +The implementation of an instruction selection pass must include a header that +declares the ``FunctionPass`` class or a subclass of ``FunctionPass``. In +``XXXTargetMachine.cpp``, a Pass Manager (PM) should add each instruction +selection pass into the queue of passes to run. + +The LLVM static compiler (``llc``) is an excellent tool for visualizing the +contents of DAGs. To display the ``SelectionDAG`` before or after specific +processing phases, use the command line options for ``llc``, described at +:ref:`SelectionDAG-Process`. + +To describe instruction selector behavior, you should add patterns for lowering +LLVM code into a ``SelectionDAG`` as the last parameter of the instruction +definitions in ``XXXInstrInfo.td``. For example, in ``SparcInstrInfo.td``, +this entry defines a register store operation, and the last parameter describes +a pattern with the store DAG operator. + +.. code-block:: llvm + + def STrr : F3_1< 3, 0b000100, (outs), (ins MEMrr:$addr, IntRegs:$src), + "st $src, [$addr]", [(store i32:$src, ADDRrr:$addr)]>; + +``ADDRrr`` is a memory mode that is also defined in ``SparcInstrInfo.td``: + +.. code-block:: llvm + + def ADDRrr : ComplexPattern; + +The definition of ``ADDRrr`` refers to ``SelectADDRrr``, which is a function +defined in an implementation of the Instructor Selector (such as +``SparcISelDAGToDAG.cpp``). + +In ``lib/Target/TargetSelectionDAG.td``, the DAG operator for store is defined +below: + +.. code-block:: llvm + + def store : PatFrag<(ops node:$val, node:$ptr), + (st node:$val, node:$ptr), [{ + if (StoreSDNode *ST = dyn_cast(N)) + return !ST->isTruncatingStore() && + ST->getAddressingMode() == ISD::UNINDEXED; + return false; + }]>; + +``XXXInstrInfo.td`` also generates (in ``XXXGenDAGISel.inc``) the +``SelectCode`` method that is used to call the appropriate processing method +for an instruction. In this example, ``SelectCode`` calls ``Select_ISD_STORE`` +for the ``ISD::STORE`` opcode. + +.. code-block:: c++ + + SDNode *SelectCode(SDValue N) { + ... + MVT::ValueType NVT = N.getNode()->getValueType(0); + switch (N.getOpcode()) { + case ISD::STORE: { + switch (NVT) { + default: + return Select_ISD_STORE(N); + break; + } + break; + } + ... + +The pattern for ``STrr`` is matched, so elsewhere in ``XXXGenDAGISel.inc``, +code for ``STrr`` is created for ``Select_ISD_STORE``. The ``Emit_22`` method +is also generated in ``XXXGenDAGISel.inc`` to complete the processing of this +instruction. + +.. code-block:: c++ + + SDNode *Select_ISD_STORE(const SDValue &N) { + SDValue Chain = N.getOperand(0); + if (Predicate_store(N.getNode())) { + SDValue N1 = N.getOperand(1); + SDValue N2 = N.getOperand(2); + SDValue CPTmp0; + SDValue CPTmp1; + + // Pattern: (st:void i32:i32:$src, + // ADDRrr:i32:$addr)<> + // Emits: (STrr:void ADDRrr:i32:$addr, IntRegs:i32:$src) + // Pattern complexity = 13 cost = 1 size = 0 + if (SelectADDRrr(N, N2, CPTmp0, CPTmp1) && + N1.getNode()->getValueType(0) == MVT::i32 && + N2.getNode()->getValueType(0) == MVT::i32) { + return Emit_22(N, SP::STrr, CPTmp0, CPTmp1); + } + ... + +The SelectionDAG Legalize Phase +------------------------------- + +The Legalize phase converts a DAG to use types and operations that are natively +supported by the target. For natively unsupported types and operations, you +need to add code to the target-specific ``XXXTargetLowering`` implementation to +convert unsupported types and operations to supported ones. + +In the constructor for the ``XXXTargetLowering`` class, first use the +``addRegisterClass`` method to specify which types are supported and which +register classes are associated with them. The code for the register classes +are generated by TableGen from ``XXXRegisterInfo.td`` and placed in +``XXXGenRegisterInfo.h.inc``. For example, the implementation of the +constructor for the SparcTargetLowering class (in ``SparcISelLowering.cpp``) +starts with the following code: + +.. code-block:: c++ + + addRegisterClass(MVT::i32, SP::IntRegsRegisterClass); + addRegisterClass(MVT::f32, SP::FPRegsRegisterClass); + addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass); + +You should examine the node types in the ``ISD`` namespace +(``include/llvm/CodeGen/SelectionDAGNodes.h``) and determine which operations +the target natively supports. For operations that do **not** have native +support, add a callback to the constructor for the ``XXXTargetLowering`` class, +so the instruction selection process knows what to do. The ``TargetLowering`` +class callback methods (declared in ``llvm/Target/TargetLowering.h``) are: + +* ``setOperationAction`` --- General operation. +* ``setLoadExtAction`` --- Load with extension. +* ``setTruncStoreAction`` --- Truncating store. +* ``setIndexedLoadAction`` --- Indexed load. +* ``setIndexedStoreAction`` --- Indexed store. +* ``setConvertAction`` --- Type conversion. +* ``setCondCodeAction`` --- Support for a given condition code. + +Note: on older releases, ``setLoadXAction`` is used instead of +``setLoadExtAction``. Also, on older releases, ``setCondCodeAction`` may not +be supported. Examine your release to see what methods are specifically +supported. + +These callbacks are used to determine that an operation does or does not work +with a specified type (or types). And in all cases, the third parameter is a +``LegalAction`` type enum value: ``Promote``, ``Expand``, ``Custom``, or +``Legal``. ``SparcISelLowering.cpp`` contains examples of all four +``LegalAction`` values. + +Promote +^^^^^^^ + +For an operation without native support for a given type, the specified type +may be promoted to a larger type that is supported. For example, SPARC does +not support a sign-extending load for Boolean values (``i1`` type), so in +``SparcISelLowering.cpp`` the third parameter below, ``Promote``, changes +``i1`` type values to a large type before loading. + +.. code-block:: c++ + + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + +Expand +^^^^^^ + +For a type without native support, a value may need to be broken down further, +rather than promoted. For an operation without native support, a combination +of other operations may be used to similar effect. In SPARC, the +floating-point sine and cosine trig operations are supported by expansion to +other operations, as indicated by the third parameter, ``Expand``, to +``setOperationAction``: + +.. code-block:: c++ + + setOperationAction(ISD::FSIN, MVT::f32, Expand); + setOperationAction(ISD::FCOS, MVT::f32, Expand); + +Custom +^^^^^^ + +For some operations, simple type promotion or operation expansion may be +insufficient. In some cases, a special intrinsic function must be implemented. + +For example, a constant value may require special treatment, or an operation +may require spilling and restoring registers in the stack and working with +register allocators. + +As seen in ``SparcISelLowering.cpp`` code below, to perform a type conversion +from a floating point value to a signed integer, first the +``setOperationAction`` should be called with ``Custom`` as the third parameter: + +.. code-block:: c++ + + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + +In the ``LowerOperation`` method, for each ``Custom`` operation, a case +statement should be added to indicate what function to call. In the following +code, an ``FP_TO_SINT`` opcode will call the ``LowerFP_TO_SINT`` method: + +.. code-block:: c++ + + SDValue SparcTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG); + ... + } + } + +Finally, the ``LowerFP_TO_SINT`` method is implemented, using an FP register to +convert the floating-point value to an integer. + +.. code-block:: c++ + + static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { + assert(Op.getValueType() == MVT::i32); + Op = DAG.getNode(SPISD::FTOI, MVT::f32, Op.getOperand(0)); + return DAG.getNode(ISD::BITCAST, MVT::i32, Op); + } + +Legal +^^^^^ + +The ``Legal`` ``LegalizeAction`` enum value simply indicates that an operation +**is** natively supported. ``Legal`` represents the default condition, so it +is rarely used. In ``SparcISelLowering.cpp``, the action for ``CTPOP`` (an +operation to count the bits set in an integer) is natively supported only for +SPARC v9. The following code enables the ``Expand`` conversion technique for +non-v9 SPARC implementations. + +.. code-block:: c++ + + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + ... + if (TM.getSubtarget().isV9()) + setOperationAction(ISD::CTPOP, MVT::i32, Legal); + +Calling Conventions +------------------- + +To support target-specific calling conventions, ``XXXGenCallingConv.td`` uses +interfaces (such as ``CCIfType`` and ``CCAssignToReg``) that are defined in +``lib/Target/TargetCallingConv.td``. TableGen can take the target descriptor +file ``XXXGenCallingConv.td`` and generate the header file +``XXXGenCallingConv.inc``, which is typically included in +``XXXISelLowering.cpp``. You can use the interfaces in +``TargetCallingConv.td`` to specify: + +* The order of parameter allocation. + +* Where parameters and return values are placed (that is, on the stack or in + registers). + +* Which registers may be used. + +* Whether the caller or callee unwinds the stack. + +The following example demonstrates the use of the ``CCIfType`` and +``CCAssignToReg`` interfaces. If the ``CCIfType`` predicate is true (that is, +if the current argument is of type ``f32`` or ``f64``), then the action is +performed. In this case, the ``CCAssignToReg`` action assigns the argument +value to the first available register: either ``R0`` or ``R1``. + +.. code-block:: llvm + + CCIfType<[f32,f64], CCAssignToReg<[R0, R1]>> + +``SparcCallingConv.td`` contains definitions for a target-specific return-value +calling convention (``RetCC_Sparc32``) and a basic 32-bit C calling convention +(``CC_Sparc32``). The definition of ``RetCC_Sparc32`` (shown below) indicates +which registers are used for specified scalar return types. A single-precision +float is returned to register ``F0``, and a double-precision float goes to +register ``D0``. A 32-bit integer is returned in register ``I0`` or ``I1``. + +.. code-block:: llvm + + def RetCC_Sparc32 : CallingConv<[ + CCIfType<[i32], CCAssignToReg<[I0, I1]>>, + CCIfType<[f32], CCAssignToReg<[F0]>>, + CCIfType<[f64], CCAssignToReg<[D0]>> + ]>; + +The definition of ``CC_Sparc32`` in ``SparcCallingConv.td`` introduces +``CCAssignToStack``, which assigns the value to a stack slot with the specified +size and alignment. In the example below, the first parameter, 4, indicates +the size of the slot, and the second parameter, also 4, indicates the stack +alignment along 4-byte units. (Special cases: if size is zero, then the ABI +size is used; if alignment is zero, then the ABI alignment is used.) + +.. code-block:: llvm + + def CC_Sparc32 : CallingConv<[ + // All arguments get passed in integer registers if there is space. + CCIfType<[i32, f32, f64], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, + CCAssignToStack<4, 4> + ]>; + +``CCDelegateTo`` is another commonly used interface, which tries to find a +specified sub-calling convention, and, if a match is found, it is invoked. In +the following example (in ``X86CallingConv.td``), the definition of +``RetCC_X86_32_C`` ends with ``CCDelegateTo``. After the current value is +assigned to the register ``ST0`` or ``ST1``, the ``RetCC_X86Common`` is +invoked. + +.. code-block:: llvm + + def RetCC_X86_32_C : CallingConv<[ + CCIfType<[f32], CCAssignToReg<[ST0, ST1]>>, + CCIfType<[f64], CCAssignToReg<[ST0, ST1]>>, + CCDelegateTo + ]>; + +``CCIfCC`` is an interface that attempts to match the given name to the current +calling convention. If the name identifies the current calling convention, +then a specified action is invoked. In the following example (in +``X86CallingConv.td``), if the ``Fast`` calling convention is in use, then +``RetCC_X86_32_Fast`` is invoked. If the ``SSECall`` calling convention is in +use, then ``RetCC_X86_32_SSE`` is invoked. + +.. code-block:: llvm + + def RetCC_X86_32 : CallingConv<[ + CCIfCC<"CallingConv::Fast", CCDelegateTo>, + CCIfCC<"CallingConv::X86_SSECall", CCDelegateTo>, + CCDelegateTo + ]>; + +Other calling convention interfaces include: + +* ``CCIf `` --- If the predicate matches, apply the action. + +* ``CCIfInReg `` --- If the argument is marked with the "``inreg``" + attribute, then apply the action. + +* ``CCIfNest `` --- If the argument is marked with the "``nest``" + attribute, then apply the action. + +* ``CCIfNotVarArg `` --- If the current function does not take a + variable number of arguments, apply the action. + +* ``CCAssignToRegWithShadow `` --- similar to + ``CCAssignToReg``, but with a shadow list of registers. + +* ``CCPassByVal `` --- Assign value to a stack slot with the + minimum specified size and alignment. + +* ``CCPromoteToType `` --- Promote the current value to the specified + type. + +* ``CallingConv <[actions]>`` --- Define each calling convention that is + supported. + +Assembly Printer +================ + +During the code emission stage, the code generator may utilize an LLVM pass to +produce assembly output. To do this, you want to implement the code for a +printer that converts LLVM IR to a GAS-format assembly language for your target +machine, using the following steps: + +* Define all the assembly strings for your target, adding them to the + instructions defined in the ``XXXInstrInfo.td`` file. (See + :ref:`instruction-set`.) TableGen will produce an output file + (``XXXGenAsmWriter.inc``) with an implementation of the ``printInstruction`` + method for the ``XXXAsmPrinter`` class. + +* Write ``XXXTargetAsmInfo.h``, which contains the bare-bones declaration of + the ``XXXTargetAsmInfo`` class (a subclass of ``TargetAsmInfo``). + +* Write ``XXXTargetAsmInfo.cpp``, which contains target-specific values for + ``TargetAsmInfo`` properties and sometimes new implementations for methods. + +* Write ``XXXAsmPrinter.cpp``, which implements the ``AsmPrinter`` class that + performs the LLVM-to-assembly conversion. + +The code in ``XXXTargetAsmInfo.h`` is usually a trivial declaration of the +``XXXTargetAsmInfo`` class for use in ``XXXTargetAsmInfo.cpp``. Similarly, +``XXXTargetAsmInfo.cpp`` usually has a few declarations of ``XXXTargetAsmInfo`` +replacement values that override the default values in ``TargetAsmInfo.cpp``. +For example in ``SparcTargetAsmInfo.cpp``: + +.. code-block:: c++ + + SparcTargetAsmInfo::SparcTargetAsmInfo(const SparcTargetMachine &TM) { + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; + Data64bitsDirective = 0; // .xword is only supported by V9. + ZeroDirective = "\t.skip\t"; + CommentString = "!"; + ConstantPoolSection = "\t.section \".rodata\",#alloc\n"; + } + +The X86 assembly printer implementation (``X86TargetAsmInfo``) is an example +where the target specific ``TargetAsmInfo`` class uses an overridden methods: +``ExpandInlineAsm``. + +A target-specific implementation of ``AsmPrinter`` is written in +``XXXAsmPrinter.cpp``, which implements the ``AsmPrinter`` class that converts +the LLVM to printable assembly. The implementation must include the following +headers that have declarations for the ``AsmPrinter`` and +``MachineFunctionPass`` classes. The ``MachineFunctionPass`` is a subclass of +``FunctionPass``. + +.. code-block:: c++ + + #include "llvm/CodeGen/AsmPrinter.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + +As a ``FunctionPass``, ``AsmPrinter`` first calls ``doInitialization`` to set +up the ``AsmPrinter``. In ``SparcAsmPrinter``, a ``Mangler`` object is +instantiated to process variable names. + +In ``XXXAsmPrinter.cpp``, the ``runOnMachineFunction`` method (declared in +``MachineFunctionPass``) must be implemented for ``XXXAsmPrinter``. In +``MachineFunctionPass``, the ``runOnFunction`` method invokes +``runOnMachineFunction``. Target-specific implementations of +``runOnMachineFunction`` differ, but generally do the following to process each +machine function: + +* Call ``SetupMachineFunction`` to perform initialization. + +* Call ``EmitConstantPool`` to print out (to the output stream) constants which + have been spilled to memory. + +* Call ``EmitJumpTableInfo`` to print out jump tables used by the current + function. + +* Print out the label for the current function. + +* Print out the code for the function, including basic block labels and the + assembly for the instruction (using ``printInstruction``) + +The ``XXXAsmPrinter`` implementation must also include the code generated by +TableGen that is output in the ``XXXGenAsmWriter.inc`` file. The code in +``XXXGenAsmWriter.inc`` contains an implementation of the ``printInstruction`` +method that may call these methods: + +* ``printOperand`` +* ``printMemOperand`` +* ``printCCOperand`` (for conditional statements) +* ``printDataDirective`` +* ``printDeclare`` +* ``printImplicitDef`` +* ``printInlineAsm`` + +The implementations of ``printDeclare``, ``printImplicitDef``, +``printInlineAsm``, and ``printLabel`` in ``AsmPrinter.cpp`` are generally +adequate for printing assembly and do not need to be overridden. + +The ``printOperand`` method is implemented with a long ``switch``/``case`` +statement for the type of operand: register, immediate, basic block, external +symbol, global address, constant pool index, or jump table index. For an +instruction with a memory address operand, the ``printMemOperand`` method +should be implemented to generate the proper output. Similarly, +``printCCOperand`` should be used to print a conditional operand. + +``doFinalization`` should be overridden in ``XXXAsmPrinter``, and it should be +called to shut down the assembly printer. During ``doFinalization``, global +variables and constants are printed to output. + +Subtarget Support +================= + +Subtarget support is used to inform the code generation process of instruction +set variations for a given chip set. For example, the LLVM SPARC +implementation provided covers three major versions of the SPARC microprocessor +architecture: Version 8 (V8, which is a 32-bit architecture), Version 9 (V9, a +64-bit architecture), and the UltraSPARC architecture. V8 has 16 +double-precision floating-point registers that are also usable as either 32 +single-precision or 8 quad-precision registers. V8 is also purely big-endian. +V9 has 32 double-precision floating-point registers that are also usable as 16 +quad-precision registers, but cannot be used as single-precision registers. +The UltraSPARC architecture combines V9 with UltraSPARC Visual Instruction Set +extensions. + +If subtarget support is needed, you should implement a target-specific +``XXXSubtarget`` class for your architecture. This class should process the +command-line options ``-mcpu=`` and ``-mattr=``. + +TableGen uses definitions in the ``Target.td`` and ``Sparc.td`` files to +generate code in ``SparcGenSubtarget.inc``. In ``Target.td``, shown below, the +``SubtargetFeature`` interface is defined. The first 4 string parameters of +the ``SubtargetFeature`` interface are a feature name, an attribute set by the +feature, the value of the attribute, and a description of the feature. (The +fifth parameter is a list of features whose presence is implied, and its +default value is an empty array.) + +.. code-block:: llvm + + class SubtargetFeature i = []> { + string Name = n; + string Attribute = a; + string Value = v; + string Desc = d; + list Implies = i; + } + +In the ``Sparc.td`` file, the ``SubtargetFeature`` is used to define the +following features. + +.. code-block:: llvm + + def FeatureV9 : SubtargetFeature<"v9", "IsV9", "true", + "Enable SPARC-V9 instructions">; + def FeatureV8Deprecated : SubtargetFeature<"deprecated-v8", + "V8DeprecatedInsts", "true", + "Enable deprecated V8 instructions in V9 mode">; + def FeatureVIS : SubtargetFeature<"vis", "IsVIS", "true", + "Enable UltraSPARC Visual Instruction Set extensions">; + +Elsewhere in ``Sparc.td``, the ``Proc`` class is defined and then is used to +define particular SPARC processor subtypes that may have the previously +described features. + +.. code-block:: llvm + + class Proc Features> + : Processor; + + def : Proc<"generic", []>; + def : Proc<"v8", []>; + def : Proc<"supersparc", []>; + def : Proc<"sparclite", []>; + def : Proc<"f934", []>; + def : Proc<"hypersparc", []>; + def : Proc<"sparclite86x", []>; + def : Proc<"sparclet", []>; + def : Proc<"tsc701", []>; + def : Proc<"v9", [FeatureV9]>; + def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated]>; + def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>; + def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>; + +From ``Target.td`` and ``Sparc.td`` files, the resulting +``SparcGenSubtarget.inc`` specifies enum values to identify the features, +arrays of constants to represent the CPU features and CPU subtypes, and the +``ParseSubtargetFeatures`` method that parses the features string that sets +specified subtarget options. The generated ``SparcGenSubtarget.inc`` file +should be included in the ``SparcSubtarget.cpp``. The target-specific +implementation of the ``XXXSubtarget`` method should follow this pseudocode: + +.. code-block:: c++ + + XXXSubtarget::XXXSubtarget(const Module &M, const std::string &FS) { + // Set the default features + // Determine default and user specified characteristics of the CPU + // Call ParseSubtargetFeatures(FS, CPU) to parse the features string + // Perform any additional operations + } + +JIT Support +=========== + +The implementation of a target machine optionally includes a Just-In-Time (JIT) +code generator that emits machine code and auxiliary structures as binary +output that can be written directly to memory. To do this, implement JIT code +generation by performing the following steps: + +* Write an ``XXXCodeEmitter.cpp`` file that contains a machine function pass + that transforms target-machine instructions into relocatable machine + code. + +* Write an ``XXXJITInfo.cpp`` file that implements the JIT interfaces for + target-specific code-generation activities, such as emitting machine code and + stubs. + +* Modify ``XXXTargetMachine`` so that it provides a ``TargetJITInfo`` object + through its ``getJITInfo`` method. + +There are several different approaches to writing the JIT support code. For +instance, TableGen and target descriptor files may be used for creating a JIT +code generator, but are not mandatory. For the Alpha and PowerPC target +machines, TableGen is used to generate ``XXXGenCodeEmitter.inc``, which +contains the binary coding of machine instructions and the +``getBinaryCodeForInstr`` method to access those codes. Other JIT +implementations do not. + +Both ``XXXJITInfo.cpp`` and ``XXXCodeEmitter.cpp`` must include the +``llvm/CodeGen/MachineCodeEmitter.h`` header file that defines the +``MachineCodeEmitter`` class containing code for several callback functions +that write data (in bytes, words, strings, etc.) to the output stream. + +Machine Code Emitter +-------------------- + +In ``XXXCodeEmitter.cpp``, a target-specific of the ``Emitter`` class is +implemented as a function pass (subclass of ``MachineFunctionPass``). The +target-specific implementation of ``runOnMachineFunction`` (invoked by +``runOnFunction`` in ``MachineFunctionPass``) iterates through the +``MachineBasicBlock`` calls ``emitInstruction`` to process each instruction and +emit binary code. ``emitInstruction`` is largely implemented with case +statements on the instruction types defined in ``XXXInstrInfo.h``. For +example, in ``X86CodeEmitter.cpp``, the ``emitInstruction`` method is built +around the following ``switch``/``case`` statements: + +.. code-block:: c++ + + switch (Desc->TSFlags & X86::FormMask) { + case X86II::Pseudo: // for not yet implemented instructions + ... // or pseudo-instructions + break; + case X86II::RawFrm: // for instructions with a fixed opcode value + ... + break; + case X86II::AddRegFrm: // for instructions that have one register operand + ... // added to their opcode + break; + case X86II::MRMDestReg:// for instructions that use the Mod/RM byte + ... // to specify a destination (register) + break; + case X86II::MRMDestMem:// for instructions that use the Mod/RM byte + ... // to specify a destination (memory) + break; + case X86II::MRMSrcReg: // for instructions that use the Mod/RM byte + ... // to specify a source (register) + break; + case X86II::MRMSrcMem: // for instructions that use the Mod/RM byte + ... // to specify a source (memory) + break; + case X86II::MRM0r: case X86II::MRM1r: // for instructions that operate on + case X86II::MRM2r: case X86II::MRM3r: // a REGISTER r/m operand and + case X86II::MRM4r: case X86II::MRM5r: // use the Mod/RM byte and a field + case X86II::MRM6r: case X86II::MRM7r: // to hold extended opcode data + ... + break; + case X86II::MRM0m: case X86II::MRM1m: // for instructions that operate on + case X86II::MRM2m: case X86II::MRM3m: // a MEMORY r/m operand and + case X86II::MRM4m: case X86II::MRM5m: // use the Mod/RM byte and a field + case X86II::MRM6m: case X86II::MRM7m: // to hold extended opcode data + ... + break; + case X86II::MRMInitReg: // for instructions whose source and + ... // destination are the same register + break; + } + +The implementations of these case statements often first emit the opcode and +then get the operand(s). Then depending upon the operand, helper methods may +be called to process the operand(s). For example, in ``X86CodeEmitter.cpp``, +for the ``X86II::AddRegFrm`` case, the first data emitted (by ``emitByte``) is +the opcode added to the register operand. Then an object representing the +machine operand, ``MO1``, is extracted. The helper methods such as +``isImmediate``, ``isGlobalAddress``, ``isExternalSymbol``, +``isConstantPoolIndex``, and ``isJumpTableIndex`` determine the operand type. +(``X86CodeEmitter.cpp`` also has private methods such as ``emitConstant``, +``emitGlobalAddress``, ``emitExternalSymbolAddress``, ``emitConstPoolAddress``, +and ``emitJumpTableAddress`` that emit the data into the output stream.) + +.. code-block:: c++ + + case X86II::AddRegFrm: + MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++).getReg())); + + if (CurOp != NumOps) { + const MachineOperand &MO1 = MI.getOperand(CurOp++); + unsigned Size = X86InstrInfo::sizeOfImm(Desc); + if (MO1.isImmediate()) + emitConstant(MO1.getImm(), Size); + else { + unsigned rt = Is64BitMode ? X86::reloc_pcrel_word + : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); + if (Opcode == X86::MOV64ri) + rt = X86::reloc_absolute_dword; // FIXME: add X86II flag? + if (MO1.isGlobalAddress()) { + bool NeedStub = isa(MO1.getGlobal()); + bool isLazy = gvNeedsLazyPtr(MO1.getGlobal()); + emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, + NeedStub, isLazy); + } else if (MO1.isExternalSymbol()) + emitExternalSymbolAddress(MO1.getSymbolName(), rt); + else if (MO1.isConstantPoolIndex()) + emitConstPoolAddress(MO1.getIndex(), rt); + else if (MO1.isJumpTableIndex()) + emitJumpTableAddress(MO1.getIndex(), rt); + } + } + break; + +In the previous example, ``XXXCodeEmitter.cpp`` uses the variable ``rt``, which +is a ``RelocationType`` enum that may be used to relocate addresses (for +example, a global address with a PIC base offset). The ``RelocationType`` enum +for that target is defined in the short target-specific ``XXXRelocations.h`` +file. The ``RelocationType`` is used by the ``relocate`` method defined in +``XXXJITInfo.cpp`` to rewrite addresses for referenced global symbols. + +For example, ``X86Relocations.h`` specifies the following relocation types for +the X86 addresses. In all four cases, the relocated value is added to the +value already in memory. For ``reloc_pcrel_word`` and ``reloc_picrel_word``, +there is an additional initial adjustment. + +.. code-block:: c++ + + enum RelocationType { + reloc_pcrel_word = 0, // add reloc value after adjusting for the PC loc + reloc_picrel_word = 1, // add reloc value after adjusting for the PIC base + reloc_absolute_word = 2, // absolute relocation; no additional adjustment + reloc_absolute_dword = 3 // absolute relocation; no additional adjustment + }; + +Target JIT Info +--------------- + +``XXXJITInfo.cpp`` implements the JIT interfaces for target-specific +code-generation activities, such as emitting machine code and stubs. At +minimum, a target-specific version of ``XXXJITInfo`` implements the following: + +* ``getLazyResolverFunction`` --- Initializes the JIT, gives the target a + function that is used for compilation. + +* ``emitFunctionStub`` --- Returns a native function with a specified address + for a callback function. + +* ``relocate`` --- Changes the addresses of referenced globals, based on + relocation types. + +* Callback function that are wrappers to a function stub that is used when the + real target is not initially known. + +``getLazyResolverFunction`` is generally trivial to implement. It makes the +incoming parameter as the global ``JITCompilerFunction`` and returns the +callback function that will be used a function wrapper. For the Alpha target +(in ``AlphaJITInfo.cpp``), the ``getLazyResolverFunction`` implementation is +simply: + +.. code-block:: c++ + + TargetJITInfo::LazyResolverFn AlphaJITInfo::getLazyResolverFunction( + JITCompilerFn F) { + JITCompilerFunction = F; + return AlphaCompilationCallback; + } + +For the X86 target, the ``getLazyResolverFunction`` implementation is a little +more complicated, because it returns a different callback function for +processors with SSE instructions and XMM registers. + +The callback function initially saves and later restores the callee register +values, incoming arguments, and frame and return address. The callback +function needs low-level access to the registers or stack, so it is typically +implemented with assembler. + diff --git a/docs/WritingAnLLVMPass.rst b/docs/WritingAnLLVMPass.rst new file mode 100644 index 00000000..f9cb4fe8 --- /dev/null +++ b/docs/WritingAnLLVMPass.rst @@ -0,0 +1,1436 @@ +==================== +Writing an LLVM Pass +==================== + +.. contents:: + :local: + +Introduction --- What is a pass? +================================ + +The LLVM Pass Framework is an important part of the LLVM system, because LLVM +passes are where most of the interesting parts of the compiler exist. Passes +perform the transformations and optimizations that make up the compiler, they +build the analysis results that are used by these transformations, and they +are, above all, a structuring technique for compiler code. + +All LLVM passes are subclasses of the `Pass +`_ class, which implement +functionality by overriding virtual methods inherited from ``Pass``. Depending +on how your pass works, you should inherit from the :ref:`ModulePass +` , :ref:`CallGraphSCCPass +`, :ref:`FunctionPass +` , or :ref:`LoopPass +`, or :ref:`RegionPass +`, or :ref:`BasicBlockPass +` classes, which gives the system more +information about what your pass does, and how it can be combined with other +passes. One of the main features of the LLVM Pass Framework is that it +schedules passes to run in an efficient way based on the constraints that your +pass meets (which are indicated by which class they derive from). + +We start by showing you how to construct a pass, everything from setting up the +code, to compiling, loading, and executing it. After the basics are down, more +advanced features are discussed. + +Quick Start --- Writing hello world +=================================== + +Here we describe how to write the "hello world" of passes. The "Hello" pass is +designed to simply print out the name of non-external functions that exist in +the program being compiled. It does not modify the program at all, it just +inspects it. The source code and files for this pass are available in the LLVM +source tree in the ``lib/Transforms/Hello`` directory. + +.. _writing-an-llvm-pass-makefile: + +Setting up the build environment +-------------------------------- + +.. FIXME: Why does this recommend to build in-tree? + +First, configure and build LLVM. This needs to be done directly inside the +LLVM source tree rather than in a separate objects directory. Next, you need +to create a new directory somewhere in the LLVM source base. For this example, +we'll assume that you made ``lib/Transforms/Hello``. Finally, you must set up +a build script (``Makefile``) that will compile the source code for the new +pass. To do this, copy the following into ``Makefile``: + +.. code-block:: make + + # Makefile for hello pass + + # Path to top level of LLVM hierarchy + LEVEL = ../../.. + + # Name of the library to build + LIBRARYNAME = Hello + + # Make the shared library become a loadable module so the tools can + # dlopen/dlsym on the resulting library. + LOADABLE_MODULE = 1 + + # Include the makefile implementation stuff + include $(LEVEL)/Makefile.common + +This makefile specifies that all of the ``.cpp`` files in the current directory +are to be compiled and linked together into a shared object +``$(LEVEL)/Debug+Asserts/lib/Hello.so`` that can be dynamically loaded by the +:program:`opt` or :program:`bugpoint` tools via their :option:`-load` options. +If your operating system uses a suffix other than ``.so`` (such as Windows or Mac +OS X), the appropriate extension will be used. + +If you are used CMake to build LLVM, see :ref:`cmake-out-of-source-pass`. + +Now that we have the build scripts set up, we just need to write the code for +the pass itself. + +.. _writing-an-llvm-pass-basiccode: + +Basic code required +------------------- + +Now that we have a way to compile our new pass, we just have to write it. +Start out with: + +.. code-block:: c++ + + #include "llvm/Pass.h" + #include "llvm/IR/Function.h" + #include "llvm/Support/raw_ostream.h" + +Which are needed because we are writing a `Pass +`_, we are operating on +`Function `_\ s, and we will +be doing some printing. + +Next we have: + +.. code-block:: c++ + + using namespace llvm; + +... which is required because the functions from the include files live in the +llvm namespace. + +Next we have: + +.. code-block:: c++ + + namespace { + +... which starts out an anonymous namespace. Anonymous namespaces are to C++ +what the "``static``" keyword is to C (at global scope). It makes the things +declared inside of the anonymous namespace visible only to the current file. +If you're not familiar with them, consult a decent C++ book for more +information. + +Next, we declare our pass itself: + +.. code-block:: c++ + + struct Hello : public FunctionPass { + +This declares a "``Hello``" class that is a subclass of :ref:`FunctionPass +`. The different builtin pass subclasses +are described in detail :ref:`later `, but +for now, know that ``FunctionPass`` operates on a function at a time. + +.. code-block:: c++ + + static char ID; + Hello() : FunctionPass(ID) {} + +This declares pass identifier used by LLVM to identify pass. This allows LLVM +to avoid using expensive C++ runtime information. + +.. code-block:: c++ + + virtual bool runOnFunction(Function &F) { + errs() << "Hello: "; + errs().write_escaped(F.getName()) << "\n"; + return false; + } + }; // end of struct Hello + } // end of anonymous namespace + +We declare a :ref:`runOnFunction ` method, +which overrides an abstract virtual method inherited from :ref:`FunctionPass +`. This is where we are supposed to do our +thing, so we just print out our message with the name of each function. + +.. code-block:: c++ + + char Hello::ID = 0; + +We initialize pass ID here. LLVM uses ID's address to identify a pass, so +initialization value is not important. + +.. code-block:: c++ + + static RegisterPass X("hello", "Hello World Pass", + false /* Only looks at CFG */, + false /* Analysis Pass */); + +Lastly, we :ref:`register our class ` +``Hello``, giving it a command line argument "``hello``", and a name "Hello +World Pass". The last two arguments describe its behavior: if a pass walks CFG +without modifying it then the third argument is set to ``true``; if a pass is +an analysis pass, for example dominator tree pass, then ``true`` is supplied as +the fourth argument. + +As a whole, the ``.cpp`` file looks like: + +.. code-block:: c++ + + #include "llvm/Pass.h" + #include "llvm/IR/Function.h" + #include "llvm/Support/raw_ostream.h" + + using namespace llvm; + + namespace { + struct Hello : public FunctionPass { + static char ID; + Hello() : FunctionPass(ID) {} + + virtual bool runOnFunction(Function &F) { + errs() << "Hello: "; + errs().write_escaped(F.getName()) << '\n'; + return false; + } + }; + } + + char Hello::ID = 0; + static RegisterPass X("hello", "Hello World Pass", false, false); + +Now that it's all together, compile the file with a simple "``gmake``" command +in the local directory and you should get a new file +"``Debug+Asserts/lib/Hello.so``" under the top level directory of the LLVM +source tree (not in the local directory). Note that everything in this file is +contained in an anonymous namespace --- this reflects the fact that passes +are self contained units that do not need external interfaces (although they +can have them) to be useful. + +Running a pass with ``opt`` +--------------------------- + +Now that you have a brand new shiny shared object file, we can use the +:program:`opt` command to run an LLVM program through your pass. Because you +registered your pass with ``RegisterPass``, you will be able to use the +:program:`opt` tool to access it, once loaded. + +To test it, follow the example at the end of the :doc:`GettingStarted` to +compile "Hello World" to LLVM. We can now run the bitcode file (hello.bc) for +the program through our transformation like this (or course, any bitcode file +will work): + +.. code-block:: console + + $ opt -load ../../../Debug+Asserts/lib/Hello.so -hello < hello.bc > /dev/null + Hello: __main + Hello: puts + Hello: main + +The :option:`-load` option specifies that :program:`opt` should load your pass +as a shared object, which makes "``-hello``" a valid command line argument +(which is one reason you need to :ref:`register your pass +`). Because the Hello pass does not modify +the program in any interesting way, we just throw away the result of +:program:`opt` (sending it to ``/dev/null``). + +To see what happened to the other string you registered, try running +:program:`opt` with the :option:`-help` option: + +.. code-block:: console + + $ opt -load ../../../Debug+Asserts/lib/Hello.so -help + OVERVIEW: llvm .bc -> .bc modular optimizer + + USAGE: opt [options] + + OPTIONS: + Optimizations available: + ... + -globalopt - Global Variable Optimizer + -globalsmodref-aa - Simple mod/ref analysis for globals + -gvn - Global Value Numbering + -hello - Hello World Pass + -indvars - Induction Variable Simplification + -inline - Function Integration/Inlining + -insert-edge-profiling - Insert instrumentation for edge profiling + ... + +The pass name gets added as the information string for your pass, giving some +documentation to users of :program:`opt`. Now that you have a working pass, +you would go ahead and make it do the cool transformations you want. Once you +get it all working and tested, it may become useful to find out how fast your +pass is. The :ref:`PassManager ` provides a +nice command line option (:option:`--time-passes`) that allows you to get +information about the execution time of your pass along with the other passes +you queue up. For example: + +.. code-block:: console + + $ opt -load ../../../Debug+Asserts/lib/Hello.so -hello -time-passes < hello.bc > /dev/null + Hello: __main + Hello: puts + Hello: main + =============================================================================== + ... Pass execution timing report ... + =============================================================================== + Total Execution Time: 0.02 seconds (0.0479059 wall clock) + + ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Pass Name --- + 0.0100 (100.0%) 0.0000 ( 0.0%) 0.0100 ( 50.0%) 0.0402 ( 84.0%) Bitcode Writer + 0.0000 ( 0.0%) 0.0100 (100.0%) 0.0100 ( 50.0%) 0.0031 ( 6.4%) Dominator Set Construction + 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0013 ( 2.7%) Module Verifier + 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0033 ( 6.9%) Hello World Pass + 0.0100 (100.0%) 0.0100 (100.0%) 0.0200 (100.0%) 0.0479 (100.0%) TOTAL + +As you can see, our implementation above is pretty fast. The additional +passes listed are automatically inserted by the :program:`opt` tool to verify +that the LLVM emitted by your pass is still valid and well formed LLVM, which +hasn't been broken somehow. + +Now that you have seen the basics of the mechanics behind passes, we can talk +about some more details of how they work and how to use them. + +.. _writing-an-llvm-pass-pass-classes: + +Pass classes and requirements +============================= + +One of the first things that you should do when designing a new pass is to +decide what class you should subclass for your pass. The :ref:`Hello World +` example uses the :ref:`FunctionPass +` class for its implementation, but we did +not discuss why or when this should occur. Here we talk about the classes +available, from the most general to the most specific. + +When choosing a superclass for your ``Pass``, you should choose the **most +specific** class possible, while still being able to meet the requirements +listed. This gives the LLVM Pass Infrastructure information necessary to +optimize how passes are run, so that the resultant compiler isn't unnecessarily +slow. + +The ``ImmutablePass`` class +--------------------------- + +The most plain and boring type of pass is the "`ImmutablePass +`_" class. This pass +type is used for passes that do not have to be run, do not change state, and +never need to be updated. This is not a normal type of transformation or +analysis, but can provide information about the current compiler configuration. + +Although this pass class is very infrequently used, it is important for +providing information about the current target machine being compiled for, and +other static information that can affect the various transformations. + +``ImmutablePass``\ es never invalidate other transformations, are never +invalidated, and are never "run". + +.. _writing-an-llvm-pass-ModulePass: + +The ``ModulePass`` class +------------------------ + +The `ModulePass `_ class +is the most general of all superclasses that you can use. Deriving from +``ModulePass`` indicates that your pass uses the entire program as a unit, +referring to function bodies in no predictable order, or adding and removing +functions. Because nothing is known about the behavior of ``ModulePass`` +subclasses, no optimization can be done for their execution. + +A module pass can use function level passes (e.g. dominators) using the +``getAnalysis`` interface ``getAnalysis(llvm::Function *)`` to +provide the function to retrieve analysis result for, if the function pass does +not require any module or immutable passes. Note that this can only be done +for functions for which the analysis ran, e.g. in the case of dominators you +should only ask for the ``DominatorTree`` for function definitions, not +declarations. + +To write a correct ``ModulePass`` subclass, derive from ``ModulePass`` and +overload the ``runOnModule`` method with the following signature: + +The ``runOnModule`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool runOnModule(Module &M) = 0; + +The ``runOnModule`` method performs the interesting work of the pass. It +should return ``true`` if the module was modified by the transformation and +``false`` otherwise. + +.. _writing-an-llvm-pass-CallGraphSCCPass: + +The ``CallGraphSCCPass`` class +------------------------------ + +The `CallGraphSCCPass +`_ is used by +passes that need to traverse the program bottom-up on the call graph (callees +before callers). Deriving from ``CallGraphSCCPass`` provides some mechanics +for building and traversing the ``CallGraph``, but also allows the system to +optimize execution of ``CallGraphSCCPass``\ es. If your pass meets the +requirements outlined below, and doesn't meet the requirements of a +:ref:`FunctionPass ` or :ref:`BasicBlockPass +`, you should derive from +``CallGraphSCCPass``. + +``TODO``: explain briefly what SCC, Tarjan's algo, and B-U mean. + +To be explicit, CallGraphSCCPass subclasses are: + +#. ... *not allowed* to inspect or modify any ``Function``\ s other than those + in the current SCC and the direct callers and direct callees of the SCC. +#. ... *required* to preserve the current ``CallGraph`` object, updating it to + reflect any changes made to the program. +#. ... *not allowed* to add or remove SCC's from the current Module, though + they may change the contents of an SCC. +#. ... *allowed* to add or remove global variables from the current Module. +#. ... *allowed* to maintain state across invocations of :ref:`runOnSCC + ` (including global data). + +Implementing a ``CallGraphSCCPass`` is slightly tricky in some cases because it +has to handle SCCs with more than one node in it. All of the virtual methods +described below should return ``true`` if they modified the program, or +``false`` if they didn't. + +The ``doInitialization(CallGraph &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doInitialization(CallGraph &CG); + +The ``doInitialization`` method is allowed to do most of the things that +``CallGraphSCCPass``\ es are not allowed to do. They can add and remove +functions, get pointers to functions, etc. The ``doInitialization`` method is +designed to do simple initialization type of stuff that does not depend on the +SCCs being processed. The ``doInitialization`` method call is not scheduled to +overlap with any other pass executions (thus it should be very fast). + +.. _writing-an-llvm-pass-runOnSCC: + +The ``runOnSCC`` method +^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool runOnSCC(CallGraphSCC &SCC) = 0; + +The ``runOnSCC`` method performs the interesting work of the pass, and should +return ``true`` if the module was modified by the transformation, ``false`` +otherwise. + +The ``doFinalization(CallGraph &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doFinalization(CallGraph &CG); + +The ``doFinalization`` method is an infrequently used method that is called +when the pass framework has finished calling :ref:`runOnFunction +` for every function in the program being +compiled. + +.. _writing-an-llvm-pass-FunctionPass: + +The ``FunctionPass`` class +-------------------------- + +In contrast to ``ModulePass`` subclasses, `FunctionPass +`_ subclasses do have a +predictable, local behavior that can be expected by the system. All +``FunctionPass`` execute on each function in the program independent of all of +the other functions in the program. ``FunctionPass``\ es do not require that +they are executed in a particular order, and ``FunctionPass``\ es do not modify +external functions. + +To be explicit, ``FunctionPass`` subclasses are not allowed to: + +#. Inspect or modify a ``Function`` other than the one currently being processed. +#. Add or remove ``Function``\ s from the current ``Module``. +#. Add or remove global variables from the current ``Module``. +#. Maintain state across invocations of:ref:`runOnFunction + ` (including global data). + +Implementing a ``FunctionPass`` is usually straightforward (See the :ref:`Hello +World ` pass for example). +``FunctionPass``\ es may overload three virtual methods to do their work. All +of these methods should return ``true`` if they modified the program, or +``false`` if they didn't. + +.. _writing-an-llvm-pass-doInitialization-mod: + +The ``doInitialization(Module &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doInitialization(Module &M); + +The ``doInitialization`` method is allowed to do most of the things that +``FunctionPass``\ es are not allowed to do. They can add and remove functions, +get pointers to functions, etc. The ``doInitialization`` method is designed to +do simple initialization type of stuff that does not depend on the functions +being processed. The ``doInitialization`` method call is not scheduled to +overlap with any other pass executions (thus it should be very fast). + +A good example of how this method should be used is the `LowerAllocations +`_ pass. This pass +converts ``malloc`` and ``free`` instructions into platform dependent +``malloc()`` and ``free()`` function calls. It uses the ``doInitialization`` +method to get a reference to the ``malloc`` and ``free`` functions that it +needs, adding prototypes to the module if necessary. + +.. _writing-an-llvm-pass-runOnFunction: + +The ``runOnFunction`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool runOnFunction(Function &F) = 0; + +The ``runOnFunction`` method must be implemented by your subclass to do the +transformation or analysis work of your pass. As usual, a ``true`` value +should be returned if the function is modified. + +.. _writing-an-llvm-pass-doFinalization-mod: + +The ``doFinalization(Module &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doFinalization(Module &M); + +The ``doFinalization`` method is an infrequently used method that is called +when the pass framework has finished calling :ref:`runOnFunction +` for every function in the program being +compiled. + +.. _writing-an-llvm-pass-LoopPass: + +The ``LoopPass`` class +---------------------- + +All ``LoopPass`` execute on each loop in the function independent of all of the +other loops in the function. ``LoopPass`` processes loops in loop nest order +such that outer most loop is processed last. + +``LoopPass`` subclasses are allowed to update loop nest using ``LPPassManager`` +interface. Implementing a loop pass is usually straightforward. +``LoopPass``\ es may overload three virtual methods to do their work. All +these methods should return ``true`` if they modified the program, or ``false`` +if they didn't. + +The ``doInitialization(Loop *, LPPassManager &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doInitialization(Loop *, LPPassManager &LPM); + +The ``doInitialization`` method is designed to do simple initialization type of +stuff that does not depend on the functions being processed. The +``doInitialization`` method call is not scheduled to overlap with any other +pass executions (thus it should be very fast). ``LPPassManager`` interface +should be used to access ``Function`` or ``Module`` level analysis information. + +.. _writing-an-llvm-pass-runOnLoop: + +The ``runOnLoop`` method +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool runOnLoop(Loop *, LPPassManager &LPM) = 0; + +The ``runOnLoop`` method must be implemented by your subclass to do the +transformation or analysis work of your pass. As usual, a ``true`` value +should be returned if the function is modified. ``LPPassManager`` interface +should be used to update loop nest. + +The ``doFinalization()`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doFinalization(); + +The ``doFinalization`` method is an infrequently used method that is called +when the pass framework has finished calling :ref:`runOnLoop +` for every loop in the program being compiled. + +.. _writing-an-llvm-pass-RegionPass: + +The ``RegionPass`` class +------------------------ + +``RegionPass`` is similar to :ref:`LoopPass `, +but executes on each single entry single exit region in the function. +``RegionPass`` processes regions in nested order such that the outer most +region is processed last. + +``RegionPass`` subclasses are allowed to update the region tree by using the +``RGPassManager`` interface. You may overload three virtual methods of +``RegionPass`` to implement your own region pass. All these methods should +return ``true`` if they modified the program, or ``false`` if they did not. + +The ``doInitialization(Region *, RGPassManager &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doInitialization(Region *, RGPassManager &RGM); + +The ``doInitialization`` method is designed to do simple initialization type of +stuff that does not depend on the functions being processed. The +``doInitialization`` method call is not scheduled to overlap with any other +pass executions (thus it should be very fast). ``RPPassManager`` interface +should be used to access ``Function`` or ``Module`` level analysis information. + +.. _writing-an-llvm-pass-runOnRegion: + +The ``runOnRegion`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool runOnRegion(Region *, RGPassManager &RGM) = 0; + +The ``runOnRegion`` method must be implemented by your subclass to do the +transformation or analysis work of your pass. As usual, a true value should be +returned if the region is modified. ``RGPassManager`` interface should be used to +update region tree. + +The ``doFinalization()`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doFinalization(); + +The ``doFinalization`` method is an infrequently used method that is called +when the pass framework has finished calling :ref:`runOnRegion +` for every region in the program being +compiled. + +.. _writing-an-llvm-pass-BasicBlockPass: + +The ``BasicBlockPass`` class +---------------------------- + +``BasicBlockPass``\ es are just like :ref:`FunctionPass's +` , except that they must limit their scope +of inspection and modification to a single basic block at a time. As such, +they are **not** allowed to do any of the following: + +#. Modify or inspect any basic blocks outside of the current one. +#. Maintain state across invocations of :ref:`runOnBasicBlock + `. +#. Modify the control flow graph (by altering terminator instructions) +#. Any of the things forbidden for :ref:`FunctionPasses + `. + +``BasicBlockPass``\ es are useful for traditional local and "peephole" +optimizations. They may override the same :ref:`doInitialization(Module &) +` and :ref:`doFinalization(Module &) +` methods that :ref:`FunctionPass's +` have, but also have the following virtual +methods that may also be implemented: + +The ``doInitialization(Function &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doInitialization(Function &F); + +The ``doInitialization`` method is allowed to do most of the things that +``BasicBlockPass``\ es are not allowed to do, but that ``FunctionPass``\ es +can. The ``doInitialization`` method is designed to do simple initialization +that does not depend on the ``BasicBlock``\ s being processed. The +``doInitialization`` method call is not scheduled to overlap with any other +pass executions (thus it should be very fast). + +.. _writing-an-llvm-pass-runOnBasicBlock: + +The ``runOnBasicBlock`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool runOnBasicBlock(BasicBlock &BB) = 0; + +Override this function to do the work of the ``BasicBlockPass``. This function +is not allowed to inspect or modify basic blocks other than the parameter, and +are not allowed to modify the CFG. A ``true`` value must be returned if the +basic block is modified. + +The ``doFinalization(Function &)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool doFinalization(Function &F); + +The ``doFinalization`` method is an infrequently used method that is called +when the pass framework has finished calling :ref:`runOnBasicBlock +` for every ``BasicBlock`` in the program +being compiled. This can be used to perform per-function finalization. + +The ``MachineFunctionPass`` class +--------------------------------- + +A ``MachineFunctionPass`` is a part of the LLVM code generator that executes on +the machine-dependent representation of each LLVM function in the program. + +Code generator passes are registered and initialized specially by +``TargetMachine::addPassesToEmitFile`` and similar routines, so they cannot +generally be run from the :program:`opt` or :program:`bugpoint` commands. + +A ``MachineFunctionPass`` is also a ``FunctionPass``, so all the restrictions +that apply to a ``FunctionPass`` also apply to it. ``MachineFunctionPass``\ es +also have additional restrictions. In particular, ``MachineFunctionPass``\ es +are not allowed to do any of the following: + +#. Modify or create any LLVM IR ``Instruction``\ s, ``BasicBlock``\ s, + ``Argument``\ s, ``Function``\ s, ``GlobalVariable``\ s, + ``GlobalAlias``\ es, or ``Module``\ s. +#. Modify a ``MachineFunction`` other than the one currently being processed. +#. Maintain state across invocations of :ref:`runOnMachineFunction + ` (including global data). + +.. _writing-an-llvm-pass-runOnMachineFunction: + +The ``runOnMachineFunction(MachineFunction &MF)`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual bool runOnMachineFunction(MachineFunction &MF) = 0; + +``runOnMachineFunction`` can be considered the main entry point of a +``MachineFunctionPass``; that is, you should override this method to do the +work of your ``MachineFunctionPass``. + +The ``runOnMachineFunction`` method is called on every ``MachineFunction`` in a +``Module``, so that the ``MachineFunctionPass`` may perform optimizations on +the machine-dependent representation of the function. If you want to get at +the LLVM ``Function`` for the ``MachineFunction`` you're working on, use +``MachineFunction``'s ``getFunction()`` accessor method --- but remember, you +may not modify the LLVM ``Function`` or its contents from a +``MachineFunctionPass``. + +.. _writing-an-llvm-pass-registration: + +Pass registration +----------------- + +In the :ref:`Hello World ` example pass we +illustrated how pass registration works, and discussed some of the reasons that +it is used and what it does. Here we discuss how and why passes are +registered. + +As we saw above, passes are registered with the ``RegisterPass`` template. The +template parameter is the name of the pass that is to be used on the command +line to specify that the pass should be added to a program (for example, with +:program:`opt` or :program:`bugpoint`). The first argument is the name of the +pass, which is to be used for the :option:`-help` output of programs, as well +as for debug output generated by the :option:`--debug-pass` option. + +If you want your pass to be easily dumpable, you should implement the virtual +print method: + +The ``print`` method +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual void print(llvm::raw_ostream &O, const Module *M) const; + +The ``print`` method must be implemented by "analyses" in order to print a +human readable version of the analysis results. This is useful for debugging +an analysis itself, as well as for other people to figure out how an analysis +works. Use the opt ``-analyze`` argument to invoke this method. + +The ``llvm::raw_ostream`` parameter specifies the stream to write the results +on, and the ``Module`` parameter gives a pointer to the top level module of the +program that has been analyzed. Note however that this pointer may be ``NULL`` +in certain circumstances (such as calling the ``Pass::dump()`` from a +debugger), so it should only be used to enhance debug output, it should not be +depended on. + +.. _writing-an-llvm-pass-interaction: + +Specifying interactions between passes +-------------------------------------- + +One of the main responsibilities of the ``PassManager`` is to make sure that +passes interact with each other correctly. Because ``PassManager`` tries to +:ref:`optimize the execution of passes ` it +must know how the passes interact with each other and what dependencies exist +between the various passes. To track this, each pass can declare the set of +passes that are required to be executed before the current pass, and the passes +which are invalidated by the current pass. + +Typically this functionality is used to require that analysis results are +computed before your pass is run. Running arbitrary transformation passes can +invalidate the computed analysis results, which is what the invalidation set +specifies. If a pass does not implement the :ref:`getAnalysisUsage +` method, it defaults to not having any +prerequisite passes, and invalidating **all** other passes. + +.. _writing-an-llvm-pass-getAnalysisUsage: + +The ``getAnalysisUsage`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual void getAnalysisUsage(AnalysisUsage &Info) const; + +By implementing the ``getAnalysisUsage`` method, the required and invalidated +sets may be specified for your transformation. The implementation should fill +in the `AnalysisUsage +`_ object with +information about which passes are required and not invalidated. To do this, a +pass may call any of the following methods on the ``AnalysisUsage`` object: + +The ``AnalysisUsage::addRequired<>`` and ``AnalysisUsage::addRequiredTransitive<>`` methods +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If your pass requires a previous pass to be executed (an analysis for example), +it can use one of these methods to arrange for it to be run before your pass. +LLVM has many different types of analyses and passes that can be required, +spanning the range from ``DominatorSet`` to ``BreakCriticalEdges``. Requiring +``BreakCriticalEdges``, for example, guarantees that there will be no critical +edges in the CFG when your pass has been run. + +Some analyses chain to other analyses to do their job. For example, an +`AliasAnalysis ` implementation is required to :ref:`chain +` to other alias analysis passes. In cases where +analyses chain, the ``addRequiredTransitive`` method should be used instead of +the ``addRequired`` method. This informs the ``PassManager`` that the +transitively required pass should be alive as long as the requiring pass is. + +The ``AnalysisUsage::addPreserved<>`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One of the jobs of the ``PassManager`` is to optimize how and when analyses are +run. In particular, it attempts to avoid recomputing data unless it needs to. +For this reason, passes are allowed to declare that they preserve (i.e., they +don't invalidate) an existing analysis if it's available. For example, a +simple constant folding pass would not modify the CFG, so it can't possibly +affect the results of dominator analysis. By default, all passes are assumed +to invalidate all others. + +The ``AnalysisUsage`` class provides several methods which are useful in +certain circumstances that are related to ``addPreserved``. In particular, the +``setPreservesAll`` method can be called to indicate that the pass does not +modify the LLVM program at all (which is true for analyses), and the +``setPreservesCFG`` method can be used by transformations that change +instructions in the program but do not modify the CFG or terminator +instructions (note that this property is implicitly set for +:ref:`BasicBlockPass `\ es). + +``addPreserved`` is particularly useful for transformations like +``BreakCriticalEdges``. This pass knows how to update a small set of loop and +dominator related analyses if they exist, so it can preserve them, despite the +fact that it hacks on the CFG. + +Example implementations of ``getAnalysisUsage`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + // This example modifies the program, but does not modify the CFG + void LICM::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + } + +.. _writing-an-llvm-pass-getAnalysis: + +The ``getAnalysis<>`` and ``getAnalysisIfAvailable<>`` methods +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``Pass::getAnalysis<>`` method is automatically inherited by your class, +providing you with access to the passes that you declared that you required +with the :ref:`getAnalysisUsage ` +method. It takes a single template argument that specifies which pass class +you want, and returns a reference to that pass. For example: + +.. code-block:: c++ + + bool LICM::runOnFunction(Function &F) { + LoopInfo &LI = getAnalysis(); + //... + } + +This method call returns a reference to the pass desired. You may get a +runtime assertion failure if you attempt to get an analysis that you did not +declare as required in your :ref:`getAnalysisUsage +` implementation. This method can be +called by your ``run*`` method implementation, or by any other local method +invoked by your ``run*`` method. + +A module level pass can use function level analysis info using this interface. +For example: + +.. code-block:: c++ + + bool ModuleLevelPass::runOnModule(Module &M) { + //... + DominatorTree &DT = getAnalysis(Func); + //... + } + +In above example, ``runOnFunction`` for ``DominatorTree`` is called by pass +manager before returning a reference to the desired pass. + +If your pass is capable of updating analyses if they exist (e.g., +``BreakCriticalEdges``, as described above), you can use the +``getAnalysisIfAvailable`` method, which returns a pointer to the analysis if +it is active. For example: + +.. code-block:: c++ + + if (DominatorSet *DS = getAnalysisIfAvailable()) { + // A DominatorSet is active. This code will update it. + } + +Implementing Analysis Groups +---------------------------- + +Now that we understand the basics of how passes are defined, how they are used, +and how they are required from other passes, it's time to get a little bit +fancier. All of the pass relationships that we have seen so far are very +simple: one pass depends on one other specific pass to be run before it can +run. For many applications, this is great, for others, more flexibility is +required. + +In particular, some analyses are defined such that there is a single simple +interface to the analysis results, but multiple ways of calculating them. +Consider alias analysis for example. The most trivial alias analysis returns +"may alias" for any alias query. The most sophisticated analysis a +flow-sensitive, context-sensitive interprocedural analysis that can take a +significant amount of time to execute (and obviously, there is a lot of room +between these two extremes for other implementations). To cleanly support +situations like this, the LLVM Pass Infrastructure supports the notion of +Analysis Groups. + +Analysis Group Concepts +^^^^^^^^^^^^^^^^^^^^^^^ + +An Analysis Group is a single simple interface that may be implemented by +multiple different passes. Analysis Groups can be given human readable names +just like passes, but unlike passes, they need not derive from the ``Pass`` +class. An analysis group may have one or more implementations, one of which is +the "default" implementation. + +Analysis groups are used by client passes just like other passes are: the +``AnalysisUsage::addRequired()`` and ``Pass::getAnalysis()`` methods. In order +to resolve this requirement, the :ref:`PassManager +` scans the available passes to see if any +implementations of the analysis group are available. If none is available, the +default implementation is created for the pass to use. All standard rules for +:ref:`interaction between passes ` still +apply. + +Although :ref:`Pass Registration ` is +optional for normal passes, all analysis group implementations must be +registered, and must use the :ref:`INITIALIZE_AG_PASS +` template to join the +implementation pool. Also, a default implementation of the interface **must** +be registered with :ref:`RegisterAnalysisGroup +`. + +As a concrete example of an Analysis Group in action, consider the +`AliasAnalysis `_ +analysis group. The default implementation of the alias analysis interface +(the `basicaa `_ pass) +just does a few simple checks that don't require significant analysis to +compute (such as: two different globals can never alias each other, etc). +Passes that use the `AliasAnalysis +`_ interface (for +example the `gcse `_ pass), do not +care which implementation of alias analysis is actually provided, they just use +the designated interface. + +From the user's perspective, commands work just like normal. Issuing the +command ``opt -gcse ...`` will cause the ``basicaa`` class to be instantiated +and added to the pass sequence. Issuing the command ``opt -somefancyaa -gcse +...`` will cause the ``gcse`` pass to use the ``somefancyaa`` alias analysis +(which doesn't actually exist, it's just a hypothetical example) instead. + +.. _writing-an-llvm-pass-RegisterAnalysisGroup: + +Using ``RegisterAnalysisGroup`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``RegisterAnalysisGroup`` template is used to register the analysis group +itself, while the ``INITIALIZE_AG_PASS`` is used to add pass implementations to +the analysis group. First, an analysis group should be registered, with a +human readable name provided for it. Unlike registration of passes, there is +no command line argument to be specified for the Analysis Group Interface +itself, because it is "abstract": + +.. code-block:: c++ + + static RegisterAnalysisGroup A("Alias Analysis"); + +Once the analysis is registered, passes can declare that they are valid +implementations of the interface by using the following code: + +.. code-block:: c++ + + namespace { + // Declare that we implement the AliasAnalysis interface + INITIALIZE_AG_PASS(FancyAA, AliasAnalysis , "somefancyaa", + "A more complex alias analysis implementation", + false, // Is CFG Only? + true, // Is Analysis? + false); // Is default Analysis Group implementation? + } + +This just shows a class ``FancyAA`` that uses the ``INITIALIZE_AG_PASS`` macro +both to register and to "join" the `AliasAnalysis +`_ analysis group. +Every implementation of an analysis group should join using this macro. + +.. code-block:: c++ + + namespace { + // Declare that we implement the AliasAnalysis interface + INITIALIZE_AG_PASS(BasicAA, AliasAnalysis, "basicaa", + "Basic Alias Analysis (default AA impl)", + false, // Is CFG Only? + true, // Is Analysis? + true); // Is default Analysis Group implementation? + } + +Here we show how the default implementation is specified (using the final +argument to the ``INITIALIZE_AG_PASS`` template). There must be exactly one +default implementation available at all times for an Analysis Group to be used. +Only default implementation can derive from ``ImmutablePass``. Here we declare +that the `BasicAliasAnalysis +`_ pass is the default +implementation for the interface. + +Pass Statistics +=============== + +The `Statistic `_ class is +designed to be an easy way to expose various success metrics from passes. +These statistics are printed at the end of a run, when the :option:`-stats` +command line option is enabled on the command line. See the :ref:`Statistics +section ` in the Programmer's Manual for details. + +.. _writing-an-llvm-pass-passmanager: + +What PassManager does +--------------------- + +The `PassManager `_ `class +`_ takes a list of +passes, ensures their :ref:`prerequisites ` +are set up correctly, and then schedules passes to run efficiently. All of the +LLVM tools that run passes use the PassManager for execution of these passes. + +The PassManager does two main things to try to reduce the execution time of a +series of passes: + +#. **Share analysis results.** The ``PassManager`` attempts to avoid + recomputing analysis results as much as possible. This means keeping track + of which analyses are available already, which analyses get invalidated, and + which analyses are needed to be run for a pass. An important part of work + is that the ``PassManager`` tracks the exact lifetime of all analysis + results, allowing it to :ref:`free memory + ` allocated to holding analysis results + as soon as they are no longer needed. + +#. **Pipeline the execution of passes on the program.** The ``PassManager`` + attempts to get better cache and memory usage behavior out of a series of + passes by pipelining the passes together. This means that, given a series + of consecutive :ref:`FunctionPass `, it + will execute all of the :ref:`FunctionPass + ` on the first function, then all of the + :ref:`FunctionPasses ` on the second + function, etc... until the entire program has been run through the passes. + + This improves the cache behavior of the compiler, because it is only + touching the LLVM program representation for a single function at a time, + instead of traversing the entire program. It reduces the memory consumption + of compiler, because, for example, only one `DominatorSet + `_ needs to be + calculated at a time. This also makes it possible to implement some + :ref:`interesting enhancements ` in the future. + +The effectiveness of the ``PassManager`` is influenced directly by how much +information it has about the behaviors of the passes it is scheduling. For +example, the "preserved" set is intentionally conservative in the face of an +unimplemented :ref:`getAnalysisUsage ` +method. Not implementing when it should be implemented will have the effect of +not allowing any analysis results to live across the execution of your pass. + +The ``PassManager`` class exposes a ``--debug-pass`` command line options that +is useful for debugging pass execution, seeing how things work, and diagnosing +when you should be preserving more analyses than you currently are. (To get +information about all of the variants of the ``--debug-pass`` option, just type +"``opt -help-hidden``"). + +By using the --debug-pass=Structure option, for example, we can see how our +:ref:`Hello World ` pass interacts with other +passes. Lets try it out with the gcse and licm passes: + +.. code-block:: console + + $ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -licm --debug-pass=Structure < hello.bc > /dev/null + Module Pass Manager + Function Pass Manager + Dominator Set Construction + Immediate Dominators Construction + Global Common Subexpression Elimination + -- Immediate Dominators Construction + -- Global Common Subexpression Elimination + Natural Loop Construction + Loop Invariant Code Motion + -- Natural Loop Construction + -- Loop Invariant Code Motion + Module Verifier + -- Dominator Set Construction + -- Module Verifier + Bitcode Writer + --Bitcode Writer + +This output shows us when passes are constructed and when the analysis results +are known to be dead (prefixed with "``--``"). Here we see that GCSE uses +dominator and immediate dominator information to do its job. The LICM pass +uses natural loop information, which uses dominator sets, but not immediate +dominators. Because immediate dominators are no longer useful after the GCSE +pass, it is immediately destroyed. The dominator sets are then reused to +compute natural loop information, which is then used by the LICM pass. + +After the LICM pass, the module verifier runs (which is automatically added by +the :program:`opt` tool), which uses the dominator set to check that the +resultant LLVM code is well formed. After it finishes, the dominator set +information is destroyed, after being computed once, and shared by three +passes. + +Lets see how this changes when we run the :ref:`Hello World +` pass in between the two passes: + +.. code-block:: console + + $ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null + Module Pass Manager + Function Pass Manager + Dominator Set Construction + Immediate Dominators Construction + Global Common Subexpression Elimination + -- Dominator Set Construction + -- Immediate Dominators Construction + -- Global Common Subexpression Elimination + Hello World Pass + -- Hello World Pass + Dominator Set Construction + Natural Loop Construction + Loop Invariant Code Motion + -- Natural Loop Construction + -- Loop Invariant Code Motion + Module Verifier + -- Dominator Set Construction + -- Module Verifier + Bitcode Writer + --Bitcode Writer + Hello: __main + Hello: puts + Hello: main + +Here we see that the :ref:`Hello World ` pass +has killed the Dominator Set pass, even though it doesn't modify the code at +all! To fix this, we need to add the following :ref:`getAnalysisUsage +` method to our pass: + +.. code-block:: c++ + + // We don't modify the program, so we preserve all analyses + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + +Now when we run our pass, we get this output: + +.. code-block:: console + + $ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null + Pass Arguments: -gcse -hello -licm + Module Pass Manager + Function Pass Manager + Dominator Set Construction + Immediate Dominators Construction + Global Common Subexpression Elimination + -- Immediate Dominators Construction + -- Global Common Subexpression Elimination + Hello World Pass + -- Hello World Pass + Natural Loop Construction + Loop Invariant Code Motion + -- Loop Invariant Code Motion + -- Natural Loop Construction + Module Verifier + -- Dominator Set Construction + -- Module Verifier + Bitcode Writer + --Bitcode Writer + Hello: __main + Hello: puts + Hello: main + +Which shows that we don't accidentally invalidate dominator information +anymore, and therefore do not have to compute it twice. + +.. _writing-an-llvm-pass-releaseMemory: + +The ``releaseMemory`` method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c++ + + virtual void releaseMemory(); + +The ``PassManager`` automatically determines when to compute analysis results, +and how long to keep them around for. Because the lifetime of the pass object +itself is effectively the entire duration of the compilation process, we need +some way to free analysis results when they are no longer useful. The +``releaseMemory`` virtual method is the way to do this. + +If you are writing an analysis or any other pass that retains a significant +amount of state (for use by another pass which "requires" your pass and uses +the :ref:`getAnalysis ` method) you should +implement ``releaseMemory`` to, well, release the memory allocated to maintain +this internal state. This method is called after the ``run*`` method for the +class, before the next call of ``run*`` in your pass. + +Registering dynamically loaded passes +===================================== + +*Size matters* when constructing production quality tools using LLVM, both for +the purposes of distribution, and for regulating the resident code size when +running on the target system. Therefore, it becomes desirable to selectively +use some passes, while omitting others and maintain the flexibility to change +configurations later on. You want to be able to do all this, and, provide +feedback to the user. This is where pass registration comes into play. + +The fundamental mechanisms for pass registration are the +``MachinePassRegistry`` class and subclasses of ``MachinePassRegistryNode``. + +An instance of ``MachinePassRegistry`` is used to maintain a list of +``MachinePassRegistryNode`` objects. This instance maintains the list and +communicates additions and deletions to the command line interface. + +An instance of ``MachinePassRegistryNode`` subclass is used to maintain +information provided about a particular pass. This information includes the +command line name, the command help string and the address of the function used +to create an instance of the pass. A global static constructor of one of these +instances *registers* with a corresponding ``MachinePassRegistry``, the static +destructor *unregisters*. Thus a pass that is statically linked in the tool +will be registered at start up. A dynamically loaded pass will register on +load and unregister at unload. + +Using existing registries +------------------------- + +There are predefined registries to track instruction scheduling +(``RegisterScheduler``) and register allocation (``RegisterRegAlloc``) machine +passes. Here we will describe how to *register* a register allocator machine +pass. + +Implement your register allocator machine pass. In your register allocator +``.cpp`` file add the following include: + +.. code-block:: c++ + + #include "llvm/CodeGen/RegAllocRegistry.h" + +Also in your register allocator ``.cpp`` file, define a creator function in the +form: + +.. code-block:: c++ + + FunctionPass *createMyRegisterAllocator() { + return new MyRegisterAllocator(); + } + +Note that the signature of this function should match the type of +``RegisterRegAlloc::FunctionPassCtor``. In the same file add the "installing" +declaration, in the form: + +.. code-block:: c++ + + static RegisterRegAlloc myRegAlloc("myregalloc", + "my register allocator help string", + createMyRegisterAllocator); + +Note the two spaces prior to the help string produces a tidy result on the +:option:`-help` query. + +.. code-block:: console + + $ llc -help + ... + -regalloc - Register allocator to use (default=linearscan) + =linearscan - linear scan register allocator + =local - local register allocator + =simple - simple register allocator + =myregalloc - my register allocator help string + ... + +And that's it. The user is now free to use ``-regalloc=myregalloc`` as an +option. Registering instruction schedulers is similar except use the +``RegisterScheduler`` class. Note that the +``RegisterScheduler::FunctionPassCtor`` is significantly different from +``RegisterRegAlloc::FunctionPassCtor``. + +To force the load/linking of your register allocator into the +:program:`llc`/:program:`lli` tools, add your creator function's global +declaration to ``Passes.h`` and add a "pseudo" call line to +``llvm/Codegen/LinkAllCodegenComponents.h``. + +Creating new registries +----------------------- + +The easiest way to get started is to clone one of the existing registries; we +recommend ``llvm/CodeGen/RegAllocRegistry.h``. The key things to modify are +the class name and the ``FunctionPassCtor`` type. + +Then you need to declare the registry. Example: if your pass registry is +``RegisterMyPasses`` then define: + +.. code-block:: c++ + + MachinePassRegistry RegisterMyPasses::Registry; + +And finally, declare the command line option for your passes. Example: + +.. code-block:: c++ + + cl::opt > + MyPassOpt("mypass", + cl::init(&createDefaultMyPass), + cl::desc("my pass option help")); + +Here the command option is "``mypass``", with ``createDefaultMyPass`` as the +default creator. + +Using GDB with dynamically loaded passes +---------------------------------------- + +Unfortunately, using GDB with dynamically loaded passes is not as easy as it +should be. First of all, you can't set a breakpoint in a shared object that +has not been loaded yet, and second of all there are problems with inlined +functions in shared objects. Here are some suggestions to debugging your pass +with GDB. + +For sake of discussion, I'm going to assume that you are debugging a +transformation invoked by :program:`opt`, although nothing described here +depends on that. + +Setting a breakpoint in your pass +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +First thing you do is start gdb on the opt process: + +.. code-block:: console + + $ gdb opt + GNU gdb 5.0 + Copyright 2000 Free Software Foundation, Inc. + GDB is free software, covered by the GNU General Public License, and you are + welcome to change it and/or distribute copies of it under certain conditions. + Type "show copying" to see the conditions. + There is absolutely no warranty for GDB. Type "show warranty" for details. + This GDB was configured as "sparc-sun-solaris2.6"... + (gdb) + +Note that :program:`opt` has a lot of debugging information in it, so it takes +time to load. Be patient. Since we cannot set a breakpoint in our pass yet +(the shared object isn't loaded until runtime), we must execute the process, +and have it stop before it invokes our pass, but after it has loaded the shared +object. The most foolproof way of doing this is to set a breakpoint in +``PassManager::run`` and then run the process with the arguments you want: + +.. code-block:: console + + $ (gdb) break llvm::PassManager::run + Breakpoint 1 at 0x2413bc: file Pass.cpp, line 70. + (gdb) run test.bc -load $(LLVMTOP)/llvm/Debug+Asserts/lib/[libname].so -[passoption] + Starting program: opt test.bc -load $(LLVMTOP)/llvm/Debug+Asserts/lib/[libname].so -[passoption] + Breakpoint 1, PassManager::run (this=0xffbef174, M=@0x70b298) at Pass.cpp:70 + 70 bool PassManager::run(Module &M) { return PM->run(M); } + (gdb) + +Once the :program:`opt` stops in the ``PassManager::run`` method you are now +free to set breakpoints in your pass so that you can trace through execution or +do other standard debugging stuff. + +Miscellaneous Problems +^^^^^^^^^^^^^^^^^^^^^^ + +Once you have the basics down, there are a couple of problems that GDB has, +some with solutions, some without. + +* Inline functions have bogus stack information. In general, GDB does a pretty + good job getting stack traces and stepping through inline functions. When a + pass is dynamically loaded however, it somehow completely loses this + capability. The only solution I know of is to de-inline a function (move it + from the body of a class to a ``.cpp`` file). + +* Restarting the program breaks breakpoints. After following the information + above, you have succeeded in getting some breakpoints planted in your pass. + Nex thing you know, you restart the program (i.e., you type "``run``" again), + and you start getting errors about breakpoints being unsettable. The only + way I have found to "fix" this problem is to delete the breakpoints that are + already set in your pass, run the program, and re-set the breakpoints once + execution stops in ``PassManager::run``. + +Hopefully these tips will help with common case debugging situations. If you'd +like to contribute some tips of your own, just contact `Chris +`_. + +Future extensions planned +------------------------- + +Although the LLVM Pass Infrastructure is very capable as it stands, and does +some nifty stuff, there are things we'd like to add in the future. Here is +where we are going: + +.. _writing-an-llvm-pass-SMP: + +Multithreaded LLVM +^^^^^^^^^^^^^^^^^^ + +Multiple CPU machines are becoming more common and compilation can never be +fast enough: obviously we should allow for a multithreaded compiler. Because +of the semantics defined for passes above (specifically they cannot maintain +state across invocations of their ``run*`` methods), a nice clean way to +implement a multithreaded compiler would be for the ``PassManager`` class to +create multiple instances of each pass object, and allow the separate instances +to be hacking on different parts of the program at the same time. + +This implementation would prevent each of the passes from having to implement +multithreaded constructs, requiring only the LLVM core to have locking in a few +places (for global resources). Although this is a simple extension, we simply +haven't had time (or multiprocessor machines, thus a reason) to implement this. +Despite that, we have kept the LLVM passes SMP ready, and you should too. + diff --git a/docs/YamlIO.rst b/docs/YamlIO.rst new file mode 100644 index 00000000..3ecd03af --- /dev/null +++ b/docs/YamlIO.rst @@ -0,0 +1,874 @@ +===================== +YAML I/O +===================== + +.. contents:: + :local: + +Introduction to YAML +==================== + +YAML is a human readable data serialization language. The full YAML language +spec can be read at `yaml.org +`_. The simplest form of +yaml is just "scalars", "mappings", and "sequences". A scalar is any number +or string. The pound/hash symbol (#) begins a comment line. A mapping is +a set of key-value pairs where the key ends with a colon. For example: + +.. code-block:: yaml + + # a mapping + name: Tom + hat-size: 7 + +A sequence is a list of items where each item starts with a leading dash ('-'). +For example: + +.. code-block:: yaml + + # a sequence + - x86 + - x86_64 + - PowerPC + +You can combine mappings and sequences by indenting. For example a sequence +of mappings in which one of the mapping values is itself a sequence: + +.. code-block:: yaml + + # a sequence of mappings with one key's value being a sequence + - name: Tom + cpus: + - x86 + - x86_64 + - name: Bob + cpus: + - x86 + - name: Dan + cpus: + - PowerPC + - x86 + +Sometime sequences are known to be short and the one entry per line is too +verbose, so YAML offers an alternate syntax for sequences called a "Flow +Sequence" in which you put comma separated sequence elements into square +brackets. The above example could then be simplified to : + + +.. code-block:: yaml + + # a sequence of mappings with one key's value being a flow sequence + - name: Tom + cpus: [ x86, x86_64 ] + - name: Bob + cpus: [ x86 ] + - name: Dan + cpus: [ PowerPC, x86 ] + + +Introduction to YAML I/O +======================== + +The use of indenting makes the YAML easy for a human to read and understand, +but having a program read and write YAML involves a lot of tedious details. +The YAML I/O library structures and simplifies reading and writing YAML +documents. + +YAML I/O assumes you have some "native" data structures which you want to be +able to dump as YAML and recreate from YAML. The first step is to try +writing example YAML for your data structures. You may find after looking at +possible YAML representations that a direct mapping of your data structures +to YAML is not very readable. Often the fields are not in the order that +a human would find readable. Or the same information is replicated in multiple +locations, making it hard for a human to write such YAML correctly. + +In relational database theory there is a design step called normalization in +which you reorganize fields and tables. The same considerations need to +go into the design of your YAML encoding. But, you may not want to change +your existing native data structures. Therefore, when writing out YAML +there may be a normalization step, and when reading YAML there would be a +corresponding denormalization step. + +YAML I/O uses a non-invasive, traits based design. YAML I/O defines some +abstract base templates. You specialize those templates on your data types. +For instance, if you have an enumerated type FooBar you could specialize +ScalarEnumerationTraits on that type and define the enumeration() method: + +.. code-block:: c++ + + using llvm::yaml::ScalarEnumerationTraits; + using llvm::yaml::IO; + + template <> + struct ScalarEnumerationTraits { + static void enumeration(IO &io, FooBar &value) { + ... + } + }; + + +As with all YAML I/O template specializations, the ScalarEnumerationTraits is used for +both reading and writing YAML. That is, the mapping between in-memory enum +values and the YAML string representation is only in one place. +This assures that the code for writing and parsing of YAML stays in sync. + +To specify a YAML mappings, you define a specialization on +llvm::yaml::MappingTraits. +If your native data structure happens to be a struct that is already normalized, +then the specialization is simple. For example: + +.. code-block:: c++ + + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + template <> + struct MappingTraits { + static void mapping(IO &io, Person &info) { + io.mapRequired("name", info.name); + io.mapOptional("hat-size", info.hatSize); + } + }; + + +A YAML sequence is automatically inferred if you data type has begin()/end() +iterators and a push_back() method. Therefore any of the STL containers +(such as std::vector<>) will automatically translate to YAML sequences. + +Once you have defined specializations for your data types, you can +programmatically use YAML I/O to write a YAML document: + +.. code-block:: c++ + + using llvm::yaml::Output; + + Person tom; + tom.name = "Tom"; + tom.hatSize = 8; + Person dan; + dan.name = "Dan"; + dan.hatSize = 7; + std::vector persons; + persons.push_back(tom); + persons.push_back(dan); + + Output yout(llvm::outs()); + yout << persons; + +This would write the following: + +.. code-block:: yaml + + - name: Tom + hat-size: 8 + - name: Dan + hat-size: 7 + +And you can also read such YAML documents with the following code: + +.. code-block:: c++ + + using llvm::yaml::Input; + + typedef std::vector PersonList; + std::vector docs; + + Input yin(document.getBuffer()); + yin >> docs; + + if ( yin.error() ) + return; + + // Process read document + for ( PersonList &pl : docs ) { + for ( Person &person : pl ) { + cout << "name=" << person.name; + } + } + +One other feature of YAML is the ability to define multiple documents in a +single file. That is why reading YAML produces a vector of your document type. + + + +Error Handling +============== + +When parsing a YAML document, if the input does not match your schema (as +expressed in your XxxTraits<> specializations). YAML I/O +will print out an error message and your Input object's error() method will +return true. For instance the following document: + +.. code-block:: yaml + + - name: Tom + shoe-size: 12 + - name: Dan + hat-size: 7 + +Has a key (shoe-size) that is not defined in the schema. YAML I/O will +automatically generate this error: + +.. code-block:: yaml + + YAML:2:2: error: unknown key 'shoe-size' + shoe-size: 12 + ^~~~~~~~~ + +Similar errors are produced for other input not conforming to the schema. + + +Scalars +======= + +YAML scalars are just strings (i.e. not a sequence or mapping). The YAML I/O +library provides support for translating between YAML scalars and specific +C++ types. + + +Built-in types +-------------- +The following types have built-in support in YAML I/O: + +* bool +* float +* double +* StringRef +* int64_t +* int32_t +* int16_t +* int8_t +* uint64_t +* uint32_t +* uint16_t +* uint8_t + +That is, you can use those types in fields of MappingTraits or as element type +in sequence. When reading, YAML I/O will validate that the string found +is convertible to that type and error out if not. + + +Unique types +------------ +Given that YAML I/O is trait based, the selection of how to convert your data +to YAML is based on the type of your data. But in C++ type matching, typedefs +do not generate unique type names. That means if you have two typedefs of +unsigned int, to YAML I/O both types look exactly like unsigned int. To +facilitate make unique type names, YAML I/O provides a macro which is used +like a typedef on built-in types, but expands to create a class with conversion +operators to and from the base type. For example: + +.. code-block:: c++ + + LLVM_YAML_STRONG_TYPEDEF(uint32_t, MyFooFlags) + LLVM_YAML_STRONG_TYPEDEF(uint32_t, MyBarFlags) + +This generates two classes MyFooFlags and MyBarFlags which you can use in your +native data structures instead of uint32_t. They are implicitly +converted to and from uint32_t. The point of creating these unique types +is that you can now specify traits on them to get different YAML conversions. + +Hex types +--------- +An example use of a unique type is that YAML I/O provides fixed sized unsigned +integers that are written with YAML I/O as hexadecimal instead of the decimal +format used by the built-in integer types: + +* Hex64 +* Hex32 +* Hex16 +* Hex8 + +You can use llvm::yaml::Hex32 instead of uint32_t and the only different will +be that when YAML I/O writes out that type it will be formatted in hexadecimal. + + +ScalarEnumerationTraits +----------------------- +YAML I/O supports translating between in-memory enumerations and a set of string +values in YAML documents. This is done by specializing ScalarEnumerationTraits<> +on your enumeration type and define a enumeration() method. +For instance, suppose you had an enumeration of CPUs and a struct with it as +a field: + +.. code-block:: c++ + + enum CPUs { + cpu_x86_64 = 5, + cpu_x86 = 7, + cpu_PowerPC = 8 + }; + + struct Info { + CPUs cpu; + uint32_t flags; + }; + +To support reading and writing of this enumeration, you can define a +ScalarEnumerationTraits specialization on CPUs, which can then be used +as a field type: + +.. code-block:: c++ + + using llvm::yaml::ScalarEnumerationTraits; + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + template <> + struct ScalarEnumerationTraits { + static void enumeration(IO &io, CPUs &value) { + io.enumCase(value, "x86_64", cpu_x86_64); + io.enumCase(value, "x86", cpu_x86); + io.enumCase(value, "PowerPC", cpu_PowerPC); + } + }; + + template <> + struct MappingTraits { + static void mapping(IO &io, Info &info) { + io.mapRequired("cpu", info.cpu); + io.mapOptional("flags", info.flags, 0); + } + }; + +When reading YAML, if the string found does not match any of the the strings +specified by enumCase() methods, an error is automatically generated. +When writing YAML, if the value being written does not match any of the values +specified by the enumCase() methods, a runtime assertion is triggered. + + +BitValue +-------- +Another common data structure in C++ is a field where each bit has a unique +meaning. This is often used in a "flags" field. YAML I/O has support for +converting such fields to a flow sequence. For instance suppose you +had the following bit flags defined: + +.. code-block:: c++ + + enum { + flagsPointy = 1 + flagsHollow = 2 + flagsFlat = 4 + flagsRound = 8 + }; + + LLVM_YAML_STRONG_TYPEDEF(uint32_t, MyFlags) + +To support reading and writing of MyFlags, you specialize ScalarBitSetTraits<> +on MyFlags and provide the bit values and their names. + +.. code-block:: c++ + + using llvm::yaml::ScalarBitSetTraits; + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + template <> + struct ScalarBitSetTraits { + static void bitset(IO &io, MyFlags &value) { + io.bitSetCase(value, "hollow", flagHollow); + io.bitSetCase(value, "flat", flagFlat); + io.bitSetCase(value, "round", flagRound); + io.bitSetCase(value, "pointy", flagPointy); + } + }; + + struct Info { + StringRef name; + MyFlags flags; + }; + + template <> + struct MappingTraits { + static void mapping(IO &io, Info& info) { + io.mapRequired("name", info.name); + io.mapRequired("flags", info.flags); + } + }; + +With the above, YAML I/O (when writing) will test mask each value in the +bitset trait against the flags field, and each that matches will +cause the corresponding string to be added to the flow sequence. The opposite +is done when reading and any unknown string values will result in a error. With +the above schema, a same valid YAML document is: + +.. code-block:: yaml + + name: Tom + flags: [ pointy, flat ] + + +Custom Scalar +------------- +Sometimes for readability a scalar needs to be formatted in a custom way. For +instance your internal data structure may use a integer for time (seconds since +some epoch), but in YAML it would be much nicer to express that integer in +some time format (e.g. 4-May-2012 10:30pm). YAML I/O has a way to support +custom formatting and parsing of scalar types by specializing ScalarTraits<> on +your data type. When writing, YAML I/O will provide the native type and +your specialization must create a temporary llvm::StringRef. When reading, +YAML I/O will provide an llvm::StringRef of scalar and your specialization +must convert that to your native data type. An outline of a custom scalar type +looks like: + +.. code-block:: c++ + + using llvm::yaml::ScalarTraits; + using llvm::yaml::IO; + + template <> + struct ScalarTraits { + static void output(const T &value, llvm::raw_ostream &out) { + out << value; // do custom formatting here + } + static StringRef input(StringRef scalar, T &value) { + // do custom parsing here. Return the empty string on success, + // or an error message on failure. + return StringRef(); + } + }; + + +Mappings +======== + +To be translated to or from a YAML mapping for your type T you must specialize +llvm::yaml::MappingTraits on T and implement the "void mapping(IO &io, T&)" +method. If your native data structures use pointers to a class everywhere, +you can specialize on the class pointer. Examples: + +.. code-block:: c++ + + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + // Example of struct Foo which is used by value + template <> + struct MappingTraits { + static void mapping(IO &io, Foo &foo) { + io.mapOptional("size", foo.size); + ... + } + }; + + // Example of struct Bar which is natively always a pointer + template <> + struct MappingTraits { + static void mapping(IO &io, Bar *&bar) { + io.mapOptional("size", bar->size); + ... + } + }; + + +No Normalization +---------------- + +The mapping() method is responsible, if needed, for normalizing and +denormalizing. In a simple case where the native data structure requires no +normalization, the mapping method just uses mapOptional() or mapRequired() to +bind the struct's fields to YAML key names. For example: + +.. code-block:: c++ + + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + template <> + struct MappingTraits { + static void mapping(IO &io, Person &info) { + io.mapRequired("name", info.name); + io.mapOptional("hat-size", info.hatSize); + } + }; + + +Normalization +---------------- + +When [de]normalization is required, the mapping() method needs a way to access +normalized values as fields. To help with this, there is +a template MappingNormalization<> which you can then use to automatically +do the normalization and denormalization. The template is used to create +a local variable in your mapping() method which contains the normalized keys. + +Suppose you have native data type +Polar which specifies a position in polar coordinates (distance, angle): + +.. code-block:: c++ + + struct Polar { + float distance; + float angle; + }; + +but you've decided the normalized YAML for should be in x,y coordinates. That +is, you want the yaml to look like: + +.. code-block:: yaml + + x: 10.3 + y: -4.7 + +You can support this by defining a MappingTraits that normalizes the polar +coordinates to x,y coordinates when writing YAML and denormalizes x,y +coordinates into polar when reading YAML. + +.. code-block:: c++ + + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + template <> + struct MappingTraits { + + class NormalizedPolar { + public: + NormalizedPolar(IO &io) + : x(0.0), y(0.0) { + } + NormalizedPolar(IO &, Polar &polar) + : x(polar.distance * cos(polar.angle)), + y(polar.distance * sin(polar.angle)) { + } + Polar denormalize(IO &) { + return Polar(sqrt(x*x+y*y), arctan(x,y)); + } + + float x; + float y; + }; + + static void mapping(IO &io, Polar &polar) { + MappingNormalization keys(io, polar); + + io.mapRequired("x", keys->x); + io.mapRequired("y", keys->y); + } + }; + +When writing YAML, the local variable "keys" will be a stack allocated +instance of NormalizedPolar, constructed from the supplied polar object which +initializes it x and y fields. The mapRequired() methods then write out the x +and y values as key/value pairs. + +When reading YAML, the local variable "keys" will be a stack allocated instance +of NormalizedPolar, constructed by the empty constructor. The mapRequired +methods will find the matching key in the YAML document and fill in the x and y +fields of the NormalizedPolar object keys. At the end of the mapping() method +when the local keys variable goes out of scope, the denormalize() method will +automatically be called to convert the read values back to polar coordinates, +and then assigned back to the second parameter to mapping(). + +In some cases, the normalized class may be a subclass of the native type and +could be returned by the denormalize() method, except that the temporary +normalized instance is stack allocated. In these cases, the utility template +MappingNormalizationHeap<> can be used instead. It just like +MappingNormalization<> except that it heap allocates the normalized object +when reading YAML. It never destroys the normalized object. The denormalize() +method can this return "this". + + +Default values +-------------- +Within a mapping() method, calls to io.mapRequired() mean that that key is +required to exist when parsing YAML documents, otherwise YAML I/O will issue an +error. + +On the other hand, keys registered with io.mapOptional() are allowed to not +exist in the YAML document being read. So what value is put in the field +for those optional keys? +There are two steps to how those optional fields are filled in. First, the +second parameter to the mapping() method is a reference to a native class. That +native class must have a default constructor. Whatever value the default +constructor initially sets for an optional field will be that field's value. +Second, the mapOptional() method has an optional third parameter. If provided +it is the value that mapOptional() should set that field to if the YAML document +does not have that key. + +There is one important difference between those two ways (default constructor +and third parameter to mapOptional). When YAML I/O generates a YAML document, +if the mapOptional() third parameter is used, if the actual value being written +is the same as (using ==) the default value, then that key/value is not written. + + +Order of Keys +-------------- + +When writing out a YAML document, the keys are written in the order that the +calls to mapRequired()/mapOptional() are made in the mapping() method. This +gives you a chance to write the fields in an order that a human reader of +the YAML document would find natural. This may be different that the order +of the fields in the native class. + +When reading in a YAML document, the keys in the document can be in any order, +but they are processed in the order that the calls to mapRequired()/mapOptional() +are made in the mapping() method. That enables some interesting +functionality. For instance, if the first field bound is the cpu and the second +field bound is flags, and the flags are cpu specific, you can programmatically +switch how the flags are converted to and from YAML based on the cpu. +This works for both reading and writing. For example: + +.. code-block:: c++ + + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + struct Info { + CPUs cpu; + uint32_t flags; + }; + + template <> + struct MappingTraits { + static void mapping(IO &io, Info &info) { + io.mapRequired("cpu", info.cpu); + // flags must come after cpu for this to work when reading yaml + if ( info.cpu == cpu_x86_64 ) + io.mapRequired("flags", *(My86_64Flags*)info.flags); + else + io.mapRequired("flags", *(My86Flags*)info.flags); + } + }; + + +Tags +---- + +The YAML syntax supports tags as a way to specify the type of a node before +it is parsed. This allows dynamic types of nodes. But the YAML I/O model uses +static typing, so there are limits to how you can use tags with the YAML I/O +model. Recently, we added support to YAML I/O for checking/setting the optional +tag on a map. Using this functionality it is even possbile to support differnt +mappings, as long as they are convertable. + +To check a tag, inside your mapping() method you can use io.mapTag() to specify +what the tag should be. This will also add that tag when writing yaml. + + +Sequence +======== + +To be translated to or from a YAML sequence for your type T you must specialize +llvm::yaml::SequenceTraits on T and implement two methods: +``size_t size(IO &io, T&)`` and +``T::value_type& element(IO &io, T&, size_t indx)``. For example: + +.. code-block:: c++ + + template <> + struct SequenceTraits { + static size_t size(IO &io, MySeq &list) { ... } + static MySeqEl &element(IO &io, MySeq &list, size_t index) { ... } + }; + +The size() method returns how many elements are currently in your sequence. +The element() method returns a reference to the i'th element in the sequence. +When parsing YAML, the element() method may be called with an index one bigger +than the current size. Your element() method should allocate space for one +more element (using default constructor if element is a C++ object) and returns +a reference to that new allocated space. + + +Flow Sequence +------------- +A YAML "flow sequence" is a sequence that when written to YAML it uses the +inline notation (e.g [ foo, bar ] ). To specify that a sequence type should +be written in YAML as a flow sequence, your SequenceTraits specialization should +add "static const bool flow = true;". For instance: + +.. code-block:: c++ + + template <> + struct SequenceTraits { + static size_t size(IO &io, MyList &list) { ... } + static MyListEl &element(IO &io, MyList &list, size_t index) { ... } + + // The existence of this member causes YAML I/O to use a flow sequence + static const bool flow = true; + }; + +With the above, if you used MyList as the data type in your native data +structures, then then when converted to YAML, a flow sequence of integers +will be used (e.g. [ 10, -3, 4 ]). + + +Utility Macros +-------------- +Since a common source of sequences is std::vector<>, YAML I/O provides macros: +LLVM_YAML_IS_SEQUENCE_VECTOR() and LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR() which +can be used to easily specify SequenceTraits<> on a std::vector type. YAML +I/O does not partial specialize SequenceTraits on std::vector<> because that +would force all vectors to be sequences. An example use of the macros: + +.. code-block:: c++ + + std::vector; + std::vector; + LLVM_YAML_IS_SEQUENCE_VECTOR(MyType1) + LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyType2) + + + +Document List +============= + +YAML allows you to define multiple "documents" in a single YAML file. Each +new document starts with a left aligned "---" token. The end of all documents +is denoted with a left aligned "..." token. Many users of YAML will never +have need for multiple documents. The top level node in their YAML schema +will be a mapping or sequence. For those cases, the following is not needed. +But for cases where you do want multiple documents, you can specify a +trait for you document list type. The trait has the same methods as +SequenceTraits but is named DocumentListTraits. For example: + +.. code-block:: c++ + + template <> + struct DocumentListTraits { + static size_t size(IO &io, MyDocList &list) { ... } + static MyDocType element(IO &io, MyDocList &list, size_t index) { ... } + }; + + +User Context Data +================= +When an llvm::yaml::Input or llvm::yaml::Output object is created their +constructors take an optional "context" parameter. This is a pointer to +whatever state information you might need. + +For instance, in a previous example we showed how the conversion type for a +flags field could be determined at runtime based on the value of another field +in the mapping. But what if an inner mapping needs to know some field value +of an outer mapping? That is where the "context" parameter comes in. You +can set values in the context in the outer map's mapping() method and +retrieve those values in the inner map's mapping() method. + +The context value is just a void*. All your traits which use the context +and operate on your native data types, need to agree what the context value +actually is. It could be a pointer to an object or struct which your various +traits use to shared context sensitive information. + + +Output +====== + +The llvm::yaml::Output class is used to generate a YAML document from your +in-memory data structures, using traits defined on your data types. +To instantiate an Output object you need an llvm::raw_ostream, and optionally +a context pointer: + +.. code-block:: c++ + + class Output : public IO { + public: + Output(llvm::raw_ostream &, void *context=NULL); + +Once you have an Output object, you can use the C++ stream operator on it +to write your native data as YAML. One thing to recall is that a YAML file +can contain multiple "documents". If the top level data structure you are +streaming as YAML is a mapping, scalar, or sequence, then Output assumes you +are generating one document and wraps the mapping output +with "``---``" and trailing "``...``". + +.. code-block:: c++ + + using llvm::yaml::Output; + + void dumpMyMapDoc(const MyMapType &info) { + Output yout(llvm::outs()); + yout << info; + } + +The above could produce output like: + +.. code-block:: yaml + + --- + name: Tom + hat-size: 7 + ... + +On the other hand, if the top level data structure you are streaming as YAML +has a DocumentListTraits specialization, then Output walks through each element +of your DocumentList and generates a "---" before the start of each element +and ends with a "...". + +.. code-block:: c++ + + using llvm::yaml::Output; + + void dumpMyMapDoc(const MyDocListType &docList) { + Output yout(llvm::outs()); + yout << docList; + } + +The above could produce output like: + +.. code-block:: yaml + + --- + name: Tom + hat-size: 7 + --- + name: Tom + shoe-size: 11 + ... + +Input +===== + +The llvm::yaml::Input class is used to parse YAML document(s) into your native +data structures. To instantiate an Input +object you need a StringRef to the entire YAML file, and optionally a context +pointer: + +.. code-block:: c++ + + class Input : public IO { + public: + Input(StringRef inputContent, void *context=NULL); + +Once you have an Input object, you can use the C++ stream operator to read +the document(s). If you expect there might be multiple YAML documents in +one file, you'll need to specialize DocumentListTraits on a list of your +document type and stream in that document list type. Otherwise you can +just stream in the document type. Also, you can check if there was +any syntax errors in the YAML be calling the error() method on the Input +object. For example: + +.. code-block:: c++ + + // Reading a single document + using llvm::yaml::Input; + + Input yin(mb.getBuffer()); + + // Parse the YAML file + MyDocType theDoc; + yin >> theDoc; + + // Check for error + if ( yin.error() ) + return; + + +.. code-block:: c++ + + // Reading multiple documents in one file + using llvm::yaml::Input; + + LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(std::vector) + + Input yin(mb.getBuffer()); + + // Parse the YAML file + std::vector theDocList; + yin >> theDocList; + + // Check for error + if ( yin.error() ) + return; + + diff --git a/docs/_static/lines.gif b/docs/_static/lines.gif new file mode 100644 index 00000000..88f491ed Binary files /dev/null and b/docs/_static/lines.gif differ diff --git a/docs/_static/llvm.css b/docs/_static/llvm.css new file mode 100644 index 00000000..d7b5dae5 --- /dev/null +++ b/docs/_static/llvm.css @@ -0,0 +1,112 @@ +/* + * LLVM documentation style sheet + */ + +/* Common styles */ +.body { color: black; background: white; margin: 0 0 0 0 } + +/* No borders on image links */ +a:link img, a:visited img { border-style: none } + +address img { float: right; width: 88px; height: 31px; } +address { clear: right; } + +table { text-align: center; border: 2px solid black; + border-collapse: collapse; margin-top: 1em; margin-left: 1em; + margin-right: 1em; margin-bottom: 1em; } +tr, td { border: 2px solid gray; padding: 4pt 4pt 2pt 2pt; } +th { border: 2px solid gray; font-weight: bold; font-size: 105%; + background: url("lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; + text-align: center; vertical-align: middle; } +/* + * Documentation + */ +/* Common for title and header */ +.doc_title, .doc_section, .doc_subsection, h1, h2, h3 { + color: black; background: url("lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; + padding-left: 8pt; + padding-top: 1px; + padding-bottom: 2px +} + +h1, .doc_title, .title { text-align: left; font-size: 25pt } + +h2, .doc_section { text-align: center; font-size: 22pt; + margin: 20pt 0pt 5pt 0pt; } + +h3, .doc_subsection { width: 75%; + text-align: left; font-size: 12pt; + padding: 4pt 4pt 4pt 4pt; + margin: 1.5em 0.5em 0.5em 0.5em } + +h4, .doc_subsubsection { margin: 2.0em 0.5em 0.5em 0.5em; + font-weight: bold; font-style: oblique; + border-bottom: 1px solid #999999; font-size: 12pt; + width: 75%; } + +.doc_author { text-align: left; font-weight: bold; padding-left: 20pt } +.doc_text { text-align: left; padding-left: 20pt; padding-right: 10pt } + +.doc_footer { text-align: left; padding: 0 0 0 0 } + +.doc_hilite { color: blue; font-weight: bold; } + +.doc_table { text-align: center; width: 90%; + padding: 1px 1px 1px 1px; border: 1px; } + +.doc_warning { color: red; font-weight: bold } + +/*
would use this class, and
adds more padding */ +.doc_code, .literal-block + { border: solid 1px gray; background: #eeeeee; + margin: 0 1em 0 1em; + padding: 0 1em 0 1em; + display: table; + } + +blockquote pre { + padding: 1em 2em 1em 1em; + border: solid 1px gray; + background: #eeeeee; + margin: 0 1em 0 1em; + display: table; +} + +h2+div, h2+p {text-align: left; padding-left: 20pt; padding-right: 10pt;} +h3+div, h3+p {text-align: left; padding-left: 20pt; padding-right: 10pt;} +h4+div, h4+p {text-align: left; padding-left: 20pt; padding-right: 10pt;} + +/* It is preferrable to use
 everywhere instead of the
+ * 
...
construct. + * + * Once all docs use
 for code regions, this style can  be merged with the
+ * one above, and we can drop the [pre] qualifier.
+ */
+pre.doc_code, .literal-block { padding: 1em 2em 1em 1em }
+
+.doc_notes      { background: #fafafa; border: 1px solid #cecece;
+                  display: table; padding: 0 1em 0 .1em }
+
+table.layout    { text-align: left; border: none; border-collapse: collapse;
+                  padding: 4px 4px 4px 4px; }
+tr.layout, td.layout, td.left, td.right
+                { border: none; padding: 4pt 4pt 2pt 2pt; vertical-align: top; }
+td.left         { text-align: left }
+td.right        { text-align: right }
+th.layout       { border: none; font-weight: bold; font-size: 105%;
+                  text-align: center; vertical-align: middle; }
+
+/* Left align table cell */
+.td_left        { border: 2px solid gray; text-align: left; }
+
+/* ReST-specific */
+.title { margin-top: 0 }
+.topic-title{ display: none }
+div.contents ul { list-style-type: decimal }
+.toc-backref    { color: black; text-decoration: none; }
diff --git a/docs/_templates/indexsidebar.html b/docs/_templates/indexsidebar.html
new file mode 100644
index 00000000..41617427
--- /dev/null
+++ b/docs/_templates/indexsidebar.html
@@ -0,0 +1,7 @@
+{# This template defines sidebar which can be used to provide common links on
+   all documentation pages. #}
+
+

Bugs

+ +

LLVM bugs should be reported to + Bugzilla.

diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 00000000..de5db5ca --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,13 @@ +{% extends "!layout.html" %} + +{% block extrahead %} + +{% endblock %} + +{% block rootrellink %} +
  • LLVM Home | 
  • +
  • Documentation»
  • +{% endblock %} diff --git a/docs/_themes/llvm-theme/layout.html b/docs/_themes/llvm-theme/layout.html new file mode 100644 index 00000000..746c2f56 --- /dev/null +++ b/docs/_themes/llvm-theme/layout.html @@ -0,0 +1,23 @@ +{# + sphinxdoc/layout.html + ~~~~~~~~~~~~~~~~~~~~~ + + Sphinx layout template for the sphinxdoc theme. + + :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{% extends "basic/layout.html" %} + +{% block relbar1 %} + +{{ super() }} +{% endblock %} + +{# put the sidebar before the body #} +{% block sidebar1 %}{{ sidebar() }}{% endblock %} +{% block sidebar2 %}{% endblock %} diff --git a/docs/_themes/llvm-theme/static/contents.png b/docs/_themes/llvm-theme/static/contents.png new file mode 100644 index 00000000..7fb82154 Binary files /dev/null and b/docs/_themes/llvm-theme/static/contents.png differ diff --git a/docs/_themes/llvm-theme/static/llvm-theme.css b/docs/_themes/llvm-theme/static/llvm-theme.css new file mode 100644 index 00000000..beab2ca2 --- /dev/null +++ b/docs/_themes/llvm-theme/static/llvm-theme.css @@ -0,0 +1,371 @@ +/* + * sphinxdoc.css_t + * ~~~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- sphinxdoc theme. Originally created by + * Armin Ronacher for Werkzeug. + * + * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', + 'Verdana', sans-serif; + font-size: 14px; + line-height: 150%; + text-align: center; + background-color: #BFD1D4; + color: black; + padding: 0; + border: 1px solid #aaa; + + margin: 0px 80px 0px 80px; + min-width: 740px; +} + +div.logo { + background-color: white; + text-align: left; + padding: 10px 10px 15px 15px; +} + +div.document { + background-color: white; + text-align: left; + background-image: url(contents.png); + background-repeat: repeat-x; +} + +div.bodywrapper { + margin: 0 240px 0 0; + border-right: 1px solid #ccc; +} + +div.body { + margin: 0; + padding: 0.5em 20px 20px 20px; +} + +div.related { + font-size: 1em; +} + +div.related ul { + background-image: url(navigation.png); + height: 2em; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} + +div.related ul li { + margin: 0; + padding: 0; + height: 2em; + float: left; +} + +div.related ul li.right { + float: right; + margin-right: 5px; +} + +div.related ul li a { + margin: 0; + padding: 0 5px 0 5px; + line-height: 1.75em; + color: #EE9816; +} + +div.related ul li a:hover { + color: #3CA8E7; +} + +div.sphinxsidebarwrapper { + padding: 0; +} + +div.sphinxsidebar { + margin: 0; + padding: 0.5em 15px 15px 0; + width: 210px; + float: right; + font-size: 1em; + text-align: left; +} + +div.sphinxsidebar h3, div.sphinxsidebar h4 { + margin: 1em 0 0.5em 0; + font-size: 1em; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border: 1px solid #86989B; + background-color: #AFC1C4; +} + +div.sphinxsidebar h3 a { + color: white; +} + +div.sphinxsidebar ul { + padding-left: 1.5em; + margin-top: 7px; + padding: 0; + line-height: 130%; +} + +div.sphinxsidebar ul ul { + margin-left: 20px; +} + +div.footer { + background-color: #E3EFF1; + color: #86989B; + padding: 3px 8px 3px 0; + clear: both; + font-size: 0.8em; + text-align: right; +} + +div.footer a { + color: #86989B; + text-decoration: underline; +} + +/* -- body styles ----------------------------------------------------------- */ + +p { + margin: 0.8em 0 0.5em 0; +} + +a { + color: #CA7900; + text-decoration: none; +} + +a:hover { + color: #2491CF; +} + +div.body p a{ + text-decoration: underline; +} + +h1 { + margin: 0; + padding: 0.7em 0 0.3em 0; + font-size: 1.5em; + color: #11557C; +} + +h2 { + margin: 1.3em 0 0.2em 0; + font-size: 1.35em; + padding: 0; +} + +h3 { + margin: 1em 0 -0.3em 0; + font-size: 1.2em; +} + +h3 a:hover { + text-decoration: underline; +} + +div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a { + color: black!important; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + background-color: #f2f2f2; + font-weight: normal; + color: #20435c; + border-bottom: 1px solid #ccc; + margin: 20px -20px 10px -20px; + padding: 3px 0 3px 10px; +} + +div.body h1 { margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 160%; } +div.body h3 { font-size: 140%; } +div.body h4 { font-size: 120%; } +div.body h5 { font-size: 110%; } +div.body h6 { font-size: 100%; } + +h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { + display: none; + margin: 0 0 0 0.3em; + padding: 0 0.2em 0 0.2em; + color: #aaa!important; +} + +h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, +h5:hover a.anchor, h6:hover a.anchor { + display: inline; +} + +h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, +h5 a.anchor:hover, h6 a.anchor:hover { + color: #777; + background-color: #eee; +} + +a.headerlink { + color: #c60f0f!important; + font-size: 1em; + margin-left: 6px; + padding: 0 4px 0 4px; + text-decoration: none!important; +} + +a.headerlink:hover { + background-color: #ccc; + color: white!important; +} + +cite, code, tt { + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; +} + +:not(a.reference) > tt { + background-color: #f2f2f2; + border-bottom: 1px solid #ddd; + color: #333; +} + +tt.descname, tt.descclassname, tt.xref { + border: 0; +} + +hr { + border: 1px solid #abc; + margin: 2em; +} + +p a tt { + border: 0; + color: #CA7900; +} + +p a tt:hover { + color: #2491CF; +} + +a tt { + border: none; +} + +pre { + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; + line-height: 120%; + padding: 0.5em; + border: 1px solid #ccc; + background-color: #f8f8f8; +} + +pre a { + color: inherit; + text-decoration: underline; +} + +td.linenos pre { + padding: 0.5em 0; +} + +div.quotebar { + background-color: #f8f8f8; + max-width: 250px; + float: right; + padding: 2px 7px; + border: 1px solid #ccc; +} + +div.topic { + background-color: #f8f8f8; +} + +table { + border-collapse: collapse; + margin: 0 -0.5em 0 -0.5em; +} + +table td, table th { + padding: 0.2em 0.5em 0.2em 0.5em; +} + +div.admonition, div.warning { + font-size: 0.9em; + margin: 1em 0 1em 0; + border: 1px solid #86989B; + background-color: #f7f7f7; + padding: 0; +} + +div.admonition p, div.warning p { + margin: 0.5em 1em 0.5em 1em; + padding: 0; +} + +div.admonition pre, div.warning pre { + margin: 0.4em 1em 0.4em 1em; +} + +div.admonition p.admonition-title, +div.warning p.admonition-title { + margin: 0; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border-bottom: 1px solid #86989B; + font-weight: bold; + background-color: #AFC1C4; +} + +div.warning { + border: 1px solid #940000; +} + +div.warning p.admonition-title { + background-color: #CF0000; + border-bottom-color: #940000; +} + +div.admonition ul, div.admonition ol, +div.warning ul, div.warning ol { + margin: 0.1em 0.5em 0.5em 3em; + padding: 0; +} + +div.versioninfo { + margin: 1em 0 0 0; + border: 1px solid #ccc; + background-color: #DDEAF0; + padding: 8px; + line-height: 1.3em; + font-size: 0.9em; +} + +.viewcode-back { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', + 'Verdana', sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} diff --git a/docs/_themes/llvm-theme/static/logo.png b/docs/_themes/llvm-theme/static/logo.png new file mode 100644 index 00000000..18d424c5 Binary files /dev/null and b/docs/_themes/llvm-theme/static/logo.png differ diff --git a/docs/_themes/llvm-theme/static/navigation.png b/docs/_themes/llvm-theme/static/navigation.png new file mode 100644 index 00000000..1081dc14 Binary files /dev/null and b/docs/_themes/llvm-theme/static/navigation.png differ diff --git a/docs/_themes/llvm-theme/theme.conf b/docs/_themes/llvm-theme/theme.conf new file mode 100644 index 00000000..573fd78a --- /dev/null +++ b/docs/_themes/llvm-theme/theme.conf @@ -0,0 +1,4 @@ +[theme] +inherit = basic +stylesheet = llvm-theme.css +pygments_style = friendly diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..d71f46e9 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,252 @@ +# -*- coding: utf-8 -*- +# +# LLVM documentation build configuration file. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'LLVM' +copyright = u'2003-2013, LLVM Project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '3.4' +# The full version, including alpha/beta/rc tags. +release = '3.4' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%Y-%m-%d' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +show_authors = True + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'friendly' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'llvm-theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { "nosidebar": True } + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ["_themes"] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%Y-%m-%d' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +html_sidebars = {'index': 'indexsidebar.html'} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'LLVMdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'LLVM.tex', u'LLVM Documentation', + u'LLVM project', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [] + +# Automatically derive the list of man pages from the contents of the command +# guide subdirectory. +basedir = os.path.dirname(__file__) +man_page_authors = "Maintained by The LLVM Team (http://llvm.org/)." +command_guide_subpath = 'CommandGuide' +command_guide_path = os.path.join(basedir, command_guide_subpath) +for name in os.listdir(command_guide_path): + # Ignore non-ReST files and the index page. + if not name.endswith('.rst') or name in ('index.rst',): + continue + + # Otherwise, automatically extract the description. + file_subpath = os.path.join(command_guide_subpath, name) + with open(os.path.join(command_guide_path, name)) as f: + title = f.readline().rstrip('\n') + header = f.readline().rstrip('\n') + + if len(header) != len(title): + print >>sys.stderr, ( + "error: invalid header in %r (does not match title)" % ( + file_subpath,)) + if ' - ' not in title: + print >>sys.stderr, ( + ("error: invalid title in %r " + "(expected ' - ')") % ( + file_subpath,)) + + # Split the name out of the title. + name,description = title.split(' - ', 1) + man_pages.append((file_subpath.replace('.rst',''), name, + description, man_page_authors, 1)) + +# If true, show URL addresses after external links. +#man_show_urls = False + +# FIXME: Define intersphinx configration. +intersphinx_mapping = {} diff --git a/docs/doxygen.cfg.in b/docs/doxygen.cfg.in new file mode 100644 index 00000000..0ed686b9 --- /dev/null +++ b/docs/doxygen.cfg.in @@ -0,0 +1,1641 @@ + +# Doxyfile 1.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = LLVM + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @abs_top_builddir@/docs/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = ../.. + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @abs_top_srcdir@/include \ + @abs_top_srcdir@/lib \ + @abs_top_srcdir@/docs/doxygen.intro + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = @abs_top_srcdir@/examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = YES + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = @abs_top_srcdir@/docs/img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 4 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = llvm:: + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = @abs_top_srcdir@/docs/doxygen.header + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = @abs_top_srcdir@/docs/doxygen.css + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = @enable_searchengine@ + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = @enable_server_based_search@ + +SEARCHENGINE_URL = @searchengine_url@ + +EXTERNAL_SEARCH = @enable_external_search@ + +EXTERNAL_SEARCH_ID = llvm + +EXTRA_SEARCH_MAPPINGS = @extra_search_mappings@ + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../include + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = YES + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = NO + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = @DOT@ + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/docs/doxygen.css b/docs/doxygen.css new file mode 100644 index 00000000..83951f67 --- /dev/null +++ b/docs/doxygen.css @@ -0,0 +1,408 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 140%; + font-weight: bold; +} +H2 { + font-size: 120%; + font-style: italic; +} +H3 { + font-size: 100%; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: Fixed, monospace; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdPrefix { + background-color: #F4F4FB; + color: #606060; + font-size: 80%; +} +TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +.mdRow { + padding: 8px 10px; +} +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #eeeeff; +} +TD.tiny { font-size: 75%; +} +a { + color: #252E78; +} +a:visited { + color: #3D2185; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #b0b0b0; +} +TH.dirtab { background: #eeeeff; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; +} + +/* + * LLVM Modifications. + * Note: Everything above here is generated with "doxygen -w htlm" command. See + * "doxygen --help" for details. What follows are CSS overrides for LLVM + * specific formatting. We want to keep the above so it can be replaced with + * subsequent doxygen upgrades. + */ + +.footer { + font-size: 80%; + font-weight: bold; + text-align: center; + vertical-align: middle; +} +.title { + font-size: 25pt; + color: black; + font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; + padding-left: 8pt; + padding-top: 1px; + padding-bottom: 2px +} +A:link { + cursor: pointer; + text-decoration: none; + font-weight: bolder; +} +A:visited { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; +} +A:hover { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; +} +A:active { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; + font-style: italic; +} +H1 { + text-align: center; + font-size: 140%; + font-weight: bold; +} +H2 { + font-size: 120%; + font-style: italic; +} +H3 { + font-size: 100%; +} + +H2, H3 { + border-bottom: 2px solid; + margin-top: 2em; +} + +A.qindex {} +A.qindexRef {} +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal; color: #4444ee } +A.codeRef { font-weight: normal; color: #4444ee } + +div.memitem { + border: 1px solid #999999; + margin-top: 1.0em; + margin-bottom: 1.0em; + -webkit-border-radius: 0.5em; + -webkit-box-shadow: 3px 3px 6px #777777; + -moz-border-radius: 0.5em; + -moz-box-shadow: black 3px 3px 3px; +} + +div.memproto { + background-color: #E3E4E5; + padding: 0.25em 0.5em; + -webkit-border-top-left-radius: 0.5em; + -webkit-border-top-right-radius: 0.5em; + -moz-border-radius-topleft: 0.5em; + -moz-border-radius-topright: 0.5em; +} + +div.memdoc { + padding-left: 1em; + padding-right: 1em; +} diff --git a/docs/doxygen.footer b/docs/doxygen.footer new file mode 100644 index 00000000..95d5434f --- /dev/null +++ b/docs/doxygen.footer @@ -0,0 +1,13 @@ +
    + + +
    + + + + diff --git a/docs/doxygen.header b/docs/doxygen.header new file mode 100644 index 00000000..56fb77fa --- /dev/null +++ b/docs/doxygen.header @@ -0,0 +1,9 @@ + + + + + +LLVM: $title + + +

    LLVM API Documentation

    diff --git a/docs/doxygen.intro b/docs/doxygen.intro new file mode 100644 index 00000000..699dadc2 --- /dev/null +++ b/docs/doxygen.intro @@ -0,0 +1,18 @@ +/// @mainpage LLVM +/// +/// @section main_intro Introduction +/// Welcome to LLVM. +/// +/// This documentation describes the @b internal software that makes +/// up LLVM, not the @b external use of LLVM. There are no instructions +/// here on how to use LLVM, only the APIs that make up the software. For usage +/// instructions, please see the programmer's guide or reference manual. +/// +/// @section main_caveat Caveat +/// This documentation is generated directly from the source code with doxygen. +/// Since LLVM is constantly under active development, what you're about to +/// read is out of date! However, it may still be useful since certain portions +/// of LLVM are very stable. +/// +/// @section main_changelog Change Log +/// - Original content written 12/30/2003 by Reid Spencer diff --git a/docs/gcc-loops.png b/docs/gcc-loops.png new file mode 100644 index 00000000..8923a311 Binary files /dev/null and b/docs/gcc-loops.png differ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..62766f10 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,426 @@ +Overview +======== + +.. warning:: + + If you are using a released version of LLVM, see `the download page + `_ to find your documentation. + +The LLVM compiler infrastructure supports a wide range of projects, from +industrial strength compilers to specialized JIT applications to small +research projects. + +Similarly, documentation is broken down into several high-level groupings +targeted at different audiences: + +LLVM Design & Overview +====================== + +Several introductory papers and presentations. + +.. toctree:: + :hidden: + + LangRef + +:doc:`LangRef` + Defines the LLVM intermediate representation. + +`Introduction to the LLVM Compiler`__ + Presentation providing a users introduction to LLVM. + + .. __: http://llvm.org/pubs/2008-10-04-ACAT-LLVM-Intro.html + +`Intro to LLVM`__ + Book chapter providing a compiler hacker's introduction to LLVM. + + .. __: http://www.aosabook.org/en/llvm.html + + +`LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation`__ + Design overview. + + .. __: http://llvm.org/pubs/2004-01-30-CGO-LLVM.html + +`LLVM: An Infrastructure for Multi-Stage Optimization`__ + More details (quite old now). + + .. __: http://llvm.org/pubs/2002-12-LattnerMSThesis.html + +`Publications mentioning LLVM `_ + .. + +User Guides +=========== + +For those new to the LLVM system. + +NOTE: If you are a user who is only interested in using LLVM-based +compilers, you should look into `Clang `_ or +`DragonEgg `_ instead. The documentation here is +intended for users who have a need to work with the intermediate LLVM +representation. + +.. toctree:: + :hidden: + + CMake + HowToBuildOnARM + HowToCrossCompileLLVM + CommandGuide/index + GettingStarted + GettingStartedVS + FAQ + Lexicon + HowToAddABuilder + yaml2obj + HowToSubmitABug + SphinxQuickstartTemplate + Phabricator + TestingGuide + tutorial/index + ReleaseNotes + Passes + YamlIO + GetElementPtr + MCJITDesignAndImplementation + +:doc:`GettingStarted` + Discusses how to get up and running quickly with the LLVM infrastructure. + Everything from unpacking and compilation of the distribution to execution + of some tools. + +:doc:`CMake` + An addendum to the main Getting Started guide for those using the `CMake + build system `_. + +:doc:`HowToBuildOnARM` + Notes on building and testing LLVM/Clang on ARM. + +:doc:`HowToCrossCompileLLVM` + Notes on cross-building and testing LLVM/Clang. + +:doc:`GettingStartedVS` + An addendum to the main Getting Started guide for those using Visual Studio + on Windows. + +:doc:`tutorial/index` + Tutorials about using LLVM. Includes a tutorial about making a custom + language with LLVM. + +:doc:`LLVM Command Guide ` + A reference manual for the LLVM command line utilities ("man" pages for LLVM + tools). + +:doc:`Passes` + A list of optimizations and analyses implemented in LLVM. + +:doc:`FAQ` + A list of common questions and problems and their solutions. + +:doc:`Release notes for the current release ` + This describes new features, known bugs, and other limitations. + +:doc:`HowToSubmitABug` + Instructions for properly submitting information about any bugs you run into + in the LLVM system. + +:doc:`SphinxQuickstartTemplate` + A template + tutorial for writing new Sphinx documentation. It is meant + to be read in source form. + +:doc:`LLVM Testing Infrastructure Guide ` + A reference manual for using the LLVM testing infrastructure. + +`How to build the C, C++, ObjC, and ObjC++ front end`__ + Instructions for building the clang front-end from source. + + .. __: http://clang.llvm.org/get_started.html + +:doc:`Lexicon` + Definition of acronyms, terms and concepts used in LLVM. + +:doc:`HowToAddABuilder` + Instructions for adding new builder to LLVM buildbot master. + +:doc:`YamlIO` + A reference guide for using LLVM's YAML I/O library. + +:doc:`GetElementPtr` + Answers to some very frequent questions about LLVM's most frequently + misunderstood instruction. + +Programming Documentation +========================= + +For developers of applications which use LLVM as a library. + +.. toctree:: + :hidden: + + Atomics + CodingStandards + CommandLine + CompilerWriterInfo + ExtendingLLVM + HowToSetUpLLVMStyleRTTI + ProgrammersManual + Extensions + +:doc:`LLVM Language Reference Manual ` + Defines the LLVM intermediate representation and the assembly form of the + different nodes. + +:doc:`Atomics` + Information about LLVM's concurrency model. + +:doc:`ProgrammersManual` + Introduction to the general layout of the LLVM sourcebase, important classes + and APIs, and some tips & tricks. + +:doc:`Extensions` + LLVM-specific extensions to tools and formats LLVM seeks compatibility with. + +:doc:`CommandLine` + Provides information on using the command line parsing library. + +:doc:`CodingStandards` + Details the LLVM coding standards and provides useful information on writing + efficient C++ code. + +:doc:`HowToSetUpLLVMStyleRTTI` + How to make ``isa<>``, ``dyn_cast<>``, etc. available for clients of your + class hierarchy. + +:doc:`ExtendingLLVM` + Look here to see how to add instructions and intrinsics to LLVM. + +`Doxygen generated documentation `_ + (`classes `_) + (`tarball `_) + +`ViewVC Repository Browser `_ + .. + +:doc:`CompilerWriterInfo` + A list of helpful links for compiler writers. + +Subsystem Documentation +======================= + +For API clients and LLVM developers. + +.. toctree:: + :hidden: + + AliasAnalysis + BitCodeFormat + BranchWeightMetadata + Bugpoint + CodeGenerator + ExceptionHandling + LinkTimeOptimization + SegmentedStacks + TableGenFundamentals + DebuggingJITedCode + GoldPlugin + MarkedUpDisassembly + SystemLibrary + SourceLevelDebugging + Vectorizers + WritingAnLLVMBackend + GarbageCollection + WritingAnLLVMPass + TableGen/LangRef + HowToUseAttributes + NVPTXUsage + +:doc:`WritingAnLLVMPass` + Information on how to write LLVM transformations and analyses. + +:doc:`WritingAnLLVMBackend` + Information on how to write LLVM backends for machine targets. + +:doc:`CodeGenerator` + The design and implementation of the LLVM code generator. Useful if you are + working on retargetting LLVM to a new architecture, designing a new codegen + pass, or enhancing existing components. + +:doc:`TableGenFundamentals` + Describes the TableGen tool, which is used heavily by the LLVM code + generator. + +:doc:`AliasAnalysis` + Information on how to write a new alias analysis implementation or how to + use existing analyses. + +:doc:`GarbageCollection` + The interfaces source-language compilers should use for compiling GC'd + programs. + +:doc:`Source Level Debugging with LLVM ` + This document describes the design and philosophy behind the LLVM + source-level debugger. + +:doc:`Vectorizers` + This document describes the current status of vectorization in LLVM. + +:doc:`ExceptionHandling` + This document describes the design and implementation of exception handling + in LLVM. + +:doc:`Bugpoint` + Automatic bug finder and test-case reducer description and usage + information. + +:doc:`BitCodeFormat` + This describes the file format and encoding used for LLVM "bc" files. + +:doc:`System Library ` + This document describes the LLVM System Library (``lib/System``) and + how to keep LLVM source code portable + +:doc:`LinkTimeOptimization` + This document describes the interface between LLVM intermodular optimizer + and the linker and its design + +:doc:`GoldPlugin` + How to build your programs with link-time optimization on Linux. + +:doc:`DebuggingJITedCode` + How to debug JITed code with GDB. + +:doc:`MCJITDesignAndImplementation` + Describes the inner workings of MCJIT execution engine. + +:doc:`BranchWeightMetadata` + Provides information about Branch Prediction Information. + +:doc:`SegmentedStacks` + This document describes segmented stacks and how they are used in LLVM. + +:doc:`MarkedUpDisassembly` + This document describes the optional rich disassembly output syntax. + +:doc:`HowToUseAttributes` + Answers some questions about the new Attributes infrastructure. + +:doc:`NVPTXUsage` + This document describes using the NVPTX back-end to compile GPU kernels. + + +Development Process Documentation +================================= + +Information about LLVM's development process. + +.. toctree:: + :hidden: + + DeveloperPolicy + MakefileGuide + Projects + LLVMBuild + HowToReleaseLLVM + Packaging + ReleaseProcess + +:doc:`DeveloperPolicy` + The LLVM project's policy towards developers and their contributions. + +:doc:`Projects` + How-to guide and templates for new projects that *use* the LLVM + infrastructure. The templates (directory organization, Makefiles, and test + tree) allow the project code to be located outside (or inside) the ``llvm/`` + tree, while using LLVM header files and libraries. + +:doc:`LLVMBuild` + Describes the LLVMBuild organization and files used by LLVM to specify + component descriptions. + +:doc:`MakefileGuide` + Describes how the LLVM makefiles work and how to use them. + +:doc:`HowToReleaseLLVM` + This is a guide to preparing LLVM releases. Most developers can ignore it. + +:doc:`ReleaseProcess` + This is a validate a new release, during the release process. Most developers can ignore it. + +:doc:`Packaging` + Advice on packaging LLVM into a distribution. + +Community +========= + +LLVM has a thriving community of friendly and helpful developers. +The two primary communication mechanisms in the LLVM community are mailing +lists and IRC. + +Mailing Lists +------------- + +If you can't find what you need in these docs, try consulting the mailing +lists. + +`Developer's List (llvmdev)`__ + This list is for people who want to be included in technical discussions of + LLVM. People post to this list when they have questions about writing code + for or using the LLVM tools. It is relatively low volume. + + .. __: http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev + +`Commits Archive (llvm-commits)`__ + This list contains all commit messages that are made when LLVM developers + commit code changes to the repository. It also serves as a forum for + patch review (i.e. send patches here). It is useful for those who want to + stay on the bleeding edge of LLVM development. This list is very high + volume. + + .. __: http://lists.cs.uiuc.edu/pipermail/llvm-commits/ + +`Bugs & Patches Archive (llvmbugs)`__ + This list gets emailed every time a bug is opened and closed. It is + higher volume than the LLVMdev list. + + .. __: http://lists.cs.uiuc.edu/pipermail/llvmbugs/ + +`Test Results Archive (llvm-testresults)`__ + A message is automatically sent to this list by every active nightly tester + when it completes. As such, this list gets email several times each day, + making it a high volume list. + + .. __: http://lists.cs.uiuc.edu/pipermail/llvm-testresults/ + +`LLVM Announcements List (llvm-announce)`__ + This is a low volume list that provides important announcements regarding + LLVM. It gets email about once a month. + + .. __: http://lists.cs.uiuc.edu/mailman/listinfo/llvm-announce + +IRC +--- + +Users and developers of the LLVM project (including subprojects such as Clang) +can be found in #llvm on `irc.oftc.net `_. + +This channel has several bots. + +* Buildbot reporters + + * llvmbb - Bot for the main LLVM buildbot master. + http://lab.llvm.org:8011/console + * bb-chapuni - An individually run buildbot master. http://bb.pgr.jp/console + * smooshlab - Apple's internal buildbot master. + +* robot - Bugzilla linker. %bug + +* clang-bot - A `geordi `_ instance running + near-trunk clang instead of gcc. + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/docs/linpack-pc.png b/docs/linpack-pc.png new file mode 100644 index 00000000..bbbee7d6 Binary files /dev/null and b/docs/linpack-pc.png differ diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..8dfec039 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\llvm.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\llvm.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/docs/re_format.7 b/docs/re_format.7 new file mode 100644 index 00000000..0c092871 --- /dev/null +++ b/docs/re_format.7 @@ -0,0 +1,756 @@ +.\" $OpenBSD: re_format.7,v 1.14 2007/05/31 19:19:30 jmc Exp $ +.\" +.\" Copyright (c) 1997, Phillip F Knaack. All rights reserved. +.\" +.\" Copyright (c) 1992, 1993, 1994 Henry Spencer. +.\" Copyright (c) 1992, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Henry Spencer. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)re_format.7 8.3 (Berkeley) 3/20/94 +.\" +.Dd $Mdocdate: May 31 2007 $ +.Dt RE_FORMAT 7 +.Os +.Sh NAME +.Nm re_format +.Nd POSIX regular expressions +.Sh DESCRIPTION +Regular expressions (REs), +as defined in +.St -p1003.1-2004 , +come in two forms: +basic regular expressions +(BREs) +and extended regular expressions +(EREs). +Both forms of regular expressions are supported +by the interfaces described in +.Xr regex 3 . +Applications dealing with regular expressions +may use one or the other form +(or indeed both). +For example, +.Xr ed 1 +uses BREs, +whilst +.Xr egrep 1 +talks EREs. +Consult the manual page for the specific application to find out which +it uses. +.Pp +POSIX leaves some aspects of RE syntax and semantics open; +.Sq ** +marks decisions on these aspects that +may not be fully portable to other POSIX implementations. +.Pp +This manual page first describes regular expressions in general, +specifically extended regular expressions, +and then discusses differences between them and basic regular expressions. +.Sh EXTENDED REGULAR EXPRESSIONS +An ERE is one** or more non-empty** +.Em branches , +separated by +.Sq \*(Ba . +It matches anything that matches one of the branches. +.Pp +A branch is one** or more +.Em pieces , +concatenated. +It matches a match for the first, followed by a match for the second, etc. +.Pp +A piece is an +.Em atom +possibly followed by a single** +.Sq * , +.Sq + , +.Sq ?\& , +or +.Em bound . +An atom followed by +.Sq * +matches a sequence of 0 or more matches of the atom. +An atom followed by +.Sq + +matches a sequence of 1 or more matches of the atom. +An atom followed by +.Sq ?\& +matches a sequence of 0 or 1 matches of the atom. +.Pp +A bound is +.Sq { +followed by an unsigned decimal integer, +possibly followed by +.Sq ,\& +possibly followed by another unsigned decimal integer, +always followed by +.Sq } . +The integers must lie between 0 and +.Dv RE_DUP_MAX +(255**) inclusive, +and if there are two of them, the first may not exceed the second. +An atom followed by a bound containing one integer +.Ar i +and no comma matches +a sequence of exactly +.Ar i +matches of the atom. +An atom followed by a bound +containing one integer +.Ar i +and a comma matches +a sequence of +.Ar i +or more matches of the atom. +An atom followed by a bound +containing two integers +.Ar i +and +.Ar j +matches a sequence of +.Ar i +through +.Ar j +(inclusive) matches of the atom. +.Pp +An atom is a regular expression enclosed in +.Sq () +(matching a part of the regular expression), +an empty set of +.Sq () +(matching the null string)**, +a +.Em bracket expression +(see below), +.Sq .\& +(matching any single character), +.Sq ^ +(matching the null string at the beginning of a line), +.Sq $ +(matching the null string at the end of a line), +a +.Sq \e +followed by one of the characters +.Sq ^.[$()|*+?{\e +(matching that character taken as an ordinary character), +a +.Sq \e +followed by any other character** +(matching that character taken as an ordinary character, +as if the +.Sq \e +had not been present**), +or a single character with no other significance (matching that character). +A +.Sq { +followed by a character other than a digit is an ordinary character, +not the beginning of a bound**. +It is illegal to end an RE with +.Sq \e . +.Pp +A bracket expression is a list of characters enclosed in +.Sq [] . +It normally matches any single character from the list (but see below). +If the list begins with +.Sq ^ , +it matches any single character +.Em not +from the rest of the list +(but see below). +If two characters in the list are separated by +.Sq - , +this is shorthand for the full +.Em range +of characters between those two (inclusive) in the +collating sequence, e.g.\& +.Sq [0-9] +in ASCII matches any decimal digit. +It is illegal** for two ranges to share an endpoint, e.g.\& +.Sq a-c-e . +Ranges are very collating-sequence-dependent, +and portable programs should avoid relying on them. +.Pp +To include a literal +.Sq ]\& +in the list, make it the first character +(following a possible +.Sq ^ ) . +To include a literal +.Sq - , +make it the first or last character, +or the second endpoint of a range. +To use a literal +.Sq - +as the first endpoint of a range, +enclose it in +.Sq [. +and +.Sq .] +to make it a collating element (see below). +With the exception of these and some combinations using +.Sq [ +(see next paragraphs), +all other special characters, including +.Sq \e , +lose their special significance within a bracket expression. +.Pp +Within a bracket expression, a collating element +(a character, +a multi-character sequence that collates as if it were a single character, +or a collating-sequence name for either) +enclosed in +.Sq [. +and +.Sq .] +stands for the sequence of characters of that collating element. +The sequence is a single element of the bracket expression's list. +A bracket expression containing a multi-character collating element +can thus match more than one character, +e.g. if the collating sequence includes a +.Sq ch +collating element, +then the RE +.Sq [[.ch.]]*c +matches the first five characters of +.Sq chchcc . +.Pp +Within a bracket expression, a collating element enclosed in +.Sq [= +and +.Sq =] +is an equivalence class, standing for the sequences of characters +of all collating elements equivalent to that one, including itself. +(If there are no other equivalent collating elements, +the treatment is as if the enclosing delimiters were +.Sq [. +and +.Sq .] . ) +For example, if +.Sq x +and +.Sq y +are the members of an equivalence class, +then +.Sq [[=x=]] , +.Sq [[=y=]] , +and +.Sq [xy] +are all synonymous. +An equivalence class may not** be an endpoint of a range. +.Pp +Within a bracket expression, the name of a +.Em character class +enclosed +in +.Sq [: +and +.Sq :] +stands for the list of all characters belonging to that class. +Standard character class names are: +.Bd -literal -offset indent +alnum digit punct +alpha graph space +blank lower upper +cntrl print xdigit +.Ed +.Pp +These stand for the character classes defined in +.Xr ctype 3 . +A locale may provide others. +A character class may not be used as an endpoint of a range. +.Pp +There are two special cases** of bracket expressions: +the bracket expressions +.Sq [[:<:]] +and +.Sq [[:>:]] +match the null string at the beginning and end of a word, respectively. +A word is defined as a sequence of +characters starting and ending with a word character +which is neither preceded nor followed by +word characters. +A word character is an +.Em alnum +character (as defined by +.Xr ctype 3 ) +or an underscore. +This is an extension, +compatible with but not specified by POSIX, +and should be used with +caution in software intended to be portable to other systems. +.Pp +In the event that an RE could match more than one substring of a given +string, +the RE matches the one starting earliest in the string. +If the RE could match more than one substring starting at that point, +it matches the longest. +Subexpressions also match the longest possible substrings, subject to +the constraint that the whole match be as long as possible, +with subexpressions starting earlier in the RE taking priority over +ones starting later. +Note that higher-level subexpressions thus take priority over +their lower-level component subexpressions. +.Pp +Match lengths are measured in characters, not collating elements. +A null string is considered longer than no match at all. +For example, +.Sq bb* +matches the three middle characters of +.Sq abbbc ; +.Sq (wee|week)(knights|nights) +matches all ten characters of +.Sq weeknights ; +when +.Sq (.*).* +is matched against +.Sq abc , +the parenthesized subexpression matches all three characters; +and when +.Sq (a*)* +is matched against +.Sq bc , +both the whole RE and the parenthesized subexpression match the null string. +.Pp +If case-independent matching is specified, +the effect is much as if all case distinctions had vanished from the +alphabet. +When an alphabetic that exists in multiple cases appears as an +ordinary character outside a bracket expression, it is effectively +transformed into a bracket expression containing both cases, +e.g.\& +.Sq x +becomes +.Sq [xX] . +When it appears inside a bracket expression, +all case counterparts of it are added to the bracket expression, +so that, for example, +.Sq [x] +becomes +.Sq [xX] +and +.Sq [^x] +becomes +.Sq [^xX] . +.Pp +No particular limit is imposed on the length of REs**. +Programs intended to be portable should not employ REs longer +than 256 bytes, +as an implementation can refuse to accept such REs and remain +POSIX-compliant. +.Pp +The following is a list of extended regular expressions: +.Bl -tag -width Ds +.It Ar c +Any character +.Ar c +not listed below matches itself. +.It \e Ns Ar c +Any backslash-escaped character +.Ar c +matches itself. +.It \&. +Matches any single character that is not a newline +.Pq Sq \en . +.It Bq Ar char-class +Matches any single character in +.Ar char-class . +To include a +.Ql \&] +in +.Ar char-class , +it must be the first character. +A range of characters may be specified by separating the end characters +of the range with a +.Ql - ; +e.g.\& +.Ar a-z +specifies the lower case characters. +The following literal expressions can also be used in +.Ar char-class +to specify sets of characters: +.Bd -unfilled -offset indent +[:alnum:] [:cntrl:] [:lower:] [:space:] +[:alpha:] [:digit:] [:print:] [:upper:] +[:blank:] [:graph:] [:punct:] [:xdigit:] +.Ed +.Pp +If +.Ql - +appears as the first or last character of +.Ar char-class , +then it matches itself. +All other characters in +.Ar char-class +match themselves. +.Pp +Patterns in +.Ar char-class +of the form +.Eo [. +.Ar col-elm +.Ec .]\& +or +.Eo [= +.Ar col-elm +.Ec =]\& , +where +.Ar col-elm +is a collating element, are interpreted according to +.Xr setlocale 3 +.Pq not currently supported . +.It Bq ^ Ns Ar char-class +Matches any single character, other than newline, not in +.Ar char-class . +.Ar char-class +is defined as above. +.It ^ +If +.Sq ^ +is the first character of a regular expression, then it +anchors the regular expression to the beginning of a line. +Otherwise, it matches itself. +.It $ +If +.Sq $ +is the last character of a regular expression, +it anchors the regular expression to the end of a line. +Otherwise, it matches itself. +.It [[:<:]] +Anchors the single character regular expression or subexpression +immediately following it to the beginning of a word. +.It [[:>:]] +Anchors the single character regular expression or subexpression +immediately following it to the end of a word. +.It Pq Ar re +Defines a subexpression +.Ar re . +Any set of characters enclosed in parentheses +matches whatever the set of characters without parentheses matches +(that is a long-winded way of saying the constructs +.Sq (re) +and +.Sq re +match identically). +.It * +Matches the single character regular expression or subexpression +immediately preceding it zero or more times. +If +.Sq * +is the first character of a regular expression or subexpression, +then it matches itself. +The +.Sq * +operator sometimes yields unexpected results. +For example, the regular expression +.Ar b* +matches the beginning of the string +.Qq abbb +(as opposed to the substring +.Qq bbb ) , +since a null match is the only leftmost match. +.It + +Matches the singular character regular expression +or subexpression immediately preceding it +one or more times. +.It ? +Matches the singular character regular expression +or subexpression immediately preceding it +0 or 1 times. +.Sm off +.It Xo +.Pf { Ar n , m No }\ \& +.Pf { Ar n , No }\ \& +.Pf { Ar n No } +.Xc +.Sm on +Matches the single character regular expression or subexpression +immediately preceding it at least +.Ar n +and at most +.Ar m +times. +If +.Ar m +is omitted, then it matches at least +.Ar n +times. +If the comma is also omitted, then it matches exactly +.Ar n +times. +.It \*(Ba +Used to separate patterns. +For example, +the pattern +.Sq cat\*(Badog +matches either +.Sq cat +or +.Sq dog . +.El +.Sh BASIC REGULAR EXPRESSIONS +Basic regular expressions differ in several respects: +.Bl -bullet -offset 3n +.It +.Sq \*(Ba , +.Sq + , +and +.Sq ?\& +are ordinary characters and there is no equivalent +for their functionality. +.It +The delimiters for bounds are +.Sq \e{ +and +.Sq \e} , +with +.Sq { +and +.Sq } +by themselves ordinary characters. +.It +The parentheses for nested subexpressions are +.Sq \e( +and +.Sq \e) , +with +.Sq ( +and +.Sq )\& +by themselves ordinary characters. +.It +.Sq ^ +is an ordinary character except at the beginning of the +RE or** the beginning of a parenthesized subexpression. +.It +.Sq $ +is an ordinary character except at the end of the +RE or** the end of a parenthesized subexpression. +.It +.Sq * +is an ordinary character if it appears at the beginning of the +RE or the beginning of a parenthesized subexpression +(after a possible leading +.Sq ^ ) . +.It +Finally, there is one new type of atom, a +.Em back-reference : +.Sq \e +followed by a non-zero decimal digit +.Ar d +matches the same sequence of characters matched by the +.Ar d Ns th +parenthesized subexpression +(numbering subexpressions by the positions of their opening parentheses, +left to right), +so that, for example, +.Sq \e([bc]\e)\e1 +matches +.Sq bb\& +or +.Sq cc +but not +.Sq bc . +.El +.Pp +The following is a list of basic regular expressions: +.Bl -tag -width Ds +.It Ar c +Any character +.Ar c +not listed below matches itself. +.It \e Ns Ar c +Any backslash-escaped character +.Ar c , +except for +.Sq { , +.Sq } , +.Sq \&( , +and +.Sq \&) , +matches itself. +.It \&. +Matches any single character that is not a newline +.Pq Sq \en . +.It Bq Ar char-class +Matches any single character in +.Ar char-class . +To include a +.Ql \&] +in +.Ar char-class , +it must be the first character. +A range of characters may be specified by separating the end characters +of the range with a +.Ql - ; +e.g.\& +.Ar a-z +specifies the lower case characters. +The following literal expressions can also be used in +.Ar char-class +to specify sets of characters: +.Bd -unfilled -offset indent +[:alnum:] [:cntrl:] [:lower:] [:space:] +[:alpha:] [:digit:] [:print:] [:upper:] +[:blank:] [:graph:] [:punct:] [:xdigit:] +.Ed +.Pp +If +.Ql - +appears as the first or last character of +.Ar char-class , +then it matches itself. +All other characters in +.Ar char-class +match themselves. +.Pp +Patterns in +.Ar char-class +of the form +.Eo [. +.Ar col-elm +.Ec .]\& +or +.Eo [= +.Ar col-elm +.Ec =]\& , +where +.Ar col-elm +is a collating element, are interpreted according to +.Xr setlocale 3 +.Pq not currently supported . +.It Bq ^ Ns Ar char-class +Matches any single character, other than newline, not in +.Ar char-class . +.Ar char-class +is defined as above. +.It ^ +If +.Sq ^ +is the first character of a regular expression, then it +anchors the regular expression to the beginning of a line. +Otherwise, it matches itself. +.It $ +If +.Sq $ +is the last character of a regular expression, +it anchors the regular expression to the end of a line. +Otherwise, it matches itself. +.It [[:<:]] +Anchors the single character regular expression or subexpression +immediately following it to the beginning of a word. +.It [[:>:]] +Anchors the single character regular expression or subexpression +immediately following it to the end of a word. +.It \e( Ns Ar re Ns \e) +Defines a subexpression +.Ar re . +Subexpressions may be nested. +A subsequent backreference of the form +.Pf \e Ns Ar n , +where +.Ar n +is a number in the range [1,9], expands to the text matched by the +.Ar n Ns th +subexpression. +For example, the regular expression +.Ar \e(.*\e)\e1 +matches any string consisting of identical adjacent substrings. +Subexpressions are ordered relative to their left delimiter. +.It * +Matches the single character regular expression or subexpression +immediately preceding it zero or more times. +If +.Sq * +is the first character of a regular expression or subexpression, +then it matches itself. +The +.Sq * +operator sometimes yields unexpected results. +For example, the regular expression +.Ar b* +matches the beginning of the string +.Qq abbb +(as opposed to the substring +.Qq bbb ) , +since a null match is the only leftmost match. +.Sm off +.It Xo +.Pf \e{ Ar n , m No \e}\ \& +.Pf \e{ Ar n , No \e}\ \& +.Pf \e{ Ar n No \e} +.Xc +.Sm on +Matches the single character regular expression or subexpression +immediately preceding it at least +.Ar n +and at most +.Ar m +times. +If +.Ar m +is omitted, then it matches at least +.Ar n +times. +If the comma is also omitted, then it matches exactly +.Ar n +times. +.El +.Sh SEE ALSO +.Xr ctype 3 , +.Xr regex 3 +.Sh STANDARDS +.St -p1003.1-2004 : +Base Definitions, Chapter 9 (Regular Expressions). +.Sh BUGS +Having two kinds of REs is a botch. +.Pp +The current POSIX spec says that +.Sq )\& +is an ordinary character in the absence of an unmatched +.Sq ( ; +this was an unintentional result of a wording error, +and change is likely. +Avoid relying on it. +.Pp +Back-references are a dreadful botch, +posing major problems for efficient implementations. +They are also somewhat vaguely defined +(does +.Sq a\e(\e(b\e)*\e2\e)*d +match +.Sq abbbd ? ) . +Avoid using them. +.Pp +POSIX's specification of case-independent matching is vague. +The +.Dq one case implies all cases +definition given above +is the current consensus among implementors as to the right interpretation. +.Pp +The syntax for word boundaries is incredibly ugly. diff --git a/docs/tutorial/LangImpl1.rst b/docs/tutorial/LangImpl1.rst new file mode 100644 index 00000000..a2c5eeeb --- /dev/null +++ b/docs/tutorial/LangImpl1.rst @@ -0,0 +1,278 @@ +================================================= +Kaleidoscope: Tutorial Introduction and the Lexer +================================================= + +.. contents:: + :local: + +Tutorial Introduction +===================== + +Welcome to the "Implementing a language with LLVM" tutorial. This +tutorial runs through the implementation of a simple language, showing +how fun and easy it can be. This tutorial will get you up and started as +well as help to build a framework you can extend to other languages. The +code in this tutorial can also be used as a playground to hack on other +LLVM specific things. + +The goal of this tutorial is to progressively unveil our language, +describing how it is built up over time. This will let us cover a fairly +broad range of language design and LLVM-specific usage issues, showing +and explaining the code for it all along the way, without overwhelming +you with tons of details up front. + +It is useful to point out ahead of time that this tutorial is really +about teaching compiler techniques and LLVM specifically, *not* about +teaching modern and sane software engineering principles. In practice, +this means that we'll take a number of shortcuts to simplify the +exposition. For example, the code leaks memory, uses global variables +all over the place, doesn't use nice design patterns like +`visitors `_, etc... but +it is very simple. If you dig in and use the code as a basis for future +projects, fixing these deficiencies shouldn't be hard. + +I've tried to put this tutorial together in a way that makes chapters +easy to skip over if you are already familiar with or are uninterested +in the various pieces. The structure of the tutorial is: + +- `Chapter #1 <#language>`_: Introduction to the Kaleidoscope + language, and the definition of its Lexer - This shows where we are + going and the basic functionality that we want it to do. In order to + make this tutorial maximally understandable and hackable, we choose + to implement everything in C++ instead of using lexer and parser + generators. LLVM obviously works just fine with such tools, feel free + to use one if you prefer. +- `Chapter #2 `_: Implementing a Parser and AST - + With the lexer in place, we can talk about parsing techniques and + basic AST construction. This tutorial describes recursive descent + parsing and operator precedence parsing. Nothing in Chapters 1 or 2 + is LLVM-specific, the code doesn't even link in LLVM at this point. + :) +- `Chapter #3 `_: Code generation to LLVM IR - With + the AST ready, we can show off how easy generation of LLVM IR really + is. +- `Chapter #4 `_: Adding JIT and Optimizer Support + - Because a lot of people are interested in using LLVM as a JIT, + we'll dive right into it and show you the 3 lines it takes to add JIT + support. LLVM is also useful in many other ways, but this is one + simple and "sexy" way to show off its power. :) +- `Chapter #5 `_: Extending the Language: Control + Flow - With the language up and running, we show how to extend it + with control flow operations (if/then/else and a 'for' loop). This + gives us a chance to talk about simple SSA construction and control + flow. +- `Chapter #6 `_: Extending the Language: + User-defined Operators - This is a silly but fun chapter that talks + about extending the language to let the user program define their own + arbitrary unary and binary operators (with assignable precedence!). + This lets us build a significant piece of the "language" as library + routines. +- `Chapter #7 `_: Extending the Language: Mutable + Variables - This chapter talks about adding user-defined local + variables along with an assignment operator. The interesting part + about this is how easy and trivial it is to construct SSA form in + LLVM: no, LLVM does *not* require your front-end to construct SSA + form! +- `Chapter #8 `_: Conclusion and other useful LLVM + tidbits - This chapter wraps up the series by talking about + potential ways to extend the language, but also includes a bunch of + pointers to info about "special topics" like adding garbage + collection support, exceptions, debugging, support for "spaghetti + stacks", and a bunch of other tips and tricks. + +By the end of the tutorial, we'll have written a bit less than 700 lines +of non-comment, non-blank, lines of code. With this small amount of +code, we'll have built up a very reasonable compiler for a non-trivial +language including a hand-written lexer, parser, AST, as well as code +generation support with a JIT compiler. While other systems may have +interesting "hello world" tutorials, I think the breadth of this +tutorial is a great testament to the strengths of LLVM and why you +should consider it if you're interested in language or compiler design. + +A note about this tutorial: we expect you to extend the language and +play with it on your own. Take the code and go crazy hacking away at it, +compilers don't need to be scary creatures - it can be a lot of fun to +play with languages! + +The Basic Language +================== + +This tutorial will be illustrated with a toy language that we'll call +"`Kaleidoscope `_" (derived +from "meaning beautiful, form, and view"). Kaleidoscope is a procedural +language that allows you to define functions, use conditionals, math, +etc. Over the course of the tutorial, we'll extend Kaleidoscope to +support the if/then/else construct, a for loop, user defined operators, +JIT compilation with a simple command line interface, etc. + +Because we want to keep things simple, the only datatype in Kaleidoscope +is a 64-bit floating point type (aka 'double' in C parlance). As such, +all values are implicitly double precision and the language doesn't +require type declarations. This gives the language a very nice and +simple syntax. For example, the following simple example computes +`Fibonacci numbers: `_ + +:: + + # Compute the x'th fibonacci number. + def fib(x) + if x < 3 then + 1 + else + fib(x-1)+fib(x-2) + + # This expression will compute the 40th number. + fib(40) + +We also allow Kaleidoscope to call into standard library functions (the +LLVM JIT makes this completely trivial). This means that you can use the +'extern' keyword to define a function before you use it (this is also +useful for mutually recursive functions). For example: + +:: + + extern sin(arg); + extern cos(arg); + extern atan2(arg1 arg2); + + atan2(sin(.4), cos(42)) + +A more interesting example is included in Chapter 6 where we write a +little Kaleidoscope application that `displays a Mandelbrot +Set `_ at various levels of magnification. + +Lets dive into the implementation of this language! + +The Lexer +========= + +When it comes to implementing a language, the first thing needed is the +ability to process a text file and recognize what it says. The +traditional way to do this is to use a +"`lexer `_" (aka +'scanner') to break the input up into "tokens". Each token returned by +the lexer includes a token code and potentially some metadata (e.g. the +numeric value of a number). First, we define the possibilities: + +.. code-block:: c++ + + // The lexer returns tokens [0-255] if it is an unknown character, otherwise one + // of these for known things. + enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + }; + + static std::string IdentifierStr; // Filled in if tok_identifier + static double NumVal; // Filled in if tok_number + +Each token returned by our lexer will either be one of the Token enum +values or it will be an 'unknown' character like '+', which is returned +as its ASCII value. If the current token is an identifier, the +``IdentifierStr`` global variable holds the name of the identifier. If +the current token is a numeric literal (like 1.0), ``NumVal`` holds its +value. Note that we use global variables for simplicity, this is not the +best choice for a real language implementation :). + +The actual implementation of the lexer is a single function named +``gettok``. The ``gettok`` function is called to return the next token +from standard input. Its definition starts as: + +.. code-block:: c++ + + /// gettok - Return the next token from standard input. + static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + +``gettok`` works by calling the C ``getchar()`` function to read +characters one at a time from standard input. It eats them as it +recognizes them and stores the last character read, but not processed, +in LastChar. The first thing that it has to do is ignore whitespace +between tokens. This is accomplished with the loop above. + +The next thing ``gettok`` needs to do is recognize identifiers and +specific keywords like "def". Kaleidoscope does this with this simple +loop: + +.. code-block:: c++ + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + return tok_identifier; + } + +Note that this code sets the '``IdentifierStr``' global whenever it +lexes an identifier. Also, since language keywords are matched by the +same loop, we handle them here inline. Numeric values are similar: + +.. code-block:: c++ + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + +This is all pretty straight-forward code for processing input. When +reading a numeric value from input, we use the C ``strtod`` function to +convert it to a numeric value that we store in ``NumVal``. Note that +this isn't doing sufficient error checking: it will incorrectly read +"1.23.45.67" and handle it as if you typed in "1.23". Feel free to +extend it :). Next we handle comments: + +.. code-block:: c++ + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + +We handle comments by skipping to the end of the line and then return +the next token. Finally, if the input doesn't match one of the above +cases, it is either an operator character like '+' or the end of the +file. These are handled with this code: + +.. code-block:: c++ + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; + } + +With this, we have the complete lexer for the basic Kaleidoscope +language (the `full code listing `_ for the Lexer +is available in the `next chapter `_ of the tutorial). +Next we'll `build a simple parser that uses this to build an Abstract +Syntax Tree `_. When we have that, we'll include a +driver so that you can use the lexer and parser together. + +`Next: Implementing a Parser and AST `_ + diff --git a/docs/tutorial/LangImpl2.rst b/docs/tutorial/LangImpl2.rst new file mode 100644 index 00000000..06b18ff6 --- /dev/null +++ b/docs/tutorial/LangImpl2.rst @@ -0,0 +1,698 @@ +=========================================== +Kaleidoscope: Implementing a Parser and AST +=========================================== + +.. contents:: + :local: + +Chapter 2 Introduction +====================== + +Welcome to Chapter 2 of the "`Implementing a language with +LLVM `_" tutorial. This chapter shows you how to use the +lexer, built in `Chapter 1 `_, to build a full +`parser `_ for our Kaleidoscope +language. Once we have a parser, we'll define and build an `Abstract +Syntax Tree `_ (AST). + +The parser we will build uses a combination of `Recursive Descent +Parsing `_ and +`Operator-Precedence +Parsing `_ to +parse the Kaleidoscope language (the latter for binary expressions and +the former for everything else). Before we get to parsing though, lets +talk about the output of the parser: the Abstract Syntax Tree. + +The Abstract Syntax Tree (AST) +============================== + +The AST for a program captures its behavior in such a way that it is +easy for later stages of the compiler (e.g. code generation) to +interpret. We basically want one object for each construct in the +language, and the AST should closely model the language. In +Kaleidoscope, we have expressions, a prototype, and a function object. +We'll start with expressions first: + +.. code-block:: c++ + + /// ExprAST - Base class for all expression nodes. + class ExprAST { + public: + virtual ~ExprAST() {} + }; + + /// NumberExprAST - Expression class for numeric literals like "1.0". + class NumberExprAST : public ExprAST { + double Val; + public: + NumberExprAST(double val) : Val(val) {} + }; + +The code above shows the definition of the base ExprAST class and one +subclass which we use for numeric literals. The important thing to note +about this code is that the NumberExprAST class captures the numeric +value of the literal as an instance variable. This allows later phases +of the compiler to know what the stored numeric value is. + +Right now we only create the AST, so there are no useful accessor +methods on them. It would be very easy to add a virtual method to pretty +print the code, for example. Here are the other expression AST node +definitions that we'll use in the basic form of the Kaleidoscope +language: + +.. code-block:: c++ + + /// VariableExprAST - Expression class for referencing a variable, like "a". + class VariableExprAST : public ExprAST { + std::string Name; + public: + VariableExprAST(const std::string &name) : Name(name) {} + }; + + /// BinaryExprAST - Expression class for a binary operator. + class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; + public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + }; + + /// CallExprAST - Expression class for function calls. + class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; + public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + }; + +This is all (intentionally) rather straight-forward: variables capture +the variable name, binary operators capture their opcode (e.g. '+'), and +calls capture a function name as well as a list of any argument +expressions. One thing that is nice about our AST is that it captures +the language features without talking about the syntax of the language. +Note that there is no discussion about precedence of binary operators, +lexical structure, etc. + +For our basic language, these are all of the expression nodes we'll +define. Because it doesn't have conditional control flow, it isn't +Turing-complete; we'll fix that in a later installment. The two things +we need next are a way to talk about the interface to a function, and a +way to talk about functions themselves: + +.. code-block:: c++ + + /// PrototypeAST - This class represents the "prototype" for a function, + /// which captures its name, and its argument names (thus implicitly the number + /// of arguments the function takes). + class PrototypeAST { + std::string Name; + std::vector Args; + public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + }; + + /// FunctionAST - This class represents a function definition itself. + class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; + public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + }; + +In Kaleidoscope, functions are typed with just a count of their +arguments. Since all values are double precision floating point, the +type of each argument doesn't need to be stored anywhere. In a more +aggressive and realistic language, the "ExprAST" class would probably +have a type field. + +With this scaffolding, we can now talk about parsing expressions and +function bodies in Kaleidoscope. + +Parser Basics +============= + +Now that we have an AST to build, we need to define the parser code to +build it. The idea here is that we want to parse something like "x+y" +(which is returned as three tokens by the lexer) into an AST that could +be generated with calls like this: + +.. code-block:: c++ + + ExprAST *X = new VariableExprAST("x"); + ExprAST *Y = new VariableExprAST("y"); + ExprAST *Result = new BinaryExprAST('+', X, Y); + +In order to do this, we'll start by defining some basic helper routines: + +.. code-block:: c++ + + /// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current + /// token the parser is looking at. getNextToken reads another token from the + /// lexer and updates CurTok with its results. + static int CurTok; + static int getNextToken() { + return CurTok = gettok(); + } + +This implements a simple token buffer around the lexer. This allows us +to look one token ahead at what the lexer is returning. Every function +in our parser will assume that CurTok is the current token that needs to +be parsed. + +.. code-block:: c++ + + + /// Error* - These are little helper functions for error handling. + ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} + PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } + FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +The ``Error`` routines are simple helper routines that our parser will +use to handle errors. The error recovery in our parser will not be the +best and is not particular user-friendly, but it will be enough for our +tutorial. These routines make it easier to handle errors in routines +that have various return types: they always return null. + +With these basic helper functions, we can implement the first piece of +our grammar: numeric literals. + +Basic Expression Parsing +======================== + +We start with numeric literals, because they are the simplest to +process. For each production in our grammar, we'll define a function +which parses that production. For numeric literals, we have: + +.. code-block:: c++ + + /// numberexpr ::= number + static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; + } + +This routine is very simple: it expects to be called when the current +token is a ``tok_number`` token. It takes the current number value, +creates a ``NumberExprAST`` node, advances the lexer to the next token, +and finally returns. + +There are some interesting aspects to this. The most important one is +that this routine eats all of the tokens that correspond to the +production and returns the lexer buffer with the next token (which is +not part of the grammar production) ready to go. This is a fairly +standard way to go for recursive descent parsers. For a better example, +the parenthesis operator is defined like this: + +.. code-block:: c++ + + /// parenexpr ::= '(' expression ')' + static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; + } + +This function illustrates a number of interesting things about the +parser: + +1) It shows how we use the Error routines. When called, this function +expects that the current token is a '(' token, but after parsing the +subexpression, it is possible that there is no ')' waiting. For example, +if the user types in "(4 x" instead of "(4)", the parser should emit an +error. Because errors can occur, the parser needs a way to indicate that +they happened: in our parser, we return null on an error. + +2) Another interesting aspect of this function is that it uses recursion +by calling ``ParseExpression`` (we will soon see that +``ParseExpression`` can call ``ParseParenExpr``). This is powerful +because it allows us to handle recursive grammars, and keeps each +production very simple. Note that parentheses do not cause construction +of AST nodes themselves. While we could do it this way, the most +important role of parentheses are to guide the parser and provide +grouping. Once the parser constructs the AST, parentheses are not +needed. + +The next simple production is for handling variable references and +function calls: + +.. code-block:: c++ + + /// identifierexpr + /// ::= identifier + /// ::= identifier '(' expression* ')' + static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); + } + +This routine follows the same style as the other routines. (It expects +to be called if the current token is a ``tok_identifier`` token). It +also has recursion and error handling. One interesting aspect of this is +that it uses *look-ahead* to determine if the current identifier is a +stand alone variable reference or if it is a function call expression. +It handles this by checking to see if the token after the identifier is +a '(' token, constructing either a ``VariableExprAST`` or +``CallExprAST`` node as appropriate. + +Now that we have all of our simple expression-parsing logic in place, we +can define a helper function to wrap it together into one entry point. +We call this class of expressions "primary" expressions, for reasons +that will become more clear `later in the +tutorial `_. In order to parse an arbitrary +primary expression, we need to determine what sort of expression it is: + +.. code-block:: c++ + + /// primary + /// ::= identifierexpr + /// ::= numberexpr + /// ::= parenexpr + static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + } + } + +Now that you see the definition of this function, it is more obvious why +we can assume the state of CurTok in the various functions. This uses +look-ahead to determine which sort of expression is being inspected, and +then parses it with a function call. + +Now that basic expressions are handled, we need to handle binary +expressions. They are a bit more complex. + +Binary Expression Parsing +========================= + +Binary expressions are significantly harder to parse because they are +often ambiguous. For example, when given the string "x+y\*z", the parser +can choose to parse it as either "(x+y)\*z" or "x+(y\*z)". With common +definitions from mathematics, we expect the later parse, because "\*" +(multiplication) has higher *precedence* than "+" (addition). + +There are many ways to handle this, but an elegant and efficient way is +to use `Operator-Precedence +Parsing `_. +This parsing technique uses the precedence of binary operators to guide +recursion. To start with, we need a table of precedences: + +.. code-block:: c++ + + /// BinopPrecedence - This holds the precedence for each binary operator that is + /// defined. + static std::map BinopPrecedence; + + /// GetTokPrecedence - Get the precedence of the pending binary operator token. + static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; + } + + int main() { + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + ... + } + +For the basic form of Kaleidoscope, we will only support 4 binary +operators (this can obviously be extended by you, our brave and intrepid +reader). The ``GetTokPrecedence`` function returns the precedence for +the current token, or -1 if the token is not a binary operator. Having a +map makes it easy to add new operators and makes it clear that the +algorithm doesn't depend on the specific operators involved, but it +would be easy enough to eliminate the map and do the comparisons in the +``GetTokPrecedence`` function. (Or just use a fixed-size array). + +With the helper above defined, we can now start parsing binary +expressions. The basic idea of operator precedence parsing is to break +down an expression with potentially ambiguous binary operators into +pieces. Consider ,for example, the expression "a+b+(c+d)\*e\*f+g". +Operator precedence parsing considers this as a stream of primary +expressions separated by binary operators. As such, it will first parse +the leading primary expression "a", then it will see the pairs [+, b] +[+, (c+d)] [\*, e] [\*, f] and [+, g]. Note that because parentheses are +primary expressions, the binary expression parser doesn't need to worry +about nested subexpressions like (c+d) at all. + +To start, an expression is a primary expression potentially followed by +a sequence of [binop,primaryexpr] pairs: + +.. code-block:: c++ + + /// expression + /// ::= primary binoprhs + /// + static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); + } + +``ParseBinOpRHS`` is the function that parses the sequence of pairs for +us. It takes a precedence and a pointer to an expression for the part +that has been parsed so far. Note that "x" is a perfectly valid +expression: As such, "binoprhs" is allowed to be empty, in which case it +returns the expression that is passed into it. In our example above, the +code passes the expression for "a" into ``ParseBinOpRHS`` and the +current token is "+". + +The precedence value passed into ``ParseBinOpRHS`` indicates the +*minimal operator precedence* that the function is allowed to eat. For +example, if the current pair stream is [+, x] and ``ParseBinOpRHS`` is +passed in a precedence of 40, it will not consume any tokens (because +the precedence of '+' is only 20). With this in mind, ``ParseBinOpRHS`` +starts with: + +.. code-block:: c++ + + /// binoprhs + /// ::= ('+' primary)* + static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + +This code gets the precedence of the current token and checks to see if +if is too low. Because we defined invalid tokens to have a precedence of +-1, this check implicitly knows that the pair-stream ends when the token +stream runs out of binary operators. If this check succeeds, we know +that the token is a binary operator and that it will be included in this +expression: + +.. code-block:: c++ + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + +As such, this code eats (and remembers) the binary operator and then +parses the primary expression that follows. This builds up the whole +pair, the first of which is [+, b] for the running example. + +Now that we parsed the left-hand side of an expression and one pair of +the RHS sequence, we have to decide which way the expression associates. +In particular, we could have "(a+b) binop unparsed" or "a + (b binop +unparsed)". To determine this, we look ahead at "binop" to determine its +precedence and compare it to BinOp's precedence (which is '+' in this +case): + +.. code-block:: c++ + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + +If the precedence of the binop to the right of "RHS" is lower or equal +to the precedence of our current operator, then we know that the +parentheses associate as "(a+b) binop ...". In our example, the current +operator is "+" and the next operator is "+", we know that they have the +same precedence. In this case we'll create the AST node for "a+b", and +then continue parsing: + +.. code-block:: c++ + + ... if body omitted ... + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } // loop around to the top of the while loop. + } + +In our example above, this will turn "a+b+" into "(a+b)" and execute the +next iteration of the loop, with "+" as the current token. The code +above will eat, remember, and parse "(c+d)" as the primary expression, +which makes the current pair equal to [+, (c+d)]. It will then evaluate +the 'if' conditional above with "\*" as the binop to the right of the +primary. In this case, the precedence of "\*" is higher than the +precedence of "+" so the if condition will be entered. + +The critical question left here is "how can the if condition parse the +right hand side in full"? In particular, to build the AST correctly for +our example, it needs to get all of "(c+d)\*e\*f" as the RHS expression +variable. The code to do this is surprisingly simple (code from the +above two blocks duplicated for context): + +.. code-block:: c++ + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } // loop around to the top of the while loop. + } + +At this point, we know that the binary operator to the RHS of our +primary has higher precedence than the binop we are currently parsing. +As such, we know that any sequence of pairs whose operators are all +higher precedence than "+" should be parsed together and returned as +"RHS". To do this, we recursively invoke the ``ParseBinOpRHS`` function +specifying "TokPrec+1" as the minimum precedence required for it to +continue. In our example above, this will cause it to return the AST +node for "(c+d)\*e\*f" as RHS, which is then set as the RHS of the '+' +expression. + +Finally, on the next iteration of the while loop, the "+g" piece is +parsed and added to the AST. With this little bit of code (14 +non-trivial lines), we correctly handle fully general binary expression +parsing in a very elegant way. This was a whirlwind tour of this code, +and it is somewhat subtle. I recommend running through it with a few +tough examples to see how it works. + +This wraps up handling of expressions. At this point, we can point the +parser at an arbitrary token stream and build an expression from it, +stopping at the first token that is not part of the expression. Next up +we need to handle function definitions, etc. + +Parsing the Rest +================ + +The next thing missing is handling of function prototypes. In +Kaleidoscope, these are used both for 'extern' function declarations as +well as function body definitions. The code to do this is +straight-forward and not very interesting (once you've survived +expressions): + +.. code-block:: c++ + + /// prototype + /// ::= id '(' id* ')' + static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + // Read the list of argument names. + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); + } + +Given this, a function definition is very simple, just a prototype plus +an expression to implement the body: + +.. code-block:: c++ + + /// definition ::= 'def' prototype expression + static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; + } + +In addition, we support 'extern' to declare functions like 'sin' and +'cos' as well as to support forward declaration of user functions. These +'extern's are just prototypes with no body: + +.. code-block:: c++ + + /// external ::= 'extern' prototype + static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); + } + +Finally, we'll also let the user type in arbitrary top-level expressions +and evaluate them on the fly. We will handle this by defining anonymous +nullary (zero argument) functions for them: + +.. code-block:: c++ + + /// toplevelexpr ::= expression + static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; + } + +Now that we have all the pieces, let's build a little driver that will +let us actually *execute* this code we've built! + +The Driver +========== + +The driver for this simply invokes all of the parsing pieces with a +top-level dispatch loop. There isn't much interesting here, so I'll just +include the top-level loop. See `below <#code>`_ for full code in the +"Top-Level Parsing" section. + +.. code-block:: c++ + + /// top ::= definition | external | expression | ';' + static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } + } + +The most interesting part of this is that we ignore top-level +semicolons. Why is this, you ask? The basic reason is that if you type +"4 + 5" at the command line, the parser doesn't know whether that is the +end of what you will type or not. For example, on the next line you +could type "def foo..." in which case 4+5 is the end of a top-level +expression. Alternatively you could type "\* 6", which would continue +the expression. Having top-level semicolons allows you to type "4+5;", +and the parser will know you are done. + +Conclusions +=========== + +With just under 400 lines of commented code (240 lines of non-comment, +non-blank code), we fully defined our minimal language, including a +lexer, parser, and AST builder. With this done, the executable will +validate Kaleidoscope code and tell us if it is grammatically invalid. +For example, here is a sample interaction: + +.. code-block:: bash + + $ ./a.out + ready> def foo(x y) x+foo(y, 4.0); + Parsed a function definition. + ready> def foo(x y) x+y y; + Parsed a function definition. + Parsed a top-level expr + ready> def foo(x y) x+y ); + Parsed a function definition. + Error: unknown token when expecting an expression + ready> extern sin(a); + ready> Parsed an extern + ready> ^D + $ + +There is a lot of room for extension here. You can define new AST nodes, +extend the language in many ways, etc. In the `next +installment `_, we will describe how to generate LLVM +Intermediate Representation (IR) from the AST. + +Full Code Listing +================= + +Here is the complete code listing for this and the previous chapter. +Note that it is fully self-contained: you don't need LLVM or any +external libraries at all for this. (Besides the C and C++ standard +libraries, of course.) To build this, just compile with: + +.. code-block:: bash + + # Compile + clang++ -g -O3 toy.cpp + # Run + ./a.out + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter2/toy.cpp + :language: c++ + +`Next: Implementing Code Generation to LLVM IR `_ + diff --git a/docs/tutorial/LangImpl3.rst b/docs/tutorial/LangImpl3.rst new file mode 100644 index 00000000..7174c09c --- /dev/null +++ b/docs/tutorial/LangImpl3.rst @@ -0,0 +1,594 @@ +======================================== +Kaleidoscope: Code generation to LLVM IR +======================================== + +.. contents:: + :local: + +Chapter 3 Introduction +====================== + +Welcome to Chapter 3 of the "`Implementing a language with +LLVM `_" tutorial. This chapter shows you how to transform +the `Abstract Syntax Tree `_, built in Chapter 2, into +LLVM IR. This will teach you a little bit about how LLVM does things, as +well as demonstrate how easy it is to use. It's much more work to build +a lexer and parser than it is to generate LLVM IR code. :) + +**Please note**: the code in this chapter and later require LLVM 2.2 or +later. LLVM 2.1 and before will not work with it. Also note that you +need to use a version of this tutorial that matches your LLVM release: +If you are using an official LLVM release, use the version of the +documentation included with your release or on the `llvm.org releases +page `_. + +Code Generation Setup +===================== + +In order to generate LLVM IR, we want some simple setup to get started. +First we define virtual code generation (codegen) methods in each AST +class: + +.. code-block:: c++ + + /// ExprAST - Base class for all expression nodes. + class ExprAST { + public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; + }; + + /// NumberExprAST - Expression class for numeric literals like "1.0". + class NumberExprAST : public ExprAST { + double Val; + public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); + }; + ... + +The Codegen() method says to emit IR for that AST node along with all +the things it depends on, and they all return an LLVM Value object. +"Value" is the class used to represent a "`Static Single Assignment +(SSA) `_ +register" or "SSA value" in LLVM. The most distinct aspect of SSA values +is that their value is computed as the related instruction executes, and +it does not get a new value until (and if) the instruction re-executes. +In other words, there is no way to "change" an SSA value. For more +information, please read up on `Static Single +Assignment `_ +- the concepts are really quite natural once you grok them. + +Note that instead of adding virtual methods to the ExprAST class +hierarchy, it could also make sense to use a `visitor +pattern `_ or some other +way to model this. Again, this tutorial won't dwell on good software +engineering practices: for our purposes, adding a virtual method is +simplest. + +The second thing we want is an "Error" method like we used for the +parser, which will be used to report errors found during code generation +(for example, use of an undeclared parameter): + +.. code-block:: c++ + + Value *ErrorV(const char *Str) { Error(Str); return 0; } + + static Module *TheModule; + static IRBuilder<> Builder(getGlobalContext()); + static std::map NamedValues; + +The static variables will be used during code generation. ``TheModule`` +is the LLVM construct that contains all of the functions and global +variables in a chunk of code. In many ways, it is the top-level +structure that the LLVM IR uses to contain code. + +The ``Builder`` object is a helper object that makes it easy to generate +LLVM instructions. Instances of the +```IRBuilder`` `_ +class template keep track of the current place to insert instructions +and has methods to create new instructions. + +The ``NamedValues`` map keeps track of which values are defined in the +current scope and what their LLVM representation is. (In other words, it +is a symbol table for the code). In this form of Kaleidoscope, the only +things that can be referenced are function parameters. As such, function +parameters will be in this map when generating code for their function +body. + +With these basics in place, we can start talking about how to generate +code for each expression. Note that this assumes that the ``Builder`` +has been set up to generate code *into* something. For now, we'll assume +that this has already been done, and we'll just use it to emit code. + +Expression Code Generation +========================== + +Generating LLVM code for expression nodes is very straightforward: less +than 45 lines of commented code for all four of our expression nodes. +First we'll do numeric literals: + +.. code-block:: c++ + + Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); + } + +In the LLVM IR, numeric constants are represented with the +``ConstantFP`` class, which holds the numeric value in an ``APFloat`` +internally (``APFloat`` has the capability of holding floating point +constants of Arbitrary Precision). This code basically just creates +and returns a ``ConstantFP``. Note that in the LLVM IR that constants +are all uniqued together and shared. For this reason, the API uses the +"foo::get(...)" idiom instead of "new foo(..)" or "foo::Create(..)". + +.. code-block:: c++ + + Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); + } + +References to variables are also quite simple using LLVM. In the simple +version of Kaleidoscope, we assume that the variable has already been +emitted somewhere and its value is available. In practice, the only +values that can be in the ``NamedValues`` map are function arguments. +This code simply checks to see that the specified name is in the map (if +not, an unknown variable is being referenced) and returns the value for +it. In future chapters, we'll add support for `loop induction +variables `_ in the symbol table, and for `local +variables `_. + +.. code-block:: c++ + + Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: return ErrorV("invalid binary operator"); + } + } + +Binary operators start to get more interesting. The basic idea here is +that we recursively emit code for the left-hand side of the expression, +then the right-hand side, then we compute the result of the binary +expression. In this code, we do a simple switch on the opcode to create +the right LLVM instruction. + +In the example above, the LLVM builder class is starting to show its +value. IRBuilder knows where to insert the newly created instruction, +all you have to do is specify what instruction to create (e.g. with +``CreateFAdd``), which operands to use (``L`` and ``R`` here) and +optionally provide a name for the generated instruction. + +One nice thing about LLVM is that the name is just a hint. For instance, +if the code above emits multiple "addtmp" variables, LLVM will +automatically provide each one with an increasing, unique numeric +suffix. Local value names for instructions are purely optional, but it +makes it much easier to read the IR dumps. + +`LLVM instructions <../LangRef.html#instref>`_ are constrained by strict +rules: for example, the Left and Right operators of an `add +instruction <../LangRef.html#i_add>`_ must have the same type, and the +result type of the add must match the operand types. Because all values +in Kaleidoscope are doubles, this makes for very simple code for add, +sub and mul. + +On the other hand, LLVM specifies that the `fcmp +instruction <../LangRef.html#i_fcmp>`_ always returns an 'i1' value (a +one bit integer). The problem with this is that Kaleidoscope wants the +value to be a 0.0 or 1.0 value. In order to get these semantics, we +combine the fcmp instruction with a `uitofp +instruction <../LangRef.html#i_uitofp>`_. This instruction converts its +input integer into a floating point value by treating the input as an +unsigned value. In contrast, if we used the `sitofp +instruction <../LangRef.html#i_sitofp>`_, the Kaleidoscope '<' operator +would return 0.0 and -1.0, depending on the input value. + +.. code-block:: c++ + + Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + } + +Code generation for function calls is quite straightforward with LLVM. +The code above initially does a function name lookup in the LLVM +Module's symbol table. Recall that the LLVM Module is the container that +holds all of the functions we are JIT'ing. By giving each function the +same name as what the user specifies, we can use the LLVM symbol table +to resolve function names for us. + +Once we have the function to call, we recursively codegen each argument +that is to be passed in, and create an LLVM `call +instruction <../LangRef.html#i_call>`_. Note that LLVM uses the native C +calling conventions by default, allowing these calls to also call into +standard library functions like "sin" and "cos", with no additional +effort. + +This wraps up our handling of the four basic expressions that we have so +far in Kaleidoscope. Feel free to go in and add some more. For example, +by browsing the `LLVM language reference <../LangRef.html>`_ you'll find +several other interesting instructions that are really easy to plug into +our basic framework. + +Function Code Generation +======================== + +Code generation for prototypes and functions must handle a number of +details, which make their code less beautiful than expression code +generation, but allows us to illustrate some important points. First, +lets talk about code generation for prototypes: they are used both for +function bodies and external function declarations. The code starts +with: + +.. code-block:: c++ + + Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + +This code packs a lot of power into a few lines. Note first that this +function returns a "Function\*" instead of a "Value\*". Because a +"prototype" really talks about the external interface for a function +(not the value computed by an expression), it makes sense for it to +return the LLVM Function it corresponds to when codegen'd. + +The call to ``FunctionType::get`` creates the ``FunctionType`` that +should be used for a given Prototype. Since all function arguments in +Kaleidoscope are of type double, the first line creates a vector of "N" +LLVM double types. It then uses the ``Functiontype::get`` method to +create a function type that takes "N" doubles as arguments, returns one +double as a result, and that is not vararg (the false parameter +indicates this). Note that Types in LLVM are uniqued just like Constants +are, so you don't "new" a type, you "get" it. + +The final line above actually creates the function that the prototype +will correspond to. This indicates the type, linkage and name to use, as +well as which module to insert into. "`external +linkage <../LangRef.html#linkage>`_" means that the function may be +defined outside the current module and/or that it is callable by +functions outside the module. The Name passed in is the name the user +specified: since "``TheModule``" is specified, this name is registered +in "``TheModule``"s symbol table, which is used by the function call +code above. + +.. code-block:: c++ + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + +The Module symbol table works just like the Function symbol table when +it comes to name conflicts: if a new function is created with a name +that was previously added to the symbol table, the new function will get +implicitly renamed when added to the Module. The code above exploits +this fact to determine if there was a previous definition of this +function. + +In Kaleidoscope, I choose to allow redefinitions of functions in two +cases: first, we want to allow 'extern'ing a function more than once, as +long as the prototypes for the externs match (since all arguments have +the same type, we just have to check that the number of arguments +match). Second, we want to allow 'extern'ing a function and then +defining a body for it. This is useful when defining mutually recursive +functions. + +In order to implement this, the code above first checks to see if there +is a collision on the name of the function. If so, it deletes the +function we just created (by calling ``eraseFromParent``) and then +calling ``getFunction`` to get the existing function with the specified +name. Note that many APIs in LLVM have "erase" forms and "remove" forms. +The "remove" form unlinks the object from its parent (e.g. a Function +from a Module) and returns it. The "erase" form unlinks the object and +then deletes it. + +.. code-block:: c++ + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + +In order to verify the logic above, we first check to see if the +pre-existing function is "empty". In this case, empty means that it has +no basic blocks in it, which means it has no body. If it has no body, it +is a forward declaration. Since we don't allow anything after a full +definition of the function, the code rejects this case. If the previous +reference to a function was an 'extern', we simply verify that the +number of arguments for that definition and this one match up. If not, +we emit an error. + +.. code-block:: c++ + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + return F; + } + +The last bit of code for prototypes loops over all of the arguments in +the function, setting the name of the LLVM Argument objects to match, +and registering the arguments in the ``NamedValues`` map for future use +by the ``VariableExprAST`` AST node. Once this is set up, it returns the +Function object to the caller. Note that we don't check for conflicting +argument names here (e.g. "extern foo(a b a)"). Doing so would be very +straight-forward with the mechanics we have already used above. + +.. code-block:: c++ + + Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + +Code generation for function definitions starts out simply enough: we +just codegen the prototype (Proto) and verify that it is ok. We then +clear out the ``NamedValues`` map to make sure that there isn't anything +in it from the last function we compiled. Code generation of the +prototype ensures that there is an LLVM Function object that is ready to +go for us. + +.. code-block:: c++ + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + +Now we get to the point where the ``Builder`` is set up. The first line +creates a new `basic block `_ +(named "entry"), which is inserted into ``TheFunction``. The second line +then tells the builder that new instructions should be inserted into the +end of the new basic block. Basic blocks in LLVM are an important part +of functions that define the `Control Flow +Graph `_. Since we +don't have any control flow, our functions will only contain one block +at this point. We'll fix this in `Chapter 5 `_ :). + +.. code-block:: c++ + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + +Once the insertion point is set up, we call the ``CodeGen()`` method for +the root expression of the function. If no error happens, this emits +code to compute the expression into the entry block and returns the +value that was computed. Assuming no error, we then create an LLVM `ret +instruction <../LangRef.html#i_ret>`_, which completes the function. +Once the function is built, we call ``verifyFunction``, which is +provided by LLVM. This function does a variety of consistency checks on +the generated code, to determine if our compiler is doing everything +right. Using this is important: it can catch a lot of bugs. Once the +function is finished and validated, we return it. + +.. code-block:: c++ + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + return 0; + } + +The only piece left here is handling of the error case. For simplicity, +we handle this by merely deleting the function we produced with the +``eraseFromParent`` method. This allows the user to redefine a function +that they incorrectly typed in before: if we didn't delete it, it would +live in the symbol table, with a body, preventing future redefinition. + +This code does have a bug, though. Since the ``PrototypeAST::Codegen`` +can return a previously defined forward declaration, our code can +actually delete a forward declaration. There are a number of ways to fix +this bug, see what you can come up with! Here is a testcase: + +:: + + extern foo(a b); # ok, defines foo. + def foo(a b) c; # error, 'c' is invalid. + def bar() foo(1, 2); # error, unknown function "foo" + +Driver Changes and Closing Thoughts +=================================== + +For now, code generation to LLVM doesn't really get us much, except that +we can look at the pretty IR calls. The sample code inserts calls to +Codegen into the "``HandleDefinition``", "``HandleExtern``" etc +functions, and then dumps out the LLVM IR. This gives a nice way to look +at the LLVM IR for simple functions. For example: + +:: + + ready> 4+5; + Read top-level expression: + define double @0() { + entry: + ret double 9.000000e+00 + } + +Note how the parser turns the top-level expression into anonymous +functions for us. This will be handy when we add `JIT +support `_ in the next chapter. Also note that the +code is very literally transcribed, no optimizations are being performed +except simple constant folding done by IRBuilder. We will `add +optimizations `_ explicitly in the next +chapter. + +:: + + ready> def foo(a b) a*a + 2*a*b + b*b; + Read function definition: + define double @foo(double %a, double %b) { + entry: + %multmp = fmul double %a, %a + %multmp1 = fmul double 2.000000e+00, %a + %multmp2 = fmul double %multmp1, %b + %addtmp = fadd double %multmp, %multmp2 + %multmp3 = fmul double %b, %b + %addtmp4 = fadd double %addtmp, %multmp3 + ret double %addtmp4 + } + +This shows some simple arithmetic. Notice the striking similarity to the +LLVM builder calls that we use to create the instructions. + +:: + + ready> def bar(a) foo(a, 4.0) + bar(31337); + Read function definition: + define double @bar(double %a) { + entry: + %calltmp = call double @foo(double %a, double 4.000000e+00) + %calltmp1 = call double @bar(double 3.133700e+04) + %addtmp = fadd double %calltmp, %calltmp1 + ret double %addtmp + } + +This shows some function calls. Note that this function will take a long +time to execute if you call it. In the future we'll add conditional +control flow to actually make recursion useful :). + +:: + + ready> extern cos(x); + Read extern: + declare double @cos(double) + + ready> cos(1.234); + Read top-level expression: + define double @1() { + entry: + %calltmp = call double @cos(double 1.234000e+00) + ret double %calltmp + } + +This shows an extern for the libm "cos" function, and a call to it. + +.. TODO:: Abandon Pygments' horrible `llvm` lexer. It just totally gives up + on highlighting this due to the first line. + +:: + + ready> ^D + ; ModuleID = 'my cool jit' + + define double @0() { + entry: + %addtmp = fadd double 4.000000e+00, 5.000000e+00 + ret double %addtmp + } + + define double @foo(double %a, double %b) { + entry: + %multmp = fmul double %a, %a + %multmp1 = fmul double 2.000000e+00, %a + %multmp2 = fmul double %multmp1, %b + %addtmp = fadd double %multmp, %multmp2 + %multmp3 = fmul double %b, %b + %addtmp4 = fadd double %addtmp, %multmp3 + ret double %addtmp4 + } + + define double @bar(double %a) { + entry: + %calltmp = call double @foo(double %a, double 4.000000e+00) + %calltmp1 = call double @bar(double 3.133700e+04) + %addtmp = fadd double %calltmp, %calltmp1 + ret double %addtmp + } + + declare double @cos(double) + + define double @1() { + entry: + %calltmp = call double @cos(double 1.234000e+00) + ret double %calltmp + } + +When you quit the current demo, it dumps out the IR for the entire +module generated. Here you can see the big picture with all the +functions referencing each other. + +This wraps up the third chapter of the Kaleidoscope tutorial. Up next, +we'll describe how to `add JIT codegen and optimizer +support `_ to this so we can actually start running +code! + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the LLVM code generator. Because this uses the LLVM libraries, we need +to link them in. To do this, we use the +`llvm-config `_ tool to inform +our makefile/command line about which options to use: + +.. code-block:: bash + + # Compile + clang++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy + # Run + ./toy + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter3/toy.cpp + :language: c++ + +`Next: Adding JIT and Optimizer Support `_ + diff --git a/docs/tutorial/LangImpl4.rst b/docs/tutorial/LangImpl4.rst new file mode 100644 index 00000000..44e0cc15 --- /dev/null +++ b/docs/tutorial/LangImpl4.rst @@ -0,0 +1,445 @@ +============================================== +Kaleidoscope: Adding JIT and Optimizer Support +============================================== + +.. contents:: + :local: + +Chapter 4 Introduction +====================== + +Welcome to Chapter 4 of the "`Implementing a language with +LLVM `_" tutorial. Chapters 1-3 described the implementation +of a simple language and added support for generating LLVM IR. This +chapter describes two new techniques: adding optimizer support to your +language, and adding JIT compiler support. These additions will +demonstrate how to get nice, efficient code for the Kaleidoscope +language. + +Trivial Constant Folding +======================== + +Our demonstration for Chapter 3 is elegant and easy to extend. +Unfortunately, it does not produce wonderful code. The IRBuilder, +however, does give us obvious optimizations when compiling simple code: + +:: + + ready> def test(x) 1+2+x; + Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double 3.000000e+00, %x + ret double %addtmp + } + +This code is not a literal transcription of the AST built by parsing the +input. That would be: + +:: + + ready> def test(x) 1+2+x; + Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double 2.000000e+00, 1.000000e+00 + %addtmp1 = fadd double %addtmp, %x + ret double %addtmp1 + } + +Constant folding, as seen above, in particular, is a very common and +very important optimization: so much so that many language implementors +implement constant folding support in their AST representation. + +With LLVM, you don't need this support in the AST. Since all calls to +build LLVM IR go through the LLVM IR builder, the builder itself checked +to see if there was a constant folding opportunity when you call it. If +so, it just does the constant fold and return the constant instead of +creating an instruction. + +Well, that was easy :). In practice, we recommend always using +``IRBuilder`` when generating code like this. It has no "syntactic +overhead" for its use (you don't have to uglify your compiler with +constant checks everywhere) and it can dramatically reduce the amount of +LLVM IR that is generated in some cases (particular for languages with a +macro preprocessor or that use a lot of constants). + +On the other hand, the ``IRBuilder`` is limited by the fact that it does +all of its analysis inline with the code as it is built. If you take a +slightly more complex example: + +:: + + ready> def test(x) (1+2+x)*(x+(1+2)); + ready> Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double 3.000000e+00, %x + %addtmp1 = fadd double %x, 3.000000e+00 + %multmp = fmul double %addtmp, %addtmp1 + ret double %multmp + } + +In this case, the LHS and RHS of the multiplication are the same value. +We'd really like to see this generate "``tmp = x+3; result = tmp*tmp;``" +instead of computing "``x+3``" twice. + +Unfortunately, no amount of local analysis will be able to detect and +correct this. This requires two transformations: reassociation of +expressions (to make the add's lexically identical) and Common +Subexpression Elimination (CSE) to delete the redundant add instruction. +Fortunately, LLVM provides a broad range of optimizations that you can +use, in the form of "passes". + +LLVM Optimization Passes +======================== + +LLVM provides many optimization passes, which do many different sorts of +things and have different tradeoffs. Unlike other systems, LLVM doesn't +hold to the mistaken notion that one set of optimizations is right for +all languages and for all situations. LLVM allows a compiler implementor +to make complete decisions about what optimizations to use, in which +order, and in what situation. + +As a concrete example, LLVM supports both "whole module" passes, which +look across as large of body of code as they can (often a whole file, +but if run at link time, this can be a substantial portion of the whole +program). It also supports and includes "per-function" passes which just +operate on a single function at a time, without looking at other +functions. For more information on passes and how they are run, see the +`How to Write a Pass <../WritingAnLLVMPass.html>`_ document and the +`List of LLVM Passes <../Passes.html>`_. + +For Kaleidoscope, we are currently generating functions on the fly, one +at a time, as the user types them in. We aren't shooting for the +ultimate optimization experience in this setting, but we also want to +catch the easy and quick stuff where possible. As such, we will choose +to run a few per-function optimizations as the user types the function +in. If we wanted to make a "static Kaleidoscope compiler", we would use +exactly the code we have now, except that we would defer running the +optimizer until the entire file has been parsed. + +In order to get per-function optimizations going, we need to set up a +`FunctionPassManager <../WritingAnLLVMPass.html#passmanager>`_ to hold +and organize the LLVM optimizations that we want to run. Once we have +that, we can add a set of optimizations to run. The code looks like +this: + +.. code-block:: c++ + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + +This code defines a ``FunctionPassManager``, "``OurFPM``". It requires a +pointer to the ``Module`` to construct itself. Once it is set up, we use +a series of "add" calls to add a bunch of LLVM passes. The first pass is +basically boilerplate, it adds a pass so that later optimizations know +how the data structures in the program are laid out. The +"``TheExecutionEngine``" variable is related to the JIT, which we will +get to in the next section. + +In this case, we choose to add 4 optimization passes. The passes we +chose here are a pretty standard set of "cleanup" optimizations that are +useful for a wide variety of code. I won't delve into what they do but, +believe me, they are a good starting place :). + +Once the PassManager is set up, we need to make use of it. We do this by +running it after our newly created function is constructed (in +``FunctionAST::Codegen``), but before it is returned to the client: + +.. code-block:: c++ + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + +As you can see, this is pretty straightforward. The +``FunctionPassManager`` optimizes and updates the LLVM Function\* in +place, improving (hopefully) its body. With this in place, we can try +our test above again: + +:: + + ready> def test(x) (1+2+x)*(x+(1+2)); + ready> Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double %x, 3.000000e+00 + %multmp = fmul double %addtmp, %addtmp + ret double %multmp + } + +As expected, we now get our nicely optimized code, saving a floating +point add instruction from every execution of this function. + +LLVM provides a wide variety of optimizations that can be used in +certain circumstances. Some `documentation about the various +passes <../Passes.html>`_ is available, but it isn't very complete. +Another good source of ideas can come from looking at the passes that +``Clang`` runs to get started. The "``opt``" tool allows you to +experiment with passes from the command line, so you can see if they do +anything. + +Now that we have reasonable code coming out of our front-end, lets talk +about executing it! + +Adding a JIT Compiler +===================== + +Code that is available in LLVM IR can have a wide variety of tools +applied to it. For example, you can run optimizations on it (as we did +above), you can dump it out in textual or binary forms, you can compile +the code to an assembly file (.s) for some target, or you can JIT +compile it. The nice thing about the LLVM IR representation is that it +is the "common currency" between many different parts of the compiler. + +In this section, we'll add JIT compiler support to our interpreter. The +basic idea that we want for Kaleidoscope is to have the user enter +function bodies as they do now, but immediately evaluate the top-level +expressions they type in. For example, if they type in "1 + 2;", we +should evaluate and print out 3. If they define a function, they should +be able to call it from the command line. + +In order to do this, we first declare and initialize the JIT. This is +done by adding a global variable and a call in ``main``: + +.. code-block:: c++ + + static ExecutionEngine *TheExecutionEngine; + ... + int main() { + .. + // Create the JIT. This takes ownership of the module. + TheExecutionEngine = EngineBuilder(TheModule).create(); + .. + } + +This creates an abstract "Execution Engine" which can be either a JIT +compiler or the LLVM interpreter. LLVM will automatically pick a JIT +compiler for you if one is available for your platform, otherwise it +will fall back to the interpreter. + +Once the ``ExecutionEngine`` is created, the JIT is ready to be used. +There are a variety of APIs that are useful, but the simplest one is the +"``getPointerToFunction(F)``" method. This method JIT compiles the +specified LLVM Function and returns a function pointer to the generated +machine code. In our case, this means that we can change the code that +parses a top-level expression to look like this: + +.. code-block:: c++ + + static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + LF->dump(); // Dump the function for exposition purposes. + + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + +Recall that we compile top-level expressions into a self-contained LLVM +function that takes no arguments and returns the computed double. +Because the LLVM JIT compiler matches the native platform ABI, this +means that you can just cast the result pointer to a function pointer of +that type and call it directly. This means, there is no difference +between JIT compiled code and native machine code that is statically +linked into your application. + +With just these two changes, lets see how Kaleidoscope works now! + +:: + + ready> 4+5; + Read top-level expression: + define double @0() { + entry: + ret double 9.000000e+00 + } + + Evaluated to 9.000000 + +Well this looks like it is basically working. The dump of the function +shows the "no argument function that always returns double" that we +synthesize for each top-level expression that is typed in. This +demonstrates very basic functionality, but can we do more? + +:: + + ready> def testfunc(x y) x + y*2; + Read function definition: + define double @testfunc(double %x, double %y) { + entry: + %multmp = fmul double %y, 2.000000e+00 + %addtmp = fadd double %multmp, %x + ret double %addtmp + } + + ready> testfunc(4, 10); + Read top-level expression: + define double @1() { + entry: + %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01) + ret double %calltmp + } + + Evaluated to 24.000000 + +This illustrates that we can now call user code, but there is something +a bit subtle going on here. Note that we only invoke the JIT on the +anonymous functions that *call testfunc*, but we never invoked it on +*testfunc* itself. What actually happened here is that the JIT scanned +for all non-JIT'd functions transitively called from the anonymous +function and compiled all of them before returning from +``getPointerToFunction()``. + +The JIT provides a number of other more advanced interfaces for things +like freeing allocated machine code, rejit'ing functions to update them, +etc. However, even with this simple code, we get some surprisingly +powerful capabilities - check this out (I removed the dump of the +anonymous functions, you should get the idea by now :) : + +:: + + ready> extern sin(x); + Read extern: + declare double @sin(double) + + ready> extern cos(x); + Read extern: + declare double @cos(double) + + ready> sin(1.0); + Read top-level expression: + define double @2() { + entry: + ret double 0x3FEAED548F090CEE + } + + Evaluated to 0.841471 + + ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x); + Read function definition: + define double @foo(double %x) { + entry: + %calltmp = call double @sin(double %x) + %multmp = fmul double %calltmp, %calltmp + %calltmp2 = call double @cos(double %x) + %multmp4 = fmul double %calltmp2, %calltmp2 + %addtmp = fadd double %multmp, %multmp4 + ret double %addtmp + } + + ready> foo(4.0); + Read top-level expression: + define double @3() { + entry: + %calltmp = call double @foo(double 4.000000e+00) + ret double %calltmp + } + + Evaluated to 1.000000 + +Whoa, how does the JIT know about sin and cos? The answer is +surprisingly simple: in this example, the JIT started execution of a +function and got to a function call. It realized that the function was +not yet JIT compiled and invoked the standard set of routines to resolve +the function. In this case, there is no body defined for the function, +so the JIT ended up calling "``dlsym("sin")``" on the Kaleidoscope +process itself. Since "``sin``" is defined within the JIT's address +space, it simply patches up calls in the module to call the libm version +of ``sin`` directly. + +The LLVM JIT provides a number of interfaces (look in the +``ExecutionEngine.h`` file) for controlling how unknown functions get +resolved. It allows you to establish explicit mappings between IR +objects and addresses (useful for LLVM global variables that you want to +map to static tables, for example), allows you to dynamically decide on +the fly based on the function name, and even allows you to have the JIT +compile functions lazily the first time they're called. + +One interesting application of this is that we can now extend the +language by writing arbitrary C++ code to implement operations. For +example, if we add: + +.. code-block:: c++ + + /// putchard - putchar that takes a double and returns 0. + extern "C" + double putchard(double X) { + putchar((char)X); + return 0; + } + +Now we can produce simple output to the console by using things like: +"``extern putchard(x); putchard(120);``", which prints a lowercase 'x' +on the console (120 is the ASCII code for 'x'). Similar code could be +used to implement file I/O, console input, and many other capabilities +in Kaleidoscope. + +This completes the JIT and optimizer chapter of the Kaleidoscope +tutorial. At this point, we can compile a non-Turing-complete +programming language, optimize and JIT compile it in a user-driven way. +Next up we'll look into `extending the language with control flow +constructs `_, tackling some interesting LLVM IR issues +along the way. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the LLVM JIT and optimizer. To build this example, use: + +.. code-block:: bash + + # Compile + clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + # Run + ./toy + +If you are compiling this on Linux, make sure to add the "-rdynamic" +option as well. This makes sure that the external functions are resolved +properly at runtime. + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter4/toy.cpp + :language: c++ + +`Next: Extending the language: control flow `_ + diff --git a/docs/tutorial/LangImpl5-cfg.png b/docs/tutorial/LangImpl5-cfg.png new file mode 100644 index 00000000..cdba92ff Binary files /dev/null and b/docs/tutorial/LangImpl5-cfg.png differ diff --git a/docs/tutorial/LangImpl5.rst b/docs/tutorial/LangImpl5.rst new file mode 100644 index 00000000..ed5b652f --- /dev/null +++ b/docs/tutorial/LangImpl5.rst @@ -0,0 +1,749 @@ +================================================== +Kaleidoscope: Extending the Language: Control Flow +================================================== + +.. contents:: + :local: + +Chapter 5 Introduction +====================== + +Welcome to Chapter 5 of the "`Implementing a language with +LLVM `_" tutorial. Parts 1-4 described the implementation of +the simple Kaleidoscope language and included support for generating +LLVM IR, followed by optimizations and a JIT compiler. Unfortunately, as +presented, Kaleidoscope is mostly useless: it has no control flow other +than call and return. This means that you can't have conditional +branches in the code, significantly limiting its power. In this episode +of "build that compiler", we'll extend Kaleidoscope to have an +if/then/else expression plus a simple 'for' loop. + +If/Then/Else +============ + +Extending Kaleidoscope to support if/then/else is quite straightforward. +It basically requires adding support for this "new" concept to the +lexer, parser, AST, and LLVM code emitter. This example is nice, because +it shows how easy it is to "grow" a language over time, incrementally +extending it as new ideas are discovered. + +Before we get going on "how" we add this extension, lets talk about +"what" we want. The basic idea is that we want to be able to write this +sort of thing: + +:: + + def fib(x) + if x < 3 then + 1 + else + fib(x-1)+fib(x-2); + +In Kaleidoscope, every construct is an expression: there are no +statements. As such, the if/then/else expression needs to return a value +like any other. Since we're using a mostly functional form, we'll have +it evaluate its conditional, then return the 'then' or 'else' value +based on how the condition was resolved. This is very similar to the C +"?:" expression. + +The semantics of the if/then/else expression is that it evaluates the +condition to a boolean equality value: 0.0 is considered to be false and +everything else is considered to be true. If the condition is true, the +first subexpression is evaluated and returned, if the condition is +false, the second subexpression is evaluated and returned. Since +Kaleidoscope allows side-effects, this behavior is important to nail +down. + +Now that we know what we "want", lets break this down into its +constituent pieces. + +Lexer Extensions for If/Then/Else +--------------------------------- + +The lexer extensions are straightforward. First we add new enum values +for the relevant tokens: + +.. code-block:: c++ + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + +Once we have that, we recognize the new keywords in the lexer. This is +pretty simple stuff: + +.. code-block:: c++ + + ... + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + return tok_identifier; + +AST Extensions for If/Then/Else +------------------------------- + +To represent the new expression we add a new AST node for it: + +.. code-block:: c++ + + /// IfExprAST - Expression class for if/then/else. + class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; + public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); + }; + +The AST node just has pointers to the various subexpressions. + +Parser Extensions for If/Then/Else +---------------------------------- + +Now that we have the relevant tokens coming from the lexer and we have +the AST node to build, our parsing logic is relatively straightforward. +First we define a new parsing function: + +.. code-block:: c++ + + /// ifexpr ::= 'if' expression 'then' expression 'else' expression + static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); + } + +Next we hook it up as a primary expression: + +.. code-block:: c++ + + static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + } + } + +LLVM IR for If/Then/Else +------------------------ + +Now that we have it parsing and building the AST, the final piece is +adding LLVM code generation support. This is the most interesting part +of the if/then/else example, because this is where it starts to +introduce new concepts. All of the code above has been thoroughly +described in previous chapters. + +To motivate the code we want to produce, lets take a look at a simple +example. Consider: + +:: + + extern foo(); + extern bar(); + def baz(x) if x then foo() else bar(); + +If you disable optimizations, the code you'll (soon) get from +Kaleidoscope looks like this: + +.. code-block:: llvm + + declare double @foo() + + declare double @bar() + + define double @baz(double %x) { + entry: + %ifcond = fcmp one double %x, 0.000000e+00 + br i1 %ifcond, label %then, label %else + + then: ; preds = %entry + %calltmp = call double @foo() + br label %ifcont + + else: ; preds = %entry + %calltmp1 = call double @bar() + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ] + ret double %iftmp + } + +To visualize the control flow graph, you can use a nifty feature of the +LLVM '`opt `_' tool. If you put this LLVM +IR into "t.ll" and run "``llvm-as < t.ll | opt -analyze -view-cfg``", `a +window will pop up <../ProgrammersManual.html#ViewGraph>`_ and you'll +see this graph: + +.. figure:: LangImpl5-cfg.png + :align: center + :alt: Example CFG + + Example CFG + +Another way to get this is to call "``F->viewCFG()``" or +"``F->viewCFGOnly()``" (where F is a "``Function*``") either by +inserting actual calls into the code and recompiling or by calling these +in the debugger. LLVM has many nice features for visualizing various +graphs. + +Getting back to the generated code, it is fairly simple: the entry block +evaluates the conditional expression ("x" in our case here) and compares +the result to 0.0 with the "``fcmp one``" instruction ('one' is "Ordered +and Not Equal"). Based on the result of this expression, the code jumps +to either the "then" or "else" blocks, which contain the expressions for +the true/false cases. + +Once the then/else blocks are finished executing, they both branch back +to the 'ifcont' block to execute the code that happens after the +if/then/else. In this case the only thing left to do is to return to the +caller of the function. The question then becomes: how does the code +know which expression to return? + +The answer to this question involves an important SSA operation: the +`Phi +operation `_. +If you're not familiar with SSA, `the wikipedia +article `_ +is a good introduction and there are various other introductions to it +available on your favorite search engine. The short version is that +"execution" of the Phi operation requires "remembering" which block +control came from. The Phi operation takes on the value corresponding to +the input control block. In this case, if control comes in from the +"then" block, it gets the value of "calltmp". If control comes from the +"else" block, it gets the value of "calltmp1". + +At this point, you are probably starting to think "Oh no! This means my +simple and elegant front-end will have to start generating SSA form in +order to use LLVM!". Fortunately, this is not the case, and we strongly +advise *not* implementing an SSA construction algorithm in your +front-end unless there is an amazingly good reason to do so. In +practice, there are two sorts of values that float around in code +written for your average imperative programming language that might need +Phi nodes: + +#. Code that involves user variables: ``x = 1; x = x + 1;`` +#. Values that are implicit in the structure of your AST, such as the + Phi node in this case. + +In `Chapter 7 `_ of this tutorial ("mutable variables"), +we'll talk about #1 in depth. For now, just believe me that you don't +need SSA construction to handle this case. For #2, you have the choice +of using the techniques that we will describe for #1, or you can insert +Phi nodes directly, if convenient. In this case, it is really really +easy to generate the Phi node, so we choose to do it directly. + +Okay, enough of the motivation and overview, lets generate code! + +Code Generation for If/Then/Else +-------------------------------- + +In order to generate code for this, we implement the ``Codegen`` method +for ``IfExprAST``: + +.. code-block:: c++ + + Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + +This code is straightforward and similar to what we saw before. We emit +the expression for the condition, then compare that value to zero to get +a truth value as a 1-bit (bool) value. + +.. code-block:: c++ + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + +This code creates the basic blocks that are related to the if/then/else +statement, and correspond directly to the blocks in the example above. +The first line gets the current Function object that is being built. It +gets this by asking the builder for the current BasicBlock, and asking +that block for its "parent" (the function it is currently embedded +into). + +Once it has that, it creates three blocks. Note that it passes +"TheFunction" into the constructor for the "then" block. This causes the +constructor to automatically insert the new block into the end of the +specified function. The other two blocks are created, but aren't yet +inserted into the function. + +Once the blocks are created, we can emit the conditional branch that +chooses between them. Note that creating new blocks does not implicitly +affect the IRBuilder, so it is still inserting into the block that the +condition went into. Also note that it is creating a branch to the +"then" block and the "else" block, even though the "else" block isn't +inserted into the function yet. This is all ok: it is the standard way +that LLVM supports forward references. + +.. code-block:: c++ + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + +After the conditional branch is inserted, we move the builder to start +inserting into the "then" block. Strictly speaking, this call moves the +insertion point to be at the end of the specified block. However, since +the "then" block is empty, it also starts out by inserting at the +beginning of the block. :) + +Once the insertion point is set, we recursively codegen the "then" +expression from the AST. To finish off the "then" block, we create an +unconditional branch to the merge block. One interesting (and very +important) aspect of the LLVM IR is that it `requires all basic blocks +to be "terminated" <../LangRef.html#functionstructure>`_ with a `control +flow instruction <../LangRef.html#terminators>`_ such as return or +branch. This means that all control flow, *including fall throughs* must +be made explicit in the LLVM IR. If you violate this rule, the verifier +will emit an error. + +The final line here is quite subtle, but is very important. The basic +issue is that when we create the Phi node in the merge block, we need to +set up the block/value pairs that indicate how the Phi will work. +Importantly, the Phi node expects to have an entry for each predecessor +of the block in the CFG. Why then, are we getting the current block when +we just set it to ThenBB 5 lines above? The problem is that the "Then" +expression may actually itself change the block that the Builder is +emitting into if, for example, it contains a nested "if/then/else" +expression. Because calling Codegen recursively could arbitrarily change +the notion of the current block, we are required to get an up-to-date +value for code that will set up the Phi node. + +.. code-block:: c++ + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + +Code generation for the 'else' block is basically identical to codegen +for the 'then' block. The only significant difference is the first line, +which adds the 'else' block to the function. Recall previously that the +'else' block was created, but not added to the function. Now that the +'then' and 'else' blocks are emitted, we can finish up with the merge +code: + +.. code-block:: c++ + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; + } + +The first two lines here are now familiar: the first adds the "merge" +block to the Function object (it was previously floating, like the else +block above). The second block changes the insertion point so that newly +created code will go into the "merge" block. Once that is done, we need +to create the PHI node and set up the block/value pairs for the PHI. + +Finally, the CodeGen function returns the phi node as the value computed +by the if/then/else expression. In our example above, this returned +value will feed into the code for the top-level function, which will +create the return instruction. + +Overall, we now have the ability to execute conditional code in +Kaleidoscope. With this extension, Kaleidoscope is a fairly complete +language that can calculate a wide variety of numeric functions. Next up +we'll add another useful expression that is familiar from non-functional +languages... + +'for' Loop Expression +===================== + +Now that we know how to add basic control flow constructs to the +language, we have the tools to add more powerful things. Lets add +something more aggressive, a 'for' expression: + +:: + + extern putchard(char) + def printstar(n) + for i = 1, i < n, 1.0 in + putchard(42); # ascii 42 = '*' + + # print 100 '*' characters + printstar(100); + +This expression defines a new variable ("i" in this case) which iterates +from a starting value, while the condition ("i < n" in this case) is +true, incrementing by an optional step value ("1.0" in this case). If +the step value is omitted, it defaults to 1.0. While the loop is true, +it executes its body expression. Because we don't have anything better +to return, we'll just define the loop as always returning 0.0. In the +future when we have mutable variables, it will get more useful. + +As before, lets talk about the changes that we need to Kaleidoscope to +support this. + +Lexer Extensions for the 'for' Loop +----------------------------------- + +The lexer extensions are the same sort of thing as for if/then/else: + +.. code-block:: c++ + + ... in enum Token ... + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10 + + ... in gettok ... + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + return tok_identifier; + +AST Extensions for the 'for' Loop +--------------------------------- + +The AST node is just as simple. It basically boils down to capturing the +variable name and the constituent expressions in the node. + +.. code-block:: c++ + + /// ForExprAST - Expression class for for/in. + class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; + public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); + }; + +Parser Extensions for the 'for' Loop +------------------------------------ + +The parser code is also fairly standard. The only interesting thing here +is handling of the optional step value. The parser code handles it by +checking to see if the second comma is present. If not, it sets the step +value to null in the AST node: + +.. code-block:: c++ + + /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression + static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); + } + +LLVM IR for the 'for' Loop +-------------------------- + +Now we get to the good part: the LLVM IR we want to generate for this +thing. With the simple example above, we get this LLVM IR (note that +this dump is generated with optimizations disabled for clarity): + +.. code-block:: llvm + + declare double @putchard(double) + + define double @printstar(double %n) { + entry: + ; initial value = 1.0 (inlined into phi) + br label %loop + + loop: ; preds = %loop, %entry + %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ] + ; body + %calltmp = call double @putchard(double 4.200000e+01) + ; increment + %nextvar = fadd double %i, 1.000000e+00 + + ; termination test + %cmptmp = fcmp ult double %i, %n + %booltmp = uitofp i1 %cmptmp to double + %loopcond = fcmp one double %booltmp, 0.000000e+00 + br i1 %loopcond, label %loop, label %afterloop + + afterloop: ; preds = %loop + ; loop always returns 0.0 + ret double 0.000000e+00 + } + +This loop contains all the same constructs we saw before: a phi node, +several expressions, and some basic blocks. Lets see how this fits +together. + +Code Generation for the 'for' Loop +---------------------------------- + +The first part of Codegen is very simple: we just output the start +expression for the loop value: + +.. code-block:: c++ + + Value *ForExprAST::Codegen() { + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + +With this out of the way, the next step is to set up the LLVM basic +block for the start of the loop body. In the case above, the whole loop +body is one block, but remember that the body code itself could consist +of multiple blocks (e.g. if it contains an if/then/else or a for/in +expression). + +.. code-block:: c++ + + // Make the new basic block for the loop header, inserting after current + // block. + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + BasicBlock *PreheaderBB = Builder.GetInsertBlock(); + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + +This code is similar to what we saw for if/then/else. Because we will +need it to create the Phi node, we remember the block that falls through +into the loop. Once we have that, we create the actual block that starts +the loop and create an unconditional branch for the fall-through between +the two blocks. + +.. code-block:: c++ + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Start the PHI node with an entry for Start. + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); + Variable->addIncoming(StartVal, PreheaderBB); + +Now that the "preheader" for the loop is set up, we switch to emitting +code for the loop body. To begin with, we move the insertion point and +create the PHI node for the loop induction variable. Since we already +know the incoming value for the starting value, we add it to the Phi +node. Note that the Phi will eventually get a second value for the +backedge, but we can't set it up yet (because it doesn't exist!). + +.. code-block:: c++ + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + Value *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Variable; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + +Now the code starts to get more interesting. Our 'for' loop introduces a +new variable to the symbol table. This means that our symbol table can +now contain either function arguments or loop variables. To handle this, +before we codegen the body of the loop, we add the loop variable as the +current value for its name. Note that it is possible that there is a +variable of the same name in the outer scope. It would be easy to make +this an error (emit an error and return null if there is already an +entry for VarName) but we choose to allow shadowing of variables. In +order to handle this correctly, we remember the Value that we are +potentially shadowing in ``OldVal`` (which will be null if there is no +shadowed variable). + +Once the loop variable is set into the symbol table, the code +recursively codegen's the body. This allows the body to use the loop +variable: any references to it will naturally find it in the symbol +table. + +.. code-block:: c++ + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); + +Now that the body is emitted, we compute the next value of the iteration +variable by adding the step value, or 1.0 if it isn't present. +'``NextVar``' will be the value of the loop variable on the next +iteration of the loop. + +.. code-block:: c++ + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + +Finally, we evaluate the exit value of the loop, to determine whether +the loop should exit. This mirrors the condition evaluation for the +if/then/else statement. + +.. code-block:: c++ + + // Create the "after loop" block and insert it. + BasicBlock *LoopEndBB = Builder.GetInsertBlock(); + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + +With the code for the body of the loop complete, we just need to finish +up the control flow for it. This code remembers the end block (for the +phi node), then creates the block for the loop exit ("afterloop"). Based +on the value of the exit condition, it creates a conditional branch that +chooses between executing the loop again and exiting the loop. Any +future code is emitted in the "afterloop" block, so it sets the +insertion position to it. + +.. code-block:: c++ + + // Add a new entry to the PHI node for the backedge. + Variable->addIncoming(NextVar, LoopEndBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); + } + +The final code handles various cleanups: now that we have the "NextVar" +value, we can add the incoming value to the loop PHI node. After that, +we remove the loop variable from the symbol table, so that it isn't in +scope after the for loop. Finally, code generation of the for loop +always returns 0.0, so that is what we return from +``ForExprAST::Codegen``. + +With this, we conclude the "adding control flow to Kaleidoscope" chapter +of the tutorial. In this chapter we added two control flow constructs, +and used them to motivate a couple of aspects of the LLVM IR that are +important for front-end implementors to know. In the next chapter of our +saga, we will get a bit crazier and add `user-defined +operators `_ to our poor innocent language. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the if/then/else and for expressions.. To build this example, use: + +.. code-block:: bash + + # Compile + clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + # Run + ./toy + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter5/toy.cpp + :language: c++ + +`Next: Extending the language: user-defined operators `_ + diff --git a/docs/tutorial/LangImpl6.rst b/docs/tutorial/LangImpl6.rst new file mode 100644 index 00000000..42839fbd --- /dev/null +++ b/docs/tutorial/LangImpl6.rst @@ -0,0 +1,750 @@ +============================================================ +Kaleidoscope: Extending the Language: User-defined Operators +============================================================ + +.. contents:: + :local: + +Chapter 6 Introduction +====================== + +Welcome to Chapter 6 of the "`Implementing a language with +LLVM `_" tutorial. At this point in our tutorial, we now +have a fully functional language that is fairly minimal, but also +useful. There is still one big problem with it, however. Our language +doesn't have many useful operators (like division, logical negation, or +even any comparisons besides less-than). + +This chapter of the tutorial takes a wild digression into adding +user-defined operators to the simple and beautiful Kaleidoscope +language. This digression now gives us a simple and ugly language in +some ways, but also a powerful one at the same time. One of the great +things about creating your own language is that you get to decide what +is good or bad. In this tutorial we'll assume that it is okay to use +this as a way to show some interesting parsing techniques. + +At the end of this tutorial, we'll run through an example Kaleidoscope +application that `renders the Mandelbrot set <#example>`_. This gives an +example of what you can build with Kaleidoscope and its feature set. + +User-defined Operators: the Idea +================================ + +The "operator overloading" that we will add to Kaleidoscope is more +general than languages like C++. In C++, you are only allowed to +redefine existing operators: you can't programatically change the +grammar, introduce new operators, change precedence levels, etc. In this +chapter, we will add this capability to Kaleidoscope, which will let the +user round out the set of operators that are supported. + +The point of going into user-defined operators in a tutorial like this +is to show the power and flexibility of using a hand-written parser. +Thus far, the parser we have been implementing uses recursive descent +for most parts of the grammar and operator precedence parsing for the +expressions. See `Chapter 2 `_ for details. Without +using operator precedence parsing, it would be very difficult to allow +the programmer to introduce new operators into the grammar: the grammar +is dynamically extensible as the JIT runs. + +The two specific features we'll add are programmable unary operators +(right now, Kaleidoscope has no unary operators at all) as well as +binary operators. An example of this is: + +:: + + # Logical unary not. + def unary!(v) + if v then + 0 + else + 1; + + # Define > with the same precedence as <. + def binary> 10 (LHS RHS) + RHS < LHS; + + # Binary "logical or", (note that it does not "short circuit") + def binary| 5 (LHS RHS) + if LHS then + 1 + else if RHS then + 1 + else + 0; + + # Define = with slightly lower precedence than relationals. + def binary= 9 (LHS RHS) + !(LHS < RHS | LHS > RHS); + +Many languages aspire to being able to implement their standard runtime +library in the language itself. In Kaleidoscope, we can implement +significant parts of the language in the library! + +We will break down implementation of these features into two parts: +implementing support for user-defined binary operators and adding unary +operators. + +User-defined Binary Operators +============================= + +Adding support for user-defined binary operators is pretty simple with +our current framework. We'll first add support for the unary/binary +keywords: + +.. code-block:: c++ + + enum Token { + ... + // operators + tok_binary = -11, tok_unary = -12 + }; + ... + static int gettok() { + ... + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + return tok_identifier; + +This just adds lexer support for the unary and binary keywords, like we +did in `previous chapters `_. One nice thing +about our current AST, is that we represent binary operators with full +generalisation by using their ASCII code as the opcode. For our extended +operators, we'll use this same representation, so we don't need any new +AST or parser support. + +On the other hand, we have to be able to represent the definitions of +these new operators, in the "def binary\| 5" part of the function +definition. In our grammar so far, the "name" for the function +definition is parsed as the "prototype" production and into the +``PrototypeAST`` AST node. To represent our new user-defined operators +as prototypes, we have to extend the ``PrototypeAST`` AST node like +this: + +.. code-block:: c++ + + /// PrototypeAST - This class represents the "prototype" for a function, + /// which captures its argument names as well as if it is an operator. + class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. + public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + }; + +Basically, in addition to knowing a name for the prototype, we now keep +track of whether it was an operator, and if it was, what precedence +level the operator is at. The precedence is only used for binary +operators (as you'll see below, it just doesn't apply for unary +operators). Now that we have a way to represent the prototype for a +user-defined operator, we need to parse it: + +.. code-block:: c++ + + /// prototype + /// ::= id '(' id* ')' + /// ::= binary LETTER number? (id, id) + static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); + } + +This is all fairly straightforward parsing code, and we have already +seen a lot of similar code in the past. One interesting part about the +code above is the couple lines that set up ``FnName`` for binary +operators. This builds names like "binary@" for a newly defined "@" +operator. This then takes advantage of the fact that symbol names in the +LLVM symbol table are allowed to have any character in them, including +embedded nul characters. + +The next interesting thing to add, is codegen support for these binary +operators. Given our current structure, this is a simple addition of a +default case for our existing binary operator node: + +.. code-block:: c++ + + Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[2] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); + } + +As you can see above, the new code is actually really simple. It just +does a lookup for the appropriate operator in the symbol table and +generates a function call to it. Since user-defined operators are just +built as normal functions (because the "prototype" boils down to a +function with the right name) everything falls into place. + +The final piece of code we are missing, is a bit of top-level magic: + +.. code-block:: c++ + + Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + ... + +Basically, before codegening a function, if it is a user-defined +operator, we register it in the precedence table. This allows the binary +operator parsing logic we already have in place to handle it. Since we +are working on a fully-general operator precedence parser, this is all +we need to do to "extend the grammar". + +Now we have useful user-defined binary operators. This builds a lot on +the previous framework we built for other operators. Adding unary +operators is a bit more challenging, because we don't have any framework +for it yet - lets see what it takes. + +User-defined Unary Operators +============================ + +Since we don't currently support unary operators in the Kaleidoscope +language, we'll need to add everything to support them. Above, we added +simple support for the 'unary' keyword to the lexer. In addition to +that, we need an AST node: + +.. code-block:: c++ + + /// UnaryExprAST - Expression class for a unary operator. + class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; + public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); + }; + +This AST node is very simple and obvious by now. It directly mirrors the +binary operator AST node, except that it only has one child. With this, +we need to add the parsing logic. Parsing a unary operator is pretty +simple: we'll add a new function to do it: + +.. code-block:: c++ + + /// unary + /// ::= primary + /// ::= '!' unary + static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; + } + +The grammar we add is pretty straightforward here. If we see a unary +operator when parsing a primary operator, we eat the operator as a +prefix and parse the remaining piece as another unary operator. This +allows us to handle multiple unary operators (e.g. "!!x"). Note that +unary operators can't have ambiguous parses like binary operators can, +so there is no need for precedence information. + +The problem with this function, is that we need to call ParseUnary from +somewhere. To do this, we change previous callers of ParsePrimary to +call ParseUnary instead: + +.. code-block:: c++ + + /// binoprhs + /// ::= ('+' unary)* + static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + ... + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + ... + } + /// expression + /// ::= unary binoprhs + /// + static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); + } + +With these two simple changes, we are now able to parse unary operators +and build the AST for them. Next up, we need to add parser support for +prototypes, to parse the unary operator prototype. We extend the binary +operator code above with: + +.. code-block:: c++ + + /// prototype + /// ::= id '(' id* ')' + /// ::= binary LETTER number? (id, id) + /// ::= unary LETTER (id) + static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + ... + +As with binary operators, we name unary operators with a name that +includes the operator character. This assists us at code generation +time. Speaking of, the final piece we need to add is codegen support for +unary operators. It looks like this: + +.. code-block:: c++ + + Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); + } + +This code is similar to, but simpler than, the code for binary +operators. It is simpler primarily because it doesn't need to handle any +predefined operators. + +Kicking the Tires +================= + +It is somewhat hard to believe, but with a few simple extensions we've +covered in the last chapters, we have grown a real-ish language. With +this, we can do a lot of interesting things, including I/O, math, and a +bunch of other things. For example, we can now add a nice sequencing +operator (printd is defined to print out the specified value and a +newline): + +:: + + ready> extern printd(x); + Read extern: + declare double @printd(double) + + ready> def binary : 1 (x y) 0; # Low-precedence operator that ignores operands. + .. + ready> printd(123) : printd(456) : printd(789); + 123.000000 + 456.000000 + 789.000000 + Evaluated to 0.000000 + +We can also define a bunch of other "primitive" operations, such as: + +:: + + # Logical unary not. + def unary!(v) + if v then + 0 + else + 1; + + # Unary negate. + def unary-(v) + 0-v; + + # Define > with the same precedence as <. + def binary> 10 (LHS RHS) + RHS < LHS; + + # Binary logical or, which does not short circuit. + def binary| 5 (LHS RHS) + if LHS then + 1 + else if RHS then + 1 + else + 0; + + # Binary logical and, which does not short circuit. + def binary& 6 (LHS RHS) + if !LHS then + 0 + else + !!RHS; + + # Define = with slightly lower precedence than relationals. + def binary = 9 (LHS RHS) + !(LHS < RHS | LHS > RHS); + + # Define ':' for sequencing: as a low-precedence operator that ignores operands + # and just returns the RHS. + def binary : 1 (x y) y; + +Given the previous if/then/else support, we can also define interesting +functions for I/O. For example, the following prints out a character +whose "density" reflects the value passed in: the lower the value, the +denser the character: + +:: + + ready> + + extern putchard(char) + def printdensity(d) + if d > 8 then + putchard(32) # ' ' + else if d > 4 then + putchard(46) # '.' + else if d > 2 then + putchard(43) # '+' + else + putchard(42); # '*' + ... + ready> printdensity(1): printdensity(2): printdensity(3): + printdensity(4): printdensity(5): printdensity(9): + putchard(10); + **++. + Evaluated to 0.000000 + +Based on these simple primitive operations, we can start to define more +interesting things. For example, here's a little function that solves +for the number of iterations it takes a function in the complex plane to +converge: + +:: + + # Determine whether the specific location diverges. + # Solve for z = z^2 + c in the complex plane. + def mandleconverger(real imag iters creal cimag) + if iters > 255 | (real*real + imag*imag > 4) then + iters + else + mandleconverger(real*real - imag*imag + creal, + 2*real*imag + cimag, + iters+1, creal, cimag); + + # Return the number of iterations required for the iteration to escape + def mandleconverge(real imag) + mandleconverger(real, imag, 0, real, imag); + +This "``z = z2 + c``" function is a beautiful little creature that is +the basis for computation of the `Mandelbrot +Set `_. Our +``mandelconverge`` function returns the number of iterations that it +takes for a complex orbit to escape, saturating to 255. This is not a +very useful function by itself, but if you plot its value over a +two-dimensional plane, you can see the Mandelbrot set. Given that we are +limited to using putchard here, our amazing graphical output is limited, +but we can whip together something using the density plotter above: + +:: + + # Compute and plot the mandlebrot set with the specified 2 dimensional range + # info. + def mandelhelp(xmin xmax xstep ymin ymax ystep) + for y = ymin, y < ymax, ystep in ( + (for x = xmin, x < xmax, xstep in + printdensity(mandleconverge(x,y))) + : putchard(10) + ) + + # mandel - This is a convenient helper function for plotting the mandelbrot set + # from the specified position with the specified Magnification. + def mandel(realstart imagstart realmag imagmag) + mandelhelp(realstart, realstart+realmag*78, realmag, + imagstart, imagstart+imagmag*40, imagmag); + +Given this, we can try plotting out the mandlebrot set! Lets try it out: + +:: + + ready> mandel(-2.3, -1.3, 0.05, 0.07); + *******************************+++++++++++************************************* + *************************+++++++++++++++++++++++******************************* + **********************+++++++++++++++++++++++++++++**************************** + *******************+++++++++++++++++++++.. ...++++++++************************* + *****************++++++++++++++++++++++.... ...+++++++++*********************** + ***************+++++++++++++++++++++++..... ...+++++++++********************* + **************+++++++++++++++++++++++.... ....+++++++++******************** + *************++++++++++++++++++++++...... .....++++++++******************* + ************+++++++++++++++++++++....... .......+++++++****************** + ***********+++++++++++++++++++.... ... .+++++++***************** + **********+++++++++++++++++....... .+++++++**************** + *********++++++++++++++........... ...+++++++*************** + ********++++++++++++............ ...++++++++************** + ********++++++++++... .......... .++++++++************** + *******+++++++++..... .+++++++++************* + *******++++++++...... ..+++++++++************* + *******++++++....... ..+++++++++************* + *******+++++...... ..+++++++++************* + *******.... .... ...+++++++++************* + *******.... . ...+++++++++************* + *******+++++...... ...+++++++++************* + *******++++++....... ..+++++++++************* + *******++++++++...... .+++++++++************* + *******+++++++++..... ..+++++++++************* + ********++++++++++... .......... .++++++++************** + ********++++++++++++............ ...++++++++************** + *********++++++++++++++.......... ...+++++++*************** + **********++++++++++++++++........ .+++++++**************** + **********++++++++++++++++++++.... ... ..+++++++**************** + ***********++++++++++++++++++++++....... .......++++++++***************** + ************+++++++++++++++++++++++...... ......++++++++****************** + **************+++++++++++++++++++++++.... ....++++++++******************** + ***************+++++++++++++++++++++++..... ...+++++++++********************* + *****************++++++++++++++++++++++.... ...++++++++*********************** + *******************+++++++++++++++++++++......++++++++************************* + *********************++++++++++++++++++++++.++++++++*************************** + *************************+++++++++++++++++++++++******************************* + ******************************+++++++++++++************************************ + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + Evaluated to 0.000000 + ready> mandel(-2, -1, 0.02, 0.04); + **************************+++++++++++++++++++++++++++++++++++++++++++++++++++++ + ***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + *********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++. + *******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++... + *****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++..... + ***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........ + **************++++++++++++++++++++++++++++++++++++++++++++++++++++++........... + ************+++++++++++++++++++++++++++++++++++++++++++++++++++++.............. + ***********++++++++++++++++++++++++++++++++++++++++++++++++++........ . + **********++++++++++++++++++++++++++++++++++++++++++++++............. + ********+++++++++++++++++++++++++++++++++++++++++++.................. + *******+++++++++++++++++++++++++++++++++++++++....................... + ******+++++++++++++++++++++++++++++++++++........................... + *****++++++++++++++++++++++++++++++++............................ + *****++++++++++++++++++++++++++++............................... + ****++++++++++++++++++++++++++...... ......................... + ***++++++++++++++++++++++++......... ...... ........... + ***++++++++++++++++++++++............ + **+++++++++++++++++++++.............. + **+++++++++++++++++++................ + *++++++++++++++++++................. + *++++++++++++++++............ ... + *++++++++++++++.............. + *+++....++++................ + *.......... ........... + * + *.......... ........... + *+++....++++................ + *++++++++++++++.............. + *++++++++++++++++............ ... + *++++++++++++++++++................. + **+++++++++++++++++++................ + **+++++++++++++++++++++.............. + ***++++++++++++++++++++++............ + ***++++++++++++++++++++++++......... ...... ........... + ****++++++++++++++++++++++++++...... ......................... + *****++++++++++++++++++++++++++++............................... + *****++++++++++++++++++++++++++++++++............................ + ******+++++++++++++++++++++++++++++++++++........................... + *******+++++++++++++++++++++++++++++++++++++++....................... + ********+++++++++++++++++++++++++++++++++++++++++++.................. + Evaluated to 0.000000 + ready> mandel(-0.9, -1.4, 0.02, 0.03); + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + **********+++++++++++++++++++++************************************************ + *+++++++++++++++++++++++++++++++++++++++*************************************** + +++++++++++++++++++++++++++++++++++++++++++++********************************** + ++++++++++++++++++++++++++++++++++++++++++++++++++***************************** + ++++++++++++++++++++++++++++++++++++++++++++++++++++++************************* + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++********************** + +++++++++++++++++++++++++++++++++.........++++++++++++++++++******************* + +++++++++++++++++++++++++++++++.... ......+++++++++++++++++++**************** + +++++++++++++++++++++++++++++....... ........+++++++++++++++++++************** + ++++++++++++++++++++++++++++........ ........++++++++++++++++++++************ + +++++++++++++++++++++++++++......... .. ...+++++++++++++++++++++********** + ++++++++++++++++++++++++++........... ....++++++++++++++++++++++******** + ++++++++++++++++++++++++............. .......++++++++++++++++++++++****** + +++++++++++++++++++++++............. ........+++++++++++++++++++++++**** + ++++++++++++++++++++++........... ..........++++++++++++++++++++++*** + ++++++++++++++++++++........... .........++++++++++++++++++++++* + ++++++++++++++++++............ ...........++++++++++++++++++++ + ++++++++++++++++............... .............++++++++++++++++++ + ++++++++++++++................. ...............++++++++++++++++ + ++++++++++++.................. .................++++++++++++++ + +++++++++.................. .................+++++++++++++ + ++++++........ . ......... ..++++++++++++ + ++............ ...... ....++++++++++ + .............. ...++++++++++ + .............. ....+++++++++ + .............. .....++++++++ + ............. ......++++++++ + ........... .......++++++++ + ......... ........+++++++ + ......... ........+++++++ + ......... ....+++++++ + ........ ...+++++++ + ....... ...+++++++ + ....+++++++ + .....+++++++ + ....+++++++ + ....+++++++ + ....+++++++ + Evaluated to 0.000000 + ready> ^D + +At this point, you may be starting to realize that Kaleidoscope is a +real and powerful language. It may not be self-similar :), but it can be +used to plot things that are! + +With this, we conclude the "adding user-defined operators" chapter of +the tutorial. We have successfully augmented our language, adding the +ability to extend the language in the library, and we have shown how +this can be used to build a simple but interesting end-user application +in Kaleidoscope. At this point, Kaleidoscope can build a variety of +applications that are functional and can call functions with +side-effects, but it can't actually define and mutate a variable itself. + +Strikingly, variable mutation is an important feature of some languages, +and it is not at all obvious how to `add support for mutable +variables `_ without having to add an "SSA construction" +phase to your front-end. In the next chapter, we will describe how you +can add variable mutation without building SSA in your front-end. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the if/then/else and for expressions.. To build this example, use: + +.. code-block:: bash + + # Compile + clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + # Run + ./toy + +On some platforms, you will need to specify -rdynamic or +-Wl,--export-dynamic when linking. This ensures that symbols defined in +the main executable are exported to the dynamic linker and so are +available for symbol resolution at run time. This is not needed if you +compile your support code into a shared library, although doing that +will cause problems on Windows. + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter6/toy.cpp + :language: c++ + +`Next: Extending the language: mutable variables / SSA +construction `_ + diff --git a/docs/tutorial/LangImpl7.rst b/docs/tutorial/LangImpl7.rst new file mode 100644 index 00000000..a2e47b5f --- /dev/null +++ b/docs/tutorial/LangImpl7.rst @@ -0,0 +1,860 @@ +======================================================= +Kaleidoscope: Extending the Language: Mutable Variables +======================================================= + +.. contents:: + :local: + +Chapter 7 Introduction +====================== + +Welcome to Chapter 7 of the "`Implementing a language with +LLVM `_" tutorial. In chapters 1 through 6, we've built a +very respectable, albeit simple, `functional programming +language `_. In our +journey, we learned some parsing techniques, how to build and represent +an AST, how to build LLVM IR, and how to optimize the resultant code as +well as JIT compile it. + +While Kaleidoscope is interesting as a functional language, the fact +that it is functional makes it "too easy" to generate LLVM IR for it. In +particular, a functional language makes it very easy to build LLVM IR +directly in `SSA +form `_. +Since LLVM requires that the input code be in SSA form, this is a very +nice property and it is often unclear to newcomers how to generate code +for an imperative language with mutable variables. + +The short (and happy) summary of this chapter is that there is no need +for your front-end to build SSA form: LLVM provides highly tuned and +well tested support for this, though the way it works is a bit +unexpected for some. + +Why is this a hard problem? +=========================== + +To understand why mutable variables cause complexities in SSA +construction, consider this extremely simple C example: + +.. code-block:: c + + int G, H; + int test(_Bool Condition) { + int X; + if (Condition) + X = G; + else + X = H; + return X; + } + +In this case, we have the variable "X", whose value depends on the path +executed in the program. Because there are two different possible values +for X before the return instruction, a PHI node is inserted to merge the +two values. The LLVM IR that we want for this example looks like this: + +.. code-block:: llvm + + @G = weak global i32 0 ; type of @G is i32* + @H = weak global i32 0 ; type of @H is i32* + + define i32 @test(i1 %Condition) { + entry: + br i1 %Condition, label %cond_true, label %cond_false + + cond_true: + %X.0 = load i32* @G + br label %cond_next + + cond_false: + %X.1 = load i32* @H + br label %cond_next + + cond_next: + %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ] + ret i32 %X.2 + } + +In this example, the loads from the G and H global variables are +explicit in the LLVM IR, and they live in the then/else branches of the +if statement (cond\_true/cond\_false). In order to merge the incoming +values, the X.2 phi node in the cond\_next block selects the right value +to use based on where control flow is coming from: if control flow comes +from the cond\_false block, X.2 gets the value of X.1. Alternatively, if +control flow comes from cond\_true, it gets the value of X.0. The intent +of this chapter is not to explain the details of SSA form. For more +information, see one of the many `online +references `_. + +The question for this article is "who places the phi nodes when lowering +assignments to mutable variables?". The issue here is that LLVM +*requires* that its IR be in SSA form: there is no "non-ssa" mode for +it. However, SSA construction requires non-trivial algorithms and data +structures, so it is inconvenient and wasteful for every front-end to +have to reproduce this logic. + +Memory in LLVM +============== + +The 'trick' here is that while LLVM does require all register values to +be in SSA form, it does not require (or permit) memory objects to be in +SSA form. In the example above, note that the loads from G and H are +direct accesses to G and H: they are not renamed or versioned. This +differs from some other compiler systems, which do try to version memory +objects. In LLVM, instead of encoding dataflow analysis of memory into +the LLVM IR, it is handled with `Analysis +Passes <../WritingAnLLVMPass.html>`_ which are computed on demand. + +With this in mind, the high-level idea is that we want to make a stack +variable (which lives in memory, because it is on the stack) for each +mutable object in a function. To take advantage of this trick, we need +to talk about how LLVM represents stack variables. + +In LLVM, all memory accesses are explicit with load/store instructions, +and it is carefully designed not to have (or need) an "address-of" +operator. Notice how the type of the @G/@H global variables is actually +"i32\*" even though the variable is defined as "i32". What this means is +that @G defines *space* for an i32 in the global data area, but its +*name* actually refers to the address for that space. Stack variables +work the same way, except that instead of being declared with global +variable definitions, they are declared with the `LLVM alloca +instruction <../LangRef.html#i_alloca>`_: + +.. code-block:: llvm + + define i32 @example() { + entry: + %X = alloca i32 ; type of %X is i32*. + ... + %tmp = load i32* %X ; load the stack value %X from the stack. + %tmp2 = add i32 %tmp, 1 ; increment it + store i32 %tmp2, i32* %X ; store it back + ... + +This code shows an example of how you can declare and manipulate a stack +variable in the LLVM IR. Stack memory allocated with the alloca +instruction is fully general: you can pass the address of the stack slot +to functions, you can store it in other variables, etc. In our example +above, we could rewrite the example to use the alloca technique to avoid +using a PHI node: + +.. code-block:: llvm + + @G = weak global i32 0 ; type of @G is i32* + @H = weak global i32 0 ; type of @H is i32* + + define i32 @test(i1 %Condition) { + entry: + %X = alloca i32 ; type of %X is i32*. + br i1 %Condition, label %cond_true, label %cond_false + + cond_true: + %X.0 = load i32* @G + store i32 %X.0, i32* %X ; Update X + br label %cond_next + + cond_false: + %X.1 = load i32* @H + store i32 %X.1, i32* %X ; Update X + br label %cond_next + + cond_next: + %X.2 = load i32* %X ; Read X + ret i32 %X.2 + } + +With this, we have discovered a way to handle arbitrary mutable +variables without the need to create Phi nodes at all: + +#. Each mutable variable becomes a stack allocation. +#. Each read of the variable becomes a load from the stack. +#. Each update of the variable becomes a store to the stack. +#. Taking the address of a variable just uses the stack address + directly. + +While this solution has solved our immediate problem, it introduced +another one: we have now apparently introduced a lot of stack traffic +for very simple and common operations, a major performance problem. +Fortunately for us, the LLVM optimizer has a highly-tuned optimization +pass named "mem2reg" that handles this case, promoting allocas like this +into SSA registers, inserting Phi nodes as appropriate. If you run this +example through the pass, for example, you'll get: + +.. code-block:: bash + + $ llvm-as < example.ll | opt -mem2reg | llvm-dis + @G = weak global i32 0 + @H = weak global i32 0 + + define i32 @test(i1 %Condition) { + entry: + br i1 %Condition, label %cond_true, label %cond_false + + cond_true: + %X.0 = load i32* @G + br label %cond_next + + cond_false: + %X.1 = load i32* @H + br label %cond_next + + cond_next: + %X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ] + ret i32 %X.01 + } + +The mem2reg pass implements the standard "iterated dominance frontier" +algorithm for constructing SSA form and has a number of optimizations +that speed up (very common) degenerate cases. The mem2reg optimization +pass is the answer to dealing with mutable variables, and we highly +recommend that you depend on it. Note that mem2reg only works on +variables in certain circumstances: + +#. mem2reg is alloca-driven: it looks for allocas and if it can handle + them, it promotes them. It does not apply to global variables or heap + allocations. +#. mem2reg only looks for alloca instructions in the entry block of the + function. Being in the entry block guarantees that the alloca is only + executed once, which makes analysis simpler. +#. mem2reg only promotes allocas whose uses are direct loads and stores. + If the address of the stack object is passed to a function, or if any + funny pointer arithmetic is involved, the alloca will not be + promoted. +#. mem2reg only works on allocas of `first + class <../LangRef.html#t_classifications>`_ values (such as pointers, + scalars and vectors), and only if the array size of the allocation is + 1 (or missing in the .ll file). mem2reg is not capable of promoting + structs or arrays to registers. Note that the "scalarrepl" pass is + more powerful and can promote structs, "unions", and arrays in many + cases. + +All of these properties are easy to satisfy for most imperative +languages, and we'll illustrate it below with Kaleidoscope. The final +question you may be asking is: should I bother with this nonsense for my +front-end? Wouldn't it be better if I just did SSA construction +directly, avoiding use of the mem2reg optimization pass? In short, we +strongly recommend that you use this technique for building SSA form, +unless there is an extremely good reason not to. Using this technique +is: + +- Proven and well tested: llvm-gcc and clang both use this technique + for local mutable variables. As such, the most common clients of LLVM + are using this to handle a bulk of their variables. You can be sure + that bugs are found fast and fixed early. +- Extremely Fast: mem2reg has a number of special cases that make it + fast in common cases as well as fully general. For example, it has + fast-paths for variables that are only used in a single block, + variables that only have one assignment point, good heuristics to + avoid insertion of unneeded phi nodes, etc. +- Needed for debug info generation: `Debug information in + LLVM <../SourceLevelDebugging.html>`_ relies on having the address of + the variable exposed so that debug info can be attached to it. This + technique dovetails very naturally with this style of debug info. + +If nothing else, this makes it much easier to get your front-end up and +running, and is very simple to implement. Lets extend Kaleidoscope with +mutable variables now! + +Mutable Variables in Kaleidoscope +================================= + +Now that we know the sort of problem we want to tackle, lets see what +this looks like in the context of our little Kaleidoscope language. +We're going to add two features: + +#. The ability to mutate variables with the '=' operator. +#. The ability to define new variables. + +While the first item is really what this is about, we only have +variables for incoming arguments as well as for induction variables, and +redefining those only goes so far :). Also, the ability to define new +variables is a useful thing regardless of whether you will be mutating +them. Here's a motivating example that shows how we could use these: + +:: + + # Define ':' for sequencing: as a low-precedence operator that ignores operands + # and just returns the RHS. + def binary : 1 (x y) y; + + # Recursive fib, we could do this before. + def fib(x) + if (x < 3) then + 1 + else + fib(x-1)+fib(x-2); + + # Iterative fib. + def fibi(x) + var a = 1, b = 1, c in + (for i = 3, i < x in + c = a + b : + a = b : + b = c) : + b; + + # Call it. + fibi(10); + +In order to mutate variables, we have to change our existing variables +to use the "alloca trick". Once we have that, we'll add our new +operator, then extend Kaleidoscope to support new variable definitions. + +Adjusting Existing Variables for Mutation +========================================= + +The symbol table in Kaleidoscope is managed at code generation time by +the '``NamedValues``' map. This map currently keeps track of the LLVM +"Value\*" that holds the double value for the named variable. In order +to support mutation, we need to change this slightly, so that it +``NamedValues`` holds the *memory location* of the variable in question. +Note that this change is a refactoring: it changes the structure of the +code, but does not (by itself) change the behavior of the compiler. All +of these changes are isolated in the Kaleidoscope code generator. + +At this point in Kaleidoscope's development, it only supports variables +for two things: incoming arguments to functions and the induction +variable of 'for' loops. For consistency, we'll allow mutation of these +variables in addition to other user-defined variables. This means that +these will both need memory locations. + +To start our transformation of Kaleidoscope, we'll change the +NamedValues map so that it maps to AllocaInst\* instead of Value\*. Once +we do this, the C++ compiler will tell us what parts of the code we need +to update: + +.. code-block:: c++ + + static std::map NamedValues; + +Also, since we will need to create these alloca's, we'll use a helper +function that ensures that the allocas are created in the entry block of +the function: + +.. code-block:: c++ + + /// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of + /// the function. This is used for mutable variables etc. + static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); + } + +This funny looking code creates an IRBuilder object that is pointing at +the first instruction (.begin()) of the entry block. It then creates an +alloca with the expected name and returns it. Because all values in +Kaleidoscope are doubles, there is no need to pass in a type to use. + +With this in place, the first functionality change we want to make is to +variable references. In our new scheme, variables live on the stack, so +code generating a reference to them actually needs to produce a load +from the stack slot: + +.. code-block:: c++ + + Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) return ErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); + } + +As you can see, this is pretty straightforward. Now we need to update +the things that define the variables to set up the alloca. We'll start +with ``ForExprAST::Codegen`` (see the `full code listing <#code>`_ for +the unabridged code): + +.. code-block:: c++ + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + ... + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + ... + +This code is virtually identical to the code `before we allowed mutable +variables `_. The big difference is that we +no longer have to construct a PHI node, and we use load/store to access +the variable as needed. + +To support mutable argument variables, we need to also make allocas for +them. The code for this is also pretty simple: + +.. code-block:: c++ + + /// CreateArgumentAllocas - Create an alloca for each argument and register the + /// argument in the symbol table so that references to it will succeed. + void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } + } + +For each argument, we make an alloca, store the input value to the +function into the alloca, and register the alloca as the memory location +for the argument. This method gets invoked by ``FunctionAST::Codegen`` +right after it sets up the entry block for the function. + +The final missing piece is adding the mem2reg pass, which allows us to +get good codegen once again: + +.. code-block:: c++ + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + +It is interesting to see what the code looks like before and after the +mem2reg optimization runs. For example, this is the before/after code +for our recursive fib function. Before the optimization: + +.. code-block:: llvm + + define double @fib(double %x) { + entry: + %x1 = alloca double + store double %x, double* %x1 + %x2 = load double* %x1 + %cmptmp = fcmp ult double %x2, 3.000000e+00 + %booltmp = uitofp i1 %cmptmp to double + %ifcond = fcmp one double %booltmp, 0.000000e+00 + br i1 %ifcond, label %then, label %else + + then: ; preds = %entry + br label %ifcont + + else: ; preds = %entry + %x3 = load double* %x1 + %subtmp = fsub double %x3, 1.000000e+00 + %calltmp = call double @fib(double %subtmp) + %x4 = load double* %x1 + %subtmp5 = fsub double %x4, 2.000000e+00 + %calltmp6 = call double @fib(double %subtmp5) + %addtmp = fadd double %calltmp, %calltmp6 + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ] + ret double %iftmp + } + +Here there is only one variable (x, the input argument) but you can +still see the extremely simple-minded code generation strategy we are +using. In the entry block, an alloca is created, and the initial input +value is stored into it. Each reference to the variable does a reload +from the stack. Also, note that we didn't modify the if/then/else +expression, so it still inserts a PHI node. While we could make an +alloca for it, it is actually easier to create a PHI node for it, so we +still just make the PHI. + +Here is the code after the mem2reg pass runs: + +.. code-block:: llvm + + define double @fib(double %x) { + entry: + %cmptmp = fcmp ult double %x, 3.000000e+00 + %booltmp = uitofp i1 %cmptmp to double + %ifcond = fcmp one double %booltmp, 0.000000e+00 + br i1 %ifcond, label %then, label %else + + then: + br label %ifcont + + else: + %subtmp = fsub double %x, 1.000000e+00 + %calltmp = call double @fib(double %subtmp) + %subtmp5 = fsub double %x, 2.000000e+00 + %calltmp6 = call double @fib(double %subtmp5) + %addtmp = fadd double %calltmp, %calltmp6 + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ] + ret double %iftmp + } + +This is a trivial case for mem2reg, since there are no redefinitions of +the variable. The point of showing this is to calm your tension about +inserting such blatent inefficiencies :). + +After the rest of the optimizers run, we get: + +.. code-block:: llvm + + define double @fib(double %x) { + entry: + %cmptmp = fcmp ult double %x, 3.000000e+00 + %booltmp = uitofp i1 %cmptmp to double + %ifcond = fcmp ueq double %booltmp, 0.000000e+00 + br i1 %ifcond, label %else, label %ifcont + + else: + %subtmp = fsub double %x, 1.000000e+00 + %calltmp = call double @fib(double %subtmp) + %subtmp5 = fsub double %x, 2.000000e+00 + %calltmp6 = call double @fib(double %subtmp5) + %addtmp = fadd double %calltmp, %calltmp6 + ret double %addtmp + + ifcont: + ret double 1.000000e+00 + } + +Here we see that the simplifycfg pass decided to clone the return +instruction into the end of the 'else' block. This allowed it to +eliminate some branches and the PHI node. + +Now that all symbol table references are updated to use stack variables, +we'll add the assignment operator. + +New Assignment Operator +======================= + +With our current framework, adding a new assignment operator is really +simple. We will parse it just like any other binary operator, but handle +it internally (instead of allowing the user to define it). The first +step is to set a precedence: + +.. code-block:: c++ + + int main() { + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + +Now that the parser knows the precedence of the binary operator, it +takes care of all the parsing and AST generation. We just need to +implement codegen for the assignment operator. This looks like: + +.. code-block:: c++ + + Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = dynamic_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + +Unlike the rest of the binary operators, our assignment operator doesn't +follow the "emit LHS, emit RHS, do computation" model. As such, it is +handled as a special case before the other binary operators are handled. +The other strange thing is that it requires the LHS to be a variable. It +is invalid to have "(x+1) = expr" - only things like "x = expr" are +allowed. + +.. code-block:: c++ + + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + ... + +Once we have the variable, codegen'ing the assignment is +straightforward: we emit the RHS of the assignment, create a store, and +return the computed value. Returning a value allows for chained +assignments like "X = (Y = Z)". + +Now that we have an assignment operator, we can mutate loop variables +and arguments. For example, we can now run code like this: + +:: + + # Function to print a double. + extern printd(x); + + # Define ':' for sequencing: as a low-precedence operator that ignores operands + # and just returns the RHS. + def binary : 1 (x y) y; + + def test(x) + printd(x) : + x = 4 : + printd(x); + + test(123); + +When run, this example prints "123" and then "4", showing that we did +actually mutate the value! Okay, we have now officially implemented our +goal: getting this to work requires SSA construction in the general +case. However, to be really useful, we want the ability to define our +own local variables, lets add this next! + +User-defined Local Variables +============================ + +Adding var/in is just like any other other extensions we made to +Kaleidoscope: we extend the lexer, the parser, the AST and the code +generator. The first step for adding our new 'var/in' construct is to +extend the lexer. As before, this is pretty trivial, the code looks like +this: + +.. code-block:: c++ + + enum Token { + ... + // var definition + tok_var = -13 + ... + } + ... + static int gettok() { + ... + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + ... + +The next step is to define the AST node that we will construct. For +var/in, it looks like this: + +.. code-block:: c++ + + /// VarExprAST - Expression class for var/in + class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; + public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); + }; + +var/in allows a list of names to be defined all at once, and each name +can optionally have an initializer value. As such, we capture this +information in the VarNames vector. Also, var/in has a body, this body +is allowed to access the variables defined by the var/in. + +With this in place, we can define the parser pieces. The first thing we +do is add it as a primary expression: + +.. code-block:: c++ + + /// primary + /// ::= identifierexpr + /// ::= numberexpr + /// ::= parenexpr + /// ::= ifexpr + /// ::= forexpr + /// ::= varexpr + static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } + } + +Next we define ParseVarExpr: + +.. code-block:: c++ + + /// varexpr ::= 'var' identifier ('=' expression)? + // (',' identifier ('=' expression)?)* 'in' expression + static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + +The first part of this code parses the list of identifier/expr pairs +into the local ``VarNames`` vector. + +.. code-block:: c++ + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + +Once all the variables are parsed, we then parse the body and create the +AST node: + +.. code-block:: c++ + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); + } + +Now that we can parse and represent the code, we need to support +emission of LLVM IR for it. This code starts out with: + +.. code-block:: c++ + + Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + +Basically it loops over all the variables, installing them one at a +time. For each variable we put into the symbol table, we remember the +previous value that we replace in OldBindings. + +.. code-block:: c++ + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + +There are more comments here than code. The basic idea is that we emit +the initializer, create the alloca, then update the symbol table to +point to it. Once all the variables are installed in the symbol table, +we evaluate the body of the var/in expression: + +.. code-block:: c++ + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + +Finally, before returning, we restore the previous variable bindings: + +.. code-block:: c++ + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; + } + +The end result of all of this is that we get properly scoped variable +definitions, and we even (trivially) allow mutation of them :). + +With this, we completed what we set out to do. Our nice iterative fib +example from the intro compiles and runs just fine. The mem2reg pass +optimizes all of our stack variables into SSA registers, inserting PHI +nodes where needed, and our front-end remains simple: no "iterated +dominance frontier" computation anywhere in sight. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +mutable variables and var/in support. To build this example, use: + +.. code-block:: bash + + # Compile + clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + # Run + ./toy + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter7/toy.cpp + :language: c++ + +`Next: Conclusion and other useful LLVM tidbits `_ + diff --git a/docs/tutorial/LangImpl8.rst b/docs/tutorial/LangImpl8.rst new file mode 100644 index 00000000..3534b2e0 --- /dev/null +++ b/docs/tutorial/LangImpl8.rst @@ -0,0 +1,267 @@ +====================================================== +Kaleidoscope: Conclusion and other useful LLVM tidbits +====================================================== + +.. contents:: + :local: + +Tutorial Conclusion +=================== + +Welcome to the final chapter of the "`Implementing a language with +LLVM `_" tutorial. In the course of this tutorial, we have +grown our little Kaleidoscope language from being a useless toy, to +being a semi-interesting (but probably still useless) toy. :) + +It is interesting to see how far we've come, and how little code it has +taken. We built the entire lexer, parser, AST, code generator, and an +interactive run-loop (with a JIT!) by-hand in under 700 lines of +(non-comment/non-blank) code. + +Our little language supports a couple of interesting features: it +supports user defined binary and unary operators, it uses JIT +compilation for immediate evaluation, and it supports a few control flow +constructs with SSA construction. + +Part of the idea of this tutorial was to show you how easy and fun it +can be to define, build, and play with languages. Building a compiler +need not be a scary or mystical process! Now that you've seen some of +the basics, I strongly encourage you to take the code and hack on it. +For example, try adding: + +- **global variables** - While global variables have questional value + in modern software engineering, they are often useful when putting + together quick little hacks like the Kaleidoscope compiler itself. + Fortunately, our current setup makes it very easy to add global + variables: just have value lookup check to see if an unresolved + variable is in the global variable symbol table before rejecting it. + To create a new global variable, make an instance of the LLVM + ``GlobalVariable`` class. +- **typed variables** - Kaleidoscope currently only supports variables + of type double. This gives the language a very nice elegance, because + only supporting one type means that you never have to specify types. + Different languages have different ways of handling this. The easiest + way is to require the user to specify types for every variable + definition, and record the type of the variable in the symbol table + along with its Value\*. +- **arrays, structs, vectors, etc** - Once you add types, you can start + extending the type system in all sorts of interesting ways. Simple + arrays are very easy and are quite useful for many different + applications. Adding them is mostly an exercise in learning how the + LLVM `getelementptr <../LangRef.html#i_getelementptr>`_ instruction + works: it is so nifty/unconventional, it `has its own + FAQ <../GetElementPtr.html>`_! If you add support for recursive types + (e.g. linked lists), make sure to read the `section in the LLVM + Programmer's Manual <../ProgrammersManual.html#TypeResolve>`_ that + describes how to construct them. +- **standard runtime** - Our current language allows the user to access + arbitrary external functions, and we use it for things like "printd" + and "putchard". As you extend the language to add higher-level + constructs, often these constructs make the most sense if they are + lowered to calls into a language-supplied runtime. For example, if + you add hash tables to the language, it would probably make sense to + add the routines to a runtime, instead of inlining them all the way. +- **memory management** - Currently we can only access the stack in + Kaleidoscope. It would also be useful to be able to allocate heap + memory, either with calls to the standard libc malloc/free interface + or with a garbage collector. If you would like to use garbage + collection, note that LLVM fully supports `Accurate Garbage + Collection <../GarbageCollection.html>`_ including algorithms that + move objects and need to scan/update the stack. +- **debugger support** - LLVM supports generation of `DWARF Debug + info <../SourceLevelDebugging.html>`_ which is understood by common + debuggers like GDB. Adding support for debug info is fairly + straightforward. The best way to understand it is to compile some + C/C++ code with "``llvm-gcc -g -O0``" and taking a look at what it + produces. +- **exception handling support** - LLVM supports generation of `zero + cost exceptions <../ExceptionHandling.html>`_ which interoperate with + code compiled in other languages. You could also generate code by + implicitly making every function return an error value and checking + it. You could also make explicit use of setjmp/longjmp. There are + many different ways to go here. +- **object orientation, generics, database access, complex numbers, + geometric programming, ...** - Really, there is no end of crazy + features that you can add to the language. +- **unusual domains** - We've been talking about applying LLVM to a + domain that many people are interested in: building a compiler for a + specific language. However, there are many other domains that can use + compiler technology that are not typically considered. For example, + LLVM has been used to implement OpenGL graphics acceleration, + translate C++ code to ActionScript, and many other cute and clever + things. Maybe you will be the first to JIT compile a regular + expression interpreter into native code with LLVM? + +Have fun - try doing something crazy and unusual. Building a language +like everyone else always has, is much less fun than trying something a +little crazy or off the wall and seeing how it turns out. If you get +stuck or want to talk about it, feel free to email the `llvmdev mailing +list `_: it has lots +of people who are interested in languages and are often willing to help +out. + +Before we end this tutorial, I want to talk about some "tips and tricks" +for generating LLVM IR. These are some of the more subtle things that +may not be obvious, but are very useful if you want to take advantage of +LLVM's capabilities. + +Properties of the LLVM IR +========================= + +We have a couple common questions about code in the LLVM IR form - lets +just get these out of the way right now, shall we? + +Target Independence +------------------- + +Kaleidoscope is an example of a "portable language": any program written +in Kaleidoscope will work the same way on any target that it runs on. +Many other languages have this property, e.g. lisp, java, haskell, +javascript, python, etc (note that while these languages are portable, +not all their libraries are). + +One nice aspect of LLVM is that it is often capable of preserving target +independence in the IR: you can take the LLVM IR for a +Kaleidoscope-compiled program and run it on any target that LLVM +supports, even emitting C code and compiling that on targets that LLVM +doesn't support natively. You can trivially tell that the Kaleidoscope +compiler generates target-independent code because it never queries for +any target-specific information when generating code. + +The fact that LLVM provides a compact, target-independent, +representation for code gets a lot of people excited. Unfortunately, +these people are usually thinking about C or a language from the C +family when they are asking questions about language portability. I say +"unfortunately", because there is really no way to make (fully general) +C code portable, other than shipping the source code around (and of +course, C source code is not actually portable in general either - ever +port a really old application from 32- to 64-bits?). + +The problem with C (again, in its full generality) is that it is heavily +laden with target specific assumptions. As one simple example, the +preprocessor often destructively removes target-independence from the +code when it processes the input text: + +.. code-block:: c + + #ifdef __i386__ + int X = 1; + #else + int X = 42; + #endif + +While it is possible to engineer more and more complex solutions to +problems like this, it cannot be solved in full generality in a way that +is better than shipping the actual source code. + +That said, there are interesting subsets of C that can be made portable. +If you are willing to fix primitive types to a fixed size (say int = +32-bits, and long = 64-bits), don't care about ABI compatibility with +existing binaries, and are willing to give up some other minor features, +you can have portable code. This can make sense for specialized domains +such as an in-kernel language. + +Safety Guarantees +----------------- + +Many of the languages above are also "safe" languages: it is impossible +for a program written in Java to corrupt its address space and crash the +process (assuming the JVM has no bugs). Safety is an interesting +property that requires a combination of language design, runtime +support, and often operating system support. + +It is certainly possible to implement a safe language in LLVM, but LLVM +IR does not itself guarantee safety. The LLVM IR allows unsafe pointer +casts, use after free bugs, buffer over-runs, and a variety of other +problems. Safety needs to be implemented as a layer on top of LLVM and, +conveniently, several groups have investigated this. Ask on the `llvmdev +mailing list `_ if +you are interested in more details. + +Language-Specific Optimizations +------------------------------- + +One thing about LLVM that turns off many people is that it does not +solve all the world's problems in one system (sorry 'world hunger', +someone else will have to solve you some other day). One specific +complaint is that people perceive LLVM as being incapable of performing +high-level language-specific optimization: LLVM "loses too much +information". + +Unfortunately, this is really not the place to give you a full and +unified version of "Chris Lattner's theory of compiler design". Instead, +I'll make a few observations: + +First, you're right that LLVM does lose information. For example, as of +this writing, there is no way to distinguish in the LLVM IR whether an +SSA-value came from a C "int" or a C "long" on an ILP32 machine (other +than debug info). Both get compiled down to an 'i32' value and the +information about what it came from is lost. The more general issue +here, is that the LLVM type system uses "structural equivalence" instead +of "name equivalence". Another place this surprises people is if you +have two types in a high-level language that have the same structure +(e.g. two different structs that have a single int field): these types +will compile down into a single LLVM type and it will be impossible to +tell what it came from. + +Second, while LLVM does lose information, LLVM is not a fixed target: we +continue to enhance and improve it in many different ways. In addition +to adding new features (LLVM did not always support exceptions or debug +info), we also extend the IR to capture important information for +optimization (e.g. whether an argument is sign or zero extended, +information about pointers aliasing, etc). Many of the enhancements are +user-driven: people want LLVM to include some specific feature, so they +go ahead and extend it. + +Third, it is *possible and easy* to add language-specific optimizations, +and you have a number of choices in how to do it. As one trivial +example, it is easy to add language-specific optimization passes that +"know" things about code compiled for a language. In the case of the C +family, there is an optimization pass that "knows" about the standard C +library functions. If you call "exit(0)" in main(), it knows that it is +safe to optimize that into "return 0;" because C specifies what the +'exit' function does. + +In addition to simple library knowledge, it is possible to embed a +variety of other language-specific information into the LLVM IR. If you +have a specific need and run into a wall, please bring the topic up on +the llvmdev list. At the very worst, you can always treat LLVM as if it +were a "dumb code generator" and implement the high-level optimizations +you desire in your front-end, on the language-specific AST. + +Tips and Tricks +=============== + +There is a variety of useful tips and tricks that you come to know after +working on/with LLVM that aren't obvious at first glance. Instead of +letting everyone rediscover them, this section talks about some of these +issues. + +Implementing portable offsetof/sizeof +------------------------------------- + +One interesting thing that comes up, if you are trying to keep the code +generated by your compiler "target independent", is that you often need +to know the size of some LLVM type or the offset of some field in an +llvm structure. For example, you might need to pass the size of a type +into a function that allocates memory. + +Unfortunately, this can vary widely across targets: for example the +width of a pointer is trivially target-specific. However, there is a +`clever way to use the getelementptr +instruction `_ +that allows you to compute this in a portable way. + +Garbage Collected Stack Frames +------------------------------ + +Some languages want to explicitly manage their stack frames, often so +that they are garbage collected or to allow easy implementation of +closures. There are often better ways to implement these features than +explicit stack frames, but `LLVM does support +them, `_ +if you want. It requires your front-end to convert the code into +`Continuation Passing +Style `_ and +the use of tail calls (which LLVM also supports). + diff --git a/docs/tutorial/OCamlLangImpl1.rst b/docs/tutorial/OCamlLangImpl1.rst new file mode 100644 index 00000000..94ca3a5a --- /dev/null +++ b/docs/tutorial/OCamlLangImpl1.rst @@ -0,0 +1,285 @@ +================================================= +Kaleidoscope: Tutorial Introduction and the Lexer +================================================= + +.. contents:: + :local: + +Tutorial Introduction +===================== + +Welcome to the "Implementing a language with LLVM" tutorial. This +tutorial runs through the implementation of a simple language, showing +how fun and easy it can be. This tutorial will get you up and started as +well as help to build a framework you can extend to other languages. The +code in this tutorial can also be used as a playground to hack on other +LLVM specific things. + +The goal of this tutorial is to progressively unveil our language, +describing how it is built up over time. This will let us cover a fairly +broad range of language design and LLVM-specific usage issues, showing +and explaining the code for it all along the way, without overwhelming +you with tons of details up front. + +It is useful to point out ahead of time that this tutorial is really +about teaching compiler techniques and LLVM specifically, *not* about +teaching modern and sane software engineering principles. In practice, +this means that we'll take a number of shortcuts to simplify the +exposition. For example, the code leaks memory, uses global variables +all over the place, doesn't use nice design patterns like +`visitors `_, etc... but +it is very simple. If you dig in and use the code as a basis for future +projects, fixing these deficiencies shouldn't be hard. + +I've tried to put this tutorial together in a way that makes chapters +easy to skip over if you are already familiar with or are uninterested +in the various pieces. The structure of the tutorial is: + +- `Chapter #1 <#language>`_: Introduction to the Kaleidoscope + language, and the definition of its Lexer - This shows where we are + going and the basic functionality that we want it to do. In order to + make this tutorial maximally understandable and hackable, we choose + to implement everything in Objective Caml instead of using lexer and + parser generators. LLVM obviously works just fine with such tools, + feel free to use one if you prefer. +- `Chapter #2 `_: Implementing a Parser and + AST - With the lexer in place, we can talk about parsing techniques + and basic AST construction. This tutorial describes recursive descent + parsing and operator precedence parsing. Nothing in Chapters 1 or 2 + is LLVM-specific, the code doesn't even link in LLVM at this point. + :) +- `Chapter #3 `_: Code generation to LLVM IR - + With the AST ready, we can show off how easy generation of LLVM IR + really is. +- `Chapter #4 `_: Adding JIT and Optimizer + Support - Because a lot of people are interested in using LLVM as a + JIT, we'll dive right into it and show you the 3 lines it takes to + add JIT support. LLVM is also useful in many other ways, but this is + one simple and "sexy" way to shows off its power. :) +- `Chapter #5 `_: Extending the Language: + Control Flow - With the language up and running, we show how to + extend it with control flow operations (if/then/else and a 'for' + loop). This gives us a chance to talk about simple SSA construction + and control flow. +- `Chapter #6 `_: Extending the Language: + User-defined Operators - This is a silly but fun chapter that talks + about extending the language to let the user program define their own + arbitrary unary and binary operators (with assignable precedence!). + This lets us build a significant piece of the "language" as library + routines. +- `Chapter #7 `_: Extending the Language: + Mutable Variables - This chapter talks about adding user-defined + local variables along with an assignment operator. The interesting + part about this is how easy and trivial it is to construct SSA form + in LLVM: no, LLVM does *not* require your front-end to construct SSA + form! +- `Chapter #8 `_: Conclusion and other useful + LLVM tidbits - This chapter wraps up the series by talking about + potential ways to extend the language, but also includes a bunch of + pointers to info about "special topics" like adding garbage + collection support, exceptions, debugging, support for "spaghetti + stacks", and a bunch of other tips and tricks. + +By the end of the tutorial, we'll have written a bit less than 700 lines +of non-comment, non-blank, lines of code. With this small amount of +code, we'll have built up a very reasonable compiler for a non-trivial +language including a hand-written lexer, parser, AST, as well as code +generation support with a JIT compiler. While other systems may have +interesting "hello world" tutorials, I think the breadth of this +tutorial is a great testament to the strengths of LLVM and why you +should consider it if you're interested in language or compiler design. + +A note about this tutorial: we expect you to extend the language and +play with it on your own. Take the code and go crazy hacking away at it, +compilers don't need to be scary creatures - it can be a lot of fun to +play with languages! + +The Basic Language +================== + +This tutorial will be illustrated with a toy language that we'll call +"`Kaleidoscope `_" (derived +from "meaning beautiful, form, and view"). Kaleidoscope is a procedural +language that allows you to define functions, use conditionals, math, +etc. Over the course of the tutorial, we'll extend Kaleidoscope to +support the if/then/else construct, a for loop, user defined operators, +JIT compilation with a simple command line interface, etc. + +Because we want to keep things simple, the only datatype in Kaleidoscope +is a 64-bit floating point type (aka 'float' in O'Caml parlance). As +such, all values are implicitly double precision and the language +doesn't require type declarations. This gives the language a very nice +and simple syntax. For example, the following simple example computes +`Fibonacci numbers: `_ + +:: + + # Compute the x'th fibonacci number. + def fib(x) + if x < 3 then + 1 + else + fib(x-1)+fib(x-2) + + # This expression will compute the 40th number. + fib(40) + +We also allow Kaleidoscope to call into standard library functions (the +LLVM JIT makes this completely trivial). This means that you can use the +'extern' keyword to define a function before you use it (this is also +useful for mutually recursive functions). For example: + +:: + + extern sin(arg); + extern cos(arg); + extern atan2(arg1 arg2); + + atan2(sin(.4), cos(42)) + +A more interesting example is included in Chapter 6 where we write a +little Kaleidoscope application that `displays a Mandelbrot +Set `_ at various levels of magnification. + +Lets dive into the implementation of this language! + +The Lexer +========= + +When it comes to implementing a language, the first thing needed is the +ability to process a text file and recognize what it says. The +traditional way to do this is to use a +"`lexer `_" (aka +'scanner') to break the input up into "tokens". Each token returned by +the lexer includes a token code and potentially some metadata (e.g. the +numeric value of a number). First, we define the possibilities: + +.. code-block:: ocaml + + (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) + type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + +Each token returned by our lexer will be one of the token variant +values. An unknown character like '+' will be returned as +``Token.Kwd '+'``. If the curr token is an identifier, the value will be +``Token.Ident s``. If the current token is a numeric literal (like 1.0), +the value will be ``Token.Number 1.0``. + +The actual implementation of the lexer is a collection of functions +driven by a function named ``Lexer.lex``. The ``Lexer.lex`` function is +called to return the next token from standard input. We will use +`Camlp4 `_ to +simplify the tokenization of the standard input. Its definition starts +as: + +.. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + + let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + +``Lexer.lex`` works by recursing over a ``char Stream.t`` to read +characters one at a time from the standard input. It eats them as it +recognizes them and stores them in in a ``Token.token`` variant. The +first thing that it has to do is ignore whitespace between tokens. This +is accomplished with the recursive call above. + +The next thing ``Lexer.lex`` needs to do is recognize identifiers and +specific keywords like "def". Kaleidoscope does this with a pattern +match and a helper function. + +.. code-block:: ocaml + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + ... + + and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + +Numeric values are similar: + +.. code-block:: ocaml + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + ... + + and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +This is all pretty straight-forward code for processing input. When +reading a numeric value from input, we use the ocaml ``float_of_string`` +function to convert it to a numeric value that we store in +``Token.Number``. Note that this isn't doing sufficient error checking: +it will raise ``Failure`` if the string "1.23.45.67". Feel free to +extend it :). Next we handle comments: + +.. code-block:: ocaml + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + ... + + and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] + +We handle comments by skipping to the end of the line and then return +the next token. Finally, if the input doesn't match one of the above +cases, it is either an operator character like '+' or the end of the +file. These are handled with this code: + +.. code-block:: ocaml + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +With this, we have the complete lexer for the basic Kaleidoscope +language (the `full code listing `_ for the +Lexer is available in the `next chapter `_ of the +tutorial). Next we'll `build a simple parser that uses this to build an +Abstract Syntax Tree `_. When we have that, we'll +include a driver so that you can use the lexer and parser together. + +`Next: Implementing a Parser and AST `_ + diff --git a/docs/tutorial/OCamlLangImpl2.rst b/docs/tutorial/OCamlLangImpl2.rst new file mode 100644 index 00000000..905b3067 --- /dev/null +++ b/docs/tutorial/OCamlLangImpl2.rst @@ -0,0 +1,899 @@ +=========================================== +Kaleidoscope: Implementing a Parser and AST +=========================================== + +.. contents:: + :local: + +Chapter 2 Introduction +====================== + +Welcome to Chapter 2 of the "`Implementing a language with LLVM in +Objective Caml `_" tutorial. This chapter shows you how to +use the lexer, built in `Chapter 1 `_, to build a +full `parser `_ for our +Kaleidoscope language. Once we have a parser, we'll define and build an +`Abstract Syntax +Tree `_ (AST). + +The parser we will build uses a combination of `Recursive Descent +Parsing `_ and +`Operator-Precedence +Parsing `_ to +parse the Kaleidoscope language (the latter for binary expressions and +the former for everything else). Before we get to parsing though, lets +talk about the output of the parser: the Abstract Syntax Tree. + +The Abstract Syntax Tree (AST) +============================== + +The AST for a program captures its behavior in such a way that it is +easy for later stages of the compiler (e.g. code generation) to +interpret. We basically want one object for each construct in the +language, and the AST should closely model the language. In +Kaleidoscope, we have expressions, a prototype, and a function object. +We'll start with expressions first: + +.. code-block:: ocaml + + (* expr - Base type for all expression nodes. *) + type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + +The code above shows the definition of the base ExprAST class and one +subclass which we use for numeric literals. The important thing to note +about this code is that the Number variant captures the numeric value of +the literal as an instance variable. This allows later phases of the +compiler to know what the stored numeric value is. + +Right now we only create the AST, so there are no useful functions on +them. It would be very easy to add a function to pretty print the code, +for example. Here are the other expression AST node definitions that +we'll use in the basic form of the Kaleidoscope language: + +.. code-block:: ocaml + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + +This is all (intentionally) rather straight-forward: variables capture +the variable name, binary operators capture their opcode (e.g. '+'), and +calls capture a function name as well as a list of any argument +expressions. One thing that is nice about our AST is that it captures +the language features without talking about the syntax of the language. +Note that there is no discussion about precedence of binary operators, +lexical structure, etc. + +For our basic language, these are all of the expression nodes we'll +define. Because it doesn't have conditional control flow, it isn't +Turing-complete; we'll fix that in a later installment. The two things +we need next are a way to talk about the interface to a function, and a +way to talk about functions themselves: + +.. code-block:: ocaml + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = Prototype of string * string array + + (* func - This type represents a function definition itself. *) + type func = Function of proto * expr + +In Kaleidoscope, functions are typed with just a count of their +arguments. Since all values are double precision floating point, the +type of each argument doesn't need to be stored anywhere. In a more +aggressive and realistic language, the "expr" variants would probably +have a type field. + +With this scaffolding, we can now talk about parsing expressions and +function bodies in Kaleidoscope. + +Parser Basics +============= + +Now that we have an AST to build, we need to define the parser code to +build it. The idea here is that we want to parse something like "x+y" +(which is returned as three tokens by the lexer) into an AST that could +be generated with calls like this: + +.. code-block:: ocaml + + let x = Variable "x" in + let y = Variable "y" in + let result = Binary ('+', x, y) in + ... + +The error handling routines make use of the builtin ``Stream.Failure`` +and ``Stream.Error``s. ``Stream.Failure`` is raised when the parser is +unable to find any matching token in the first position of a pattern. +``Stream.Error`` is raised when the first token matches, but the rest do +not. The error recovery in our parser will not be the best and is not +particular user-friendly, but it will be enough for our tutorial. These +exceptions make it easier to handle errors in routines that have various +return types. + +With these basic types and exceptions, we can implement the first piece +of our grammar: numeric literals. + +Basic Expression Parsing +======================== + +We start with numeric literals, because they are the simplest to +process. For each production in our grammar, we'll define a function +which parses that production. We call this class of expressions +"primary" expressions, for reasons that will become more clear `later in +the tutorial `_. In order to parse an +arbitrary primary expression, we need to determine what sort of +expression it is. For numeric literals, we have: + +.. code-block:: ocaml + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) + parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + +This routine is very simple: it expects to be called when the current +token is a ``Token.Number`` token. It takes the current number value, +creates a ``Ast.Number`` node, advances the lexer to the next token, and +finally returns. + +There are some interesting aspects to this. The most important one is +that this routine eats all of the tokens that correspond to the +production and returns the lexer buffer with the next token (which is +not part of the grammar production) ready to go. This is a fairly +standard way to go for recursive descent parsers. For a better example, +the parenthesis operator is defined like this: + +.. code-block:: ocaml + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + +This function illustrates a number of interesting things about the +parser: + +1) It shows how we use the ``Stream.Error`` exception. When called, this +function expects that the current token is a '(' token, but after +parsing the subexpression, it is possible that there is no ')' waiting. +For example, if the user types in "(4 x" instead of "(4)", the parser +should emit an error. Because errors can occur, the parser needs a way +to indicate that they happened. In our parser, we use the camlp4 +shortcut syntax ``token ?? "parse error"``, where if the token before +the ``??`` does not match, then ``Stream.Error "parse error"`` will be +raised. + +2) Another interesting aspect of this function is that it uses recursion +by calling ``Parser.parse_primary`` (we will soon see that +``Parser.parse_primary`` can call ``Parser.parse_primary``). This is +powerful because it allows us to handle recursive grammars, and keeps +each production very simple. Note that parentheses do not cause +construction of AST nodes themselves. While we could do it this way, the +most important role of parentheses are to guide the parser and provide +grouping. Once the parser constructs the AST, parentheses are not +needed. + +The next simple production is for handling variable references and +function calls: + +.. code-block:: ocaml + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + +This routine follows the same style as the other routines. (It expects +to be called if the current token is a ``Token.Ident`` token). It also +has recursion and error handling. One interesting aspect of this is that +it uses *look-ahead* to determine if the current identifier is a stand +alone variable reference or if it is a function call expression. It +handles this by checking to see if the token after the identifier is a +'(' token, constructing either a ``Ast.Variable`` or ``Ast.Call`` node +as appropriate. + +We finish up by raising an exception if we received a token we didn't +expect: + +.. code-block:: ocaml + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +Now that basic expressions are handled, we need to handle binary +expressions. They are a bit more complex. + +Binary Expression Parsing +========================= + +Binary expressions are significantly harder to parse because they are +often ambiguous. For example, when given the string "x+y\*z", the parser +can choose to parse it as either "(x+y)\*z" or "x+(y\*z)". With common +definitions from mathematics, we expect the later parse, because "\*" +(multiplication) has higher *precedence* than "+" (addition). + +There are many ways to handle this, but an elegant and efficient way is +to use `Operator-Precedence +Parsing `_. +This parsing technique uses the precedence of binary operators to guide +recursion. To start with, we need a table of precedences: + +.. code-block:: ocaml + + (* binop_precedence - This holds the precedence for each binary operator that is + * defined *) + let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + + (* precedence - Get the precedence of the pending binary operator token. *) + let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + + ... + + let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + ... + +For the basic form of Kaleidoscope, we will only support 4 binary +operators (this can obviously be extended by you, our brave and intrepid +reader). The ``Parser.precedence`` function returns the precedence for +the current token, or -1 if the token is not a binary operator. Having a +``Hashtbl.t`` makes it easy to add new operators and makes it clear that +the algorithm doesn't depend on the specific operators involved, but it +would be easy enough to eliminate the ``Hashtbl.t`` and do the +comparisons in the ``Parser.precedence`` function. (Or just use a +fixed-size array). + +With the helper above defined, we can now start parsing binary +expressions. The basic idea of operator precedence parsing is to break +down an expression with potentially ambiguous binary operators into +pieces. Consider ,for example, the expression "a+b+(c+d)\*e\*f+g". +Operator precedence parsing considers this as a stream of primary +expressions separated by binary operators. As such, it will first parse +the leading primary expression "a", then it will see the pairs [+, b] +[+, (c+d)] [\*, e] [\*, f] and [+, g]. Note that because parentheses are +primary expressions, the binary expression parser doesn't need to worry +about nested subexpressions like (c+d) at all. + +To start, an expression is a primary expression potentially followed by +a sequence of [binop,primaryexpr] pairs: + +.. code-block:: ocaml + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + +``Parser.parse_bin_rhs`` is the function that parses the sequence of +pairs for us. It takes a precedence and a pointer to an expression for +the part that has been parsed so far. Note that "x" is a perfectly valid +expression: As such, "binoprhs" is allowed to be empty, in which case it +returns the expression that is passed into it. In our example above, the +code passes the expression for "a" into ``Parser.parse_bin_rhs`` and the +current token is "+". + +The precedence value passed into ``Parser.parse_bin_rhs`` indicates the +*minimal operator precedence* that the function is allowed to eat. For +example, if the current pair stream is [+, x] and +``Parser.parse_bin_rhs`` is passed in a precedence of 40, it will not +consume any tokens (because the precedence of '+' is only 20). With this +in mind, ``Parser.parse_bin_rhs`` starts with: + +.. code-block:: ocaml + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + +This code gets the precedence of the current token and checks to see if +if is too low. Because we defined invalid tokens to have a precedence of +-1, this check implicitly knows that the pair-stream ends when the token +stream runs out of binary operators. If this check succeeds, we know +that the token is a binary operator and that it will be included in this +expression: + +.. code-block:: ocaml + + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + +As such, this code eats (and remembers) the binary operator and then +parses the primary expression that follows. This builds up the whole +pair, the first of which is [+, b] for the running example. + +Now that we parsed the left-hand side of an expression and one pair of +the RHS sequence, we have to decide which way the expression associates. +In particular, we could have "(a+b) binop unparsed" or "a + (b binop +unparsed)". To determine this, we look ahead at "binop" to determine its +precedence and compare it to BinOp's precedence (which is '+' in this +case): + +.. code-block:: ocaml + + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + +If the precedence of the binop to the right of "RHS" is lower or equal +to the precedence of our current operator, then we know that the +parentheses associate as "(a+b) binop ...". In our example, the current +operator is "+" and the next operator is "+", we know that they have the +same precedence. In this case we'll create the AST node for "a+b", and +then continue parsing: + +.. code-block:: ocaml + + ... if body omitted ... + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + +In our example above, this will turn "a+b+" into "(a+b)" and execute the +next iteration of the loop, with "+" as the current token. The code +above will eat, remember, and parse "(c+d)" as the primary expression, +which makes the current pair equal to [+, (c+d)]. It will then evaluate +the 'if' conditional above with "\*" as the binop to the right of the +primary. In this case, the precedence of "\*" is higher than the +precedence of "+" so the if condition will be entered. + +The critical question left here is "how can the if condition parse the +right hand side in full"? In particular, to build the AST correctly for +our example, it needs to get all of "(c+d)\*e\*f" as the RHS expression +variable. The code to do this is surprisingly simple (code from the +above two blocks duplicated for context): + +.. code-block:: ocaml + + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + if token_prec < precedence c2 + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + +At this point, we know that the binary operator to the RHS of our +primary has higher precedence than the binop we are currently parsing. +As such, we know that any sequence of pairs whose operators are all +higher precedence than "+" should be parsed together and returned as +"RHS". To do this, we recursively invoke the ``Parser.parse_bin_rhs`` +function specifying "token\_prec+1" as the minimum precedence required +for it to continue. In our example above, this will cause it to return +the AST node for "(c+d)\*e\*f" as RHS, which is then set as the RHS of +the '+' expression. + +Finally, on the next iteration of the while loop, the "+g" piece is +parsed and added to the AST. With this little bit of code (14 +non-trivial lines), we correctly handle fully general binary expression +parsing in a very elegant way. This was a whirlwind tour of this code, +and it is somewhat subtle. I recommend running through it with a few +tough examples to see how it works. + +This wraps up handling of expressions. At this point, we can point the +parser at an arbitrary token stream and build an expression from it, +stopping at the first token that is not part of the expression. Next up +we need to handle function definitions, etc. + +Parsing the Rest +================ + +The next thing missing is handling of function prototypes. In +Kaleidoscope, these are used both for 'extern' function declarations as +well as function body definitions. The code to do this is +straight-forward and not very interesting (once you've survived +expressions): + +.. code-block:: ocaml + + (* prototype + * ::= id '(' id* ')' *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +Given this, a function definition is very simple, just a prototype plus +an expression to implement the body: + +.. code-block:: ocaml + + (* definition ::= 'def' prototype expression *) + let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +In addition, we support 'extern' to declare functions like 'sin' and +'cos' as well as to support forward declaration of user functions. These +'extern's are just prototypes with no body: + +.. code-block:: ocaml + + (* external ::= 'extern' prototype *) + let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e + +Finally, we'll also let the user type in arbitrary top-level expressions +and evaluate them on the fly. We will handle this by defining anonymous +nullary (zero argument) functions for them: + +.. code-block:: ocaml + + (* toplevelexpr ::= expression *) + let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +Now that we have all the pieces, let's build a little driver that will +let us actually *execute* this code we've built! + +The Driver +========== + +The driver for this simply invokes all of the parsing pieces with a +top-level dispatch loop. There isn't much interesting here, so I'll just +include the top-level loop. See `below <#code>`_ for full code in the +"Top-Level Parsing" section. + +.. code-block:: ocaml + + (* top ::= definition | external | expression | ';' *) + let rec main_loop stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop stream + + | Some token -> + begin + try match token with + | Token.Def -> + ignore(Parser.parse_definition stream); + print_endline "parsed a function definition."; + | Token.Extern -> + ignore(Parser.parse_extern stream); + print_endline "parsed an extern."; + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + ignore(Parser.parse_toplevel stream); + print_endline "parsed a top-level expr"; + with Stream.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop stream + +The most interesting part of this is that we ignore top-level +semicolons. Why is this, you ask? The basic reason is that if you type +"4 + 5" at the command line, the parser doesn't know whether that is the +end of what you will type or not. For example, on the next line you +could type "def foo..." in which case 4+5 is the end of a top-level +expression. Alternatively you could type "\* 6", which would continue +the expression. Having top-level semicolons allows you to type "4+5;", +and the parser will know you are done. + +Conclusions +=========== + +With just under 300 lines of commented code (240 lines of non-comment, +non-blank code), we fully defined our minimal language, including a +lexer, parser, and AST builder. With this done, the executable will +validate Kaleidoscope code and tell us if it is grammatically invalid. +For example, here is a sample interaction: + +.. code-block:: bash + + $ ./toy.byte + ready> def foo(x y) x+foo(y, 4.0); + Parsed a function definition. + ready> def foo(x y) x+y y; + Parsed a function definition. + Parsed a top-level expr + ready> def foo(x y) x+y ); + Parsed a function definition. + Error: unknown token when expecting an expression + ready> extern sin(a); + ready> Parsed an extern + ready> ^D + $ + +There is a lot of room for extension here. You can define new AST nodes, +extend the language in many ways, etc. In the `next +installment `_, we will describe how to generate +LLVM Intermediate Representation (IR) from the AST. + +Full Code Listing +================= + +Here is the complete code listing for this and the previous chapter. +Note that it is fully self-contained: you don't need LLVM or any +external libraries at all for this. (Besides the ocaml standard +libraries, of course.) To build this, just compile with: + +.. code-block:: bash + + # Compile + ocamlbuild toy.byte + # Run + ./toy.byte + +Here is the code: + +\_tags: + :: + + <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) + +token.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + + (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) + type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + +lexer.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + + let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + + and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + + and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + + and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] + +ast.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + + (* expr - Base type for all expression nodes. *) + type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = Prototype of string * string array + + (* func - This type represents a function definition itself. *) + type func = Function of proto * expr + +parser.ml: + .. code-block:: ocaml + + (*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + + (* binop_precedence - This holds the precedence for each binary operator that is + * defined *) + let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + + (* precedence - Get the precedence of the pending binary operator token. *) + let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) + let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + + (* prototype + * ::= id '(' id* ')' *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + + (* definition ::= 'def' prototype expression *) + let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + + (* toplevelexpr ::= expression *) + let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + + (* external ::= 'extern' prototype *) + let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e + +toplevel.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + + (* top ::= definition | external | expression | ';' *) + let rec main_loop stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop stream + + | Some token -> + begin + try match token with + | Token.Def -> + ignore(Parser.parse_definition stream); + print_endline "parsed a function definition."; + | Token.Extern -> + ignore(Parser.parse_extern stream); + print_endline "parsed an extern."; + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + ignore(Parser.parse_toplevel stream); + print_endline "parsed a top-level expr"; + with Stream.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop stream + +toy.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + + let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop stream; + ;; + + main () + +`Next: Implementing Code Generation to LLVM IR `_ + diff --git a/docs/tutorial/OCamlLangImpl3.rst b/docs/tutorial/OCamlLangImpl3.rst new file mode 100644 index 00000000..fd9f0e5c --- /dev/null +++ b/docs/tutorial/OCamlLangImpl3.rst @@ -0,0 +1,961 @@ +======================================== +Kaleidoscope: Code generation to LLVM IR +======================================== + +.. contents:: + :local: + +Chapter 3 Introduction +====================== + +Welcome to Chapter 3 of the "`Implementing a language with +LLVM `_" tutorial. This chapter shows you how to transform +the `Abstract Syntax Tree `_, built in Chapter 2, +into LLVM IR. This will teach you a little bit about how LLVM does +things, as well as demonstrate how easy it is to use. It's much more +work to build a lexer and parser than it is to generate LLVM IR code. :) + +**Please note**: the code in this chapter and later require LLVM 2.3 or +LLVM SVN to work. LLVM 2.2 and before will not work with it. + +Code Generation Setup +===================== + +In order to generate LLVM IR, we want some simple setup to get started. +First we define virtual code generation (codegen) methods in each AST +class: + +.. code-block:: ocaml + + let rec codegen_expr = function + | Ast.Number n -> ... + | Ast.Variable name -> ... + +The ``Codegen.codegen_expr`` function says to emit IR for that AST node +along with all the things it depends on, and they all return an LLVM +Value object. "Value" is the class used to represent a "`Static Single +Assignment +(SSA) `_ +register" or "SSA value" in LLVM. The most distinct aspect of SSA values +is that their value is computed as the related instruction executes, and +it does not get a new value until (and if) the instruction re-executes. +In other words, there is no way to "change" an SSA value. For more +information, please read up on `Static Single +Assignment `_ +- the concepts are really quite natural once you grok them. + +The second thing we want is an "Error" exception like we used for the +parser, which will be used to report errors found during code generation +(for example, use of an undeclared parameter): + +.. code-block:: ocaml + + exception Error of string + + let context = global_context () + let the_module = create_module context "my cool jit" + let builder = builder context + let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 + let double_type = double_type context + +The static variables will be used during code generation. +``Codgen.the_module`` is the LLVM construct that contains all of the +functions and global variables in a chunk of code. In many ways, it is +the top-level structure that the LLVM IR uses to contain code. + +The ``Codegen.builder`` object is a helper object that makes it easy to +generate LLVM instructions. Instances of the +```IRBuilder`` `_ +class keep track of the current place to insert instructions and has +methods to create new instructions. + +The ``Codegen.named_values`` map keeps track of which values are defined +in the current scope and what their LLVM representation is. (In other +words, it is a symbol table for the code). In this form of Kaleidoscope, +the only things that can be referenced are function parameters. As such, +function parameters will be in this map when generating code for their +function body. + +With these basics in place, we can start talking about how to generate +code for each expression. Note that this assumes that the +``Codgen.builder`` has been set up to generate code *into* something. +For now, we'll assume that this has already been done, and we'll just +use it to emit code. + +Expression Code Generation +========================== + +Generating LLVM code for expression nodes is very straightforward: less +than 30 lines of commented code for all four of our expression nodes. +First we'll do numeric literals: + +.. code-block:: ocaml + + | Ast.Number n -> const_float double_type n + +In the LLVM IR, numeric constants are represented with the +``ConstantFP`` class, which holds the numeric value in an ``APFloat`` +internally (``APFloat`` has the capability of holding floating point +constants of Arbitrary Precision). This code basically just creates +and returns a ``ConstantFP``. Note that in the LLVM IR that constants +are all uniqued together and shared. For this reason, the API uses "the +foo::get(..)" idiom instead of "new foo(..)" or "foo::Create(..)". + +.. code-block:: ocaml + + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + +References to variables are also quite simple using LLVM. In the simple +version of Kaleidoscope, we assume that the variable has already been +emitted somewhere and its value is available. In practice, the only +values that can be in the ``Codegen.named_values`` map are function +arguments. This code simply checks to see that the specified name is in +the map (if not, an unknown variable is being referenced) and returns +the value for it. In future chapters, we'll add support for `loop +induction variables `_ in the symbol table, and for +`local variables `_. + +.. code-block:: ocaml + + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_fadd lhs_val rhs_val "addtmp" builder + | '-' -> build_fsub lhs_val rhs_val "subtmp" builder + | '*' -> build_fmul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + +Binary operators start to get more interesting. The basic idea here is +that we recursively emit code for the left-hand side of the expression, +then the right-hand side, then we compute the result of the binary +expression. In this code, we do a simple switch on the opcode to create +the right LLVM instruction. + +In the example above, the LLVM builder class is starting to show its +value. IRBuilder knows where to insert the newly created instruction, +all you have to do is specify what instruction to create (e.g. with +``Llvm.create_add``), which operands to use (``lhs`` and ``rhs`` here) +and optionally provide a name for the generated instruction. + +One nice thing about LLVM is that the name is just a hint. For instance, +if the code above emits multiple "addtmp" variables, LLVM will +automatically provide each one with an increasing, unique numeric +suffix. Local value names for instructions are purely optional, but it +makes it much easier to read the IR dumps. + +`LLVM instructions <../LangRef.html#instref>`_ are constrained by strict +rules: for example, the Left and Right operators of an `add +instruction <../LangRef.html#i_add>`_ must have the same type, and the +result type of the add must match the operand types. Because all values +in Kaleidoscope are doubles, this makes for very simple code for add, +sub and mul. + +On the other hand, LLVM specifies that the `fcmp +instruction <../LangRef.html#i_fcmp>`_ always returns an 'i1' value (a +one bit integer). The problem with this is that Kaleidoscope wants the +value to be a 0.0 or 1.0 value. In order to get these semantics, we +combine the fcmp instruction with a `uitofp +instruction <../LangRef.html#i_uitofp>`_. This instruction converts its +input integer into a floating point value by treating the input as an +unsigned value. In contrast, if we used the `sitofp +instruction <../LangRef.html#i_sitofp>`_, the Kaleidoscope '<' operator +would return 0.0 and -1.0, depending on the input value. + +.. code-block:: ocaml + + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + +Code generation for function calls is quite straightforward with LLVM. +The code above initially does a function name lookup in the LLVM +Module's symbol table. Recall that the LLVM Module is the container that +holds all of the functions we are JIT'ing. By giving each function the +same name as what the user specifies, we can use the LLVM symbol table +to resolve function names for us. + +Once we have the function to call, we recursively codegen each argument +that is to be passed in, and create an LLVM `call +instruction <../LangRef.html#i_call>`_. Note that LLVM uses the native C +calling conventions by default, allowing these calls to also call into +standard library functions like "sin" and "cos", with no additional +effort. + +This wraps up our handling of the four basic expressions that we have so +far in Kaleidoscope. Feel free to go in and add some more. For example, +by browsing the `LLVM language reference <../LangRef.html>`_ you'll find +several other interesting instructions that are really easy to plug into +our basic framework. + +Function Code Generation +======================== + +Code generation for prototypes and functions must handle a number of +details, which make their code less beautiful than expression code +generation, but allows us to illustrate some important points. First, +lets talk about code generation for prototypes: they are used both for +function bodies and external function declarations. The code starts +with: + +.. code-block:: ocaml + + let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + +This code packs a lot of power into a few lines. Note first that this +function returns a "Function\*" instead of a "Value\*" (although at the +moment they both are modeled by ``llvalue`` in ocaml). Because a +"prototype" really talks about the external interface for a function +(not the value computed by an expression), it makes sense for it to +return the LLVM Function it corresponds to when codegen'd. + +The call to ``Llvm.function_type`` creates the ``Llvm.llvalue`` that +should be used for a given Prototype. Since all function arguments in +Kaleidoscope are of type double, the first line creates a vector of "N" +LLVM double types. It then uses the ``Llvm.function_type`` method to +create a function type that takes "N" doubles as arguments, returns one +double as a result, and that is not vararg (that uses the function +``Llvm.var_arg_function_type``). Note that Types in LLVM are uniqued +just like ``Constant``'s are, so you don't "new" a type, you "get" it. + +The final line above checks if the function has already been defined in +``Codegen.the_module``. If not, we will create it. + +.. code-block:: ocaml + + | None -> declare_function name ft the_module + +This indicates the type and name to use, as well as which module to +insert into. By default we assume a function has +``Llvm.Linkage.ExternalLinkage``. "`external +linkage `_" means that the function may be defined +outside the current module and/or that it is callable by functions +outside the module. The "``name``" passed in is the name the user +specified: this name is registered in "``Codegen.the_module``"s symbol +table, which is used by the function call code above. + +In Kaleidoscope, I choose to allow redefinitions of functions in two +cases: first, we want to allow 'extern'ing a function more than once, as +long as the prototypes for the externs match (since all arguments have +the same type, we just have to check that the number of arguments +match). Second, we want to allow 'extern'ing a function and then +defining a body for it. This is useful when defining mutually recursive +functions. + +.. code-block:: ocaml + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if Array.length (basic_blocks f) == 0 then () else + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if Array.length (params f) == Array.length args then () else + raise (Error "redefinition of function with different # args"); + f + in + +In order to verify the logic above, we first check to see if the +pre-existing function is "empty". In this case, empty means that it has +no basic blocks in it, which means it has no body. If it has no body, it +is a forward declaration. Since we don't allow anything after a full +definition of the function, the code rejects this case. If the previous +reference to a function was an 'extern', we simply verify that the +number of arguments for that definition and this one match up. If not, +we emit an error. + +.. code-block:: ocaml + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + +The last bit of code for prototypes loops over all of the arguments in +the function, setting the name of the LLVM Argument objects to match, +and registering the arguments in the ``Codegen.named_values`` map for +future use by the ``Ast.Variable`` variant. Once this is set up, it +returns the Function object to the caller. Note that we don't check for +conflicting argument names here (e.g. "extern foo(a b a)"). Doing so +would be very straight-forward with the mechanics we have already used +above. + +.. code-block:: ocaml + + let codegen_func = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + +Code generation for function definitions starts out simply enough: we +just codegen the prototype (Proto) and verify that it is ok. We then +clear out the ``Codegen.named_values`` map to make sure that there isn't +anything in it from the last function we compiled. Code generation of +the prototype ensures that there is an LLVM Function object that is +ready to go for us. + +.. code-block:: ocaml + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + +Now we get to the point where the ``Codegen.builder`` is set up. The +first line creates a new `basic +block `_ (named "entry"), +which is inserted into ``the_function``. The second line then tells the +builder that new instructions should be inserted into the end of the new +basic block. Basic blocks in LLVM are an important part of functions +that define the `Control Flow +Graph `_. Since we +don't have any control flow, our functions will only contain one block +at this point. We'll fix this in `Chapter 5 `_ :). + +.. code-block:: ocaml + + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + the_function + +Once the insertion point is set up, we call the ``Codegen.codegen_func`` +method for the root expression of the function. If no error happens, +this emits code to compute the expression into the entry block and +returns the value that was computed. Assuming no error, we then create +an LLVM `ret instruction <../LangRef.html#i_ret>`_, which completes the +function. Once the function is built, we call +``Llvm_analysis.assert_valid_function``, which is provided by LLVM. This +function does a variety of consistency checks on the generated code, to +determine if our compiler is doing everything right. Using this is +important: it can catch a lot of bugs. Once the function is finished and +validated, we return it. + +.. code-block:: ocaml + + with e -> + delete_function the_function; + raise e + +The only piece left here is handling of the error case. For simplicity, +we handle this by merely deleting the function we produced with the +``Llvm.delete_function`` method. This allows the user to redefine a +function that they incorrectly typed in before: if we didn't delete it, +it would live in the symbol table, with a body, preventing future +redefinition. + +This code does have a bug, though. Since the ``Codegen.codegen_proto`` +can return a previously defined forward declaration, our code can +actually delete a forward declaration. There are a number of ways to fix +this bug, see what you can come up with! Here is a testcase: + +:: + + extern foo(a b); # ok, defines foo. + def foo(a b) c; # error, 'c' is invalid. + def bar() foo(1, 2); # error, unknown function "foo" + +Driver Changes and Closing Thoughts +=================================== + +For now, code generation to LLVM doesn't really get us much, except that +we can look at the pretty IR calls. The sample code inserts calls to +Codegen into the "``Toplevel.main_loop``", and then dumps out the LLVM +IR. This gives a nice way to look at the LLVM IR for simple functions. +For example: + +:: + + ready> 4+5; + Read top-level expression: + define double @""() { + entry: + %addtmp = fadd double 4.000000e+00, 5.000000e+00 + ret double %addtmp + } + +Note how the parser turns the top-level expression into anonymous +functions for us. This will be handy when we add `JIT +support `_ in the next chapter. Also note that +the code is very literally transcribed, no optimizations are being +performed. We will `add +optimizations `_ explicitly in the +next chapter. + +:: + + ready> def foo(a b) a*a + 2*a*b + b*b; + Read function definition: + define double @foo(double %a, double %b) { + entry: + %multmp = fmul double %a, %a + %multmp1 = fmul double 2.000000e+00, %a + %multmp2 = fmul double %multmp1, %b + %addtmp = fadd double %multmp, %multmp2 + %multmp3 = fmul double %b, %b + %addtmp4 = fadd double %addtmp, %multmp3 + ret double %addtmp4 + } + +This shows some simple arithmetic. Notice the striking similarity to the +LLVM builder calls that we use to create the instructions. + +:: + + ready> def bar(a) foo(a, 4.0) + bar(31337); + Read function definition: + define double @bar(double %a) { + entry: + %calltmp = call double @foo(double %a, double 4.000000e+00) + %calltmp1 = call double @bar(double 3.133700e+04) + %addtmp = fadd double %calltmp, %calltmp1 + ret double %addtmp + } + +This shows some function calls. Note that this function will take a long +time to execute if you call it. In the future we'll add conditional +control flow to actually make recursion useful :). + +:: + + ready> extern cos(x); + Read extern: + declare double @cos(double) + + ready> cos(1.234); + Read top-level expression: + define double @""() { + entry: + %calltmp = call double @cos(double 1.234000e+00) + ret double %calltmp + } + +This shows an extern for the libm "cos" function, and a call to it. + +:: + + ready> ^D + ; ModuleID = 'my cool jit' + + define double @""() { + entry: + %addtmp = fadd double 4.000000e+00, 5.000000e+00 + ret double %addtmp + } + + define double @foo(double %a, double %b) { + entry: + %multmp = fmul double %a, %a + %multmp1 = fmul double 2.000000e+00, %a + %multmp2 = fmul double %multmp1, %b + %addtmp = fadd double %multmp, %multmp2 + %multmp3 = fmul double %b, %b + %addtmp4 = fadd double %addtmp, %multmp3 + ret double %addtmp4 + } + + define double @bar(double %a) { + entry: + %calltmp = call double @foo(double %a, double 4.000000e+00) + %calltmp1 = call double @bar(double 3.133700e+04) + %addtmp = fadd double %calltmp, %calltmp1 + ret double %addtmp + } + + declare double @cos(double) + + define double @""() { + entry: + %calltmp = call double @cos(double 1.234000e+00) + ret double %calltmp + } + +When you quit the current demo, it dumps out the IR for the entire +module generated. Here you can see the big picture with all the +functions referencing each other. + +This wraps up the third chapter of the Kaleidoscope tutorial. Up next, +we'll describe how to `add JIT codegen and optimizer +support `_ to this so we can actually start running +code! + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the LLVM code generator. Because this uses the LLVM libraries, we need +to link them in. To do this, we use the +`llvm-config `_ tool to inform +our makefile/command line about which options to use: + +.. code-block:: bash + + # Compile + ocamlbuild toy.byte + # Run + ./toy.byte + +Here is the code: + +\_tags: + :: + + <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) + <*.{byte,native}>: g++, use_llvm, use_llvm_analysis + +myocamlbuild.ml: + .. code-block:: ocaml + + open Ocamlbuild_plugin;; + + ocaml_lib ~extern:true "llvm";; + ocaml_lib ~extern:true "llvm_analysis";; + + flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; + +token.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + + (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) + type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + +lexer.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + + let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + + and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + + and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + + and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] + +ast.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + + (* expr - Base type for all expression nodes. *) + type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = Prototype of string * string array + + (* func - This type represents a function definition itself. *) + type func = Function of proto * expr + +parser.ml: + .. code-block:: ocaml + + (*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + + (* binop_precedence - This holds the precedence for each binary operator that is + * defined *) + let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + + (* precedence - Get the precedence of the pending binary operator token. *) + let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) + let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + + (* prototype + * ::= id '(' id* ')' *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + + (* definition ::= 'def' prototype expression *) + let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + + (* toplevelexpr ::= expression *) + let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + + (* external ::= 'extern' prototype *) + let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e + +codegen.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + + open Llvm + + exception Error of string + + let context = global_context () + let the_module = create_module context "my cool jit" + let builder = builder context + let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 + let double_type = double_type context + + let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + + let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + + let codegen_func = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + the_function + with e -> + delete_function the_function; + raise e + +toplevel.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + + open Llvm + + (* top ::= definition | external | expression | ';' *) + let rec main_loop stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + dump_value (Codegen.codegen_func e); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop stream + +toy.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + + open Llvm + + let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module + ;; + + main () + +`Next: Adding JIT and Optimizer Support `_ + diff --git a/docs/tutorial/OCamlLangImpl4.rst b/docs/tutorial/OCamlLangImpl4.rst new file mode 100644 index 00000000..b13b2afa --- /dev/null +++ b/docs/tutorial/OCamlLangImpl4.rst @@ -0,0 +1,915 @@ +============================================== +Kaleidoscope: Adding JIT and Optimizer Support +============================================== + +.. contents:: + :local: + +Chapter 4 Introduction +====================== + +Welcome to Chapter 4 of the "`Implementing a language with +LLVM `_" tutorial. Chapters 1-3 described the implementation +of a simple language and added support for generating LLVM IR. This +chapter describes two new techniques: adding optimizer support to your +language, and adding JIT compiler support. These additions will +demonstrate how to get nice, efficient code for the Kaleidoscope +language. + +Trivial Constant Folding +======================== + +**Note:** the default ``IRBuilder`` now always includes the constant +folding optimisations below. + +Our demonstration for Chapter 3 is elegant and easy to extend. +Unfortunately, it does not produce wonderful code. For example, when +compiling simple code, we don't get obvious optimizations: + +:: + + ready> def test(x) 1+2+x; + Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double 1.000000e+00, 2.000000e+00 + %addtmp1 = fadd double %addtmp, %x + ret double %addtmp1 + } + +This code is a very, very literal transcription of the AST built by +parsing the input. As such, this transcription lacks optimizations like +constant folding (we'd like to get "``add x, 3.0``" in the example +above) as well as other more important optimizations. Constant folding, +in particular, is a very common and very important optimization: so much +so that many language implementors implement constant folding support in +their AST representation. + +With LLVM, you don't need this support in the AST. Since all calls to +build LLVM IR go through the LLVM builder, it would be nice if the +builder itself checked to see if there was a constant folding +opportunity when you call it. If so, it could just do the constant fold +and return the constant instead of creating an instruction. This is +exactly what the ``LLVMFoldingBuilder`` class does. + +All we did was switch from ``LLVMBuilder`` to ``LLVMFoldingBuilder``. +Though we change no other code, we now have all of our instructions +implicitly constant folded without us having to do anything about it. +For example, the input above now compiles to: + +:: + + ready> def test(x) 1+2+x; + Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double 3.000000e+00, %x + ret double %addtmp + } + +Well, that was easy :). In practice, we recommend always using +``LLVMFoldingBuilder`` when generating code like this. It has no +"syntactic overhead" for its use (you don't have to uglify your compiler +with constant checks everywhere) and it can dramatically reduce the +amount of LLVM IR that is generated in some cases (particular for +languages with a macro preprocessor or that use a lot of constants). + +On the other hand, the ``LLVMFoldingBuilder`` is limited by the fact +that it does all of its analysis inline with the code as it is built. If +you take a slightly more complex example: + +:: + + ready> def test(x) (1+2+x)*(x+(1+2)); + ready> Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double 3.000000e+00, %x + %addtmp1 = fadd double %x, 3.000000e+00 + %multmp = fmul double %addtmp, %addtmp1 + ret double %multmp + } + +In this case, the LHS and RHS of the multiplication are the same value. +We'd really like to see this generate "``tmp = x+3; result = tmp*tmp;``" +instead of computing "``x*3``" twice. + +Unfortunately, no amount of local analysis will be able to detect and +correct this. This requires two transformations: reassociation of +expressions (to make the add's lexically identical) and Common +Subexpression Elimination (CSE) to delete the redundant add instruction. +Fortunately, LLVM provides a broad range of optimizations that you can +use, in the form of "passes". + +LLVM Optimization Passes +======================== + +LLVM provides many optimization passes, which do many different sorts of +things and have different tradeoffs. Unlike other systems, LLVM doesn't +hold to the mistaken notion that one set of optimizations is right for +all languages and for all situations. LLVM allows a compiler implementor +to make complete decisions about what optimizations to use, in which +order, and in what situation. + +As a concrete example, LLVM supports both "whole module" passes, which +look across as large of body of code as they can (often a whole file, +but if run at link time, this can be a substantial portion of the whole +program). It also supports and includes "per-function" passes which just +operate on a single function at a time, without looking at other +functions. For more information on passes and how they are run, see the +`How to Write a Pass <../WritingAnLLVMPass.html>`_ document and the +`List of LLVM Passes <../Passes.html>`_. + +For Kaleidoscope, we are currently generating functions on the fly, one +at a time, as the user types them in. We aren't shooting for the +ultimate optimization experience in this setting, but we also want to +catch the easy and quick stuff where possible. As such, we will choose +to run a few per-function optimizations as the user types the function +in. If we wanted to make a "static Kaleidoscope compiler", we would use +exactly the code we have now, except that we would defer running the +optimizer until the entire file has been parsed. + +In order to get per-function optimizations going, we need to set up a +`Llvm.PassManager <../WritingAnLLVMPass.html#passmanager>`_ to hold and +organize the LLVM optimizations that we want to run. Once we have that, +we can add a set of optimizations to run. The code looks like this: + +.. code-block:: ocaml + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + DataLayout.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combining the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + +The meat of the matter here, is the definition of "``the_fpm``". It +requires a pointer to the ``the_module`` to construct itself. Once it is +set up, we use a series of "add" calls to add a bunch of LLVM passes. +The first pass is basically boilerplate, it adds a pass so that later +optimizations know how the data structures in the program are laid out. +The "``the_execution_engine``" variable is related to the JIT, which we +will get to in the next section. + +In this case, we choose to add 4 optimization passes. The passes we +chose here are a pretty standard set of "cleanup" optimizations that are +useful for a wide variety of code. I won't delve into what they do but, +believe me, they are a good starting place :). + +Once the ``Llvm.PassManager.`` is set up, we need to make use of it. We +do this by running it after our newly created function is constructed +(in ``Codegen.codegen_func``), but before it is returned to the client: + +.. code-block:: ocaml + + let codegen_func the_fpm = function + ... + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + +As you can see, this is pretty straightforward. The ``the_fpm`` +optimizes and updates the LLVM Function\* in place, improving +(hopefully) its body. With this in place, we can try our test above +again: + +:: + + ready> def test(x) (1+2+x)*(x+(1+2)); + ready> Read function definition: + define double @test(double %x) { + entry: + %addtmp = fadd double %x, 3.000000e+00 + %multmp = fmul double %addtmp, %addtmp + ret double %multmp + } + +As expected, we now get our nicely optimized code, saving a floating +point add instruction from every execution of this function. + +LLVM provides a wide variety of optimizations that can be used in +certain circumstances. Some `documentation about the various +passes <../Passes.html>`_ is available, but it isn't very complete. +Another good source of ideas can come from looking at the passes that +``Clang`` runs to get started. The "``opt``" tool allows you to +experiment with passes from the command line, so you can see if they do +anything. + +Now that we have reasonable code coming out of our front-end, lets talk +about executing it! + +Adding a JIT Compiler +===================== + +Code that is available in LLVM IR can have a wide variety of tools +applied to it. For example, you can run optimizations on it (as we did +above), you can dump it out in textual or binary forms, you can compile +the code to an assembly file (.s) for some target, or you can JIT +compile it. The nice thing about the LLVM IR representation is that it +is the "common currency" between many different parts of the compiler. + +In this section, we'll add JIT compiler support to our interpreter. The +basic idea that we want for Kaleidoscope is to have the user enter +function bodies as they do now, but immediately evaluate the top-level +expressions they type in. For example, if they type in "1 + 2;", we +should evaluate and print out 3. If they define a function, they should +be able to call it from the command line. + +In order to do this, we first declare and initialize the JIT. This is +done by adding a global variable and a call in ``main``: + +.. code-block:: ocaml + + ... + let main () = + ... + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + ... + +This creates an abstract "Execution Engine" which can be either a JIT +compiler or the LLVM interpreter. LLVM will automatically pick a JIT +compiler for you if one is available for your platform, otherwise it +will fall back to the interpreter. + +Once the ``Llvm_executionengine.ExecutionEngine.t`` is created, the JIT +is ready to be used. There are a variety of APIs that are useful, but +the simplest one is the +"``Llvm_executionengine.ExecutionEngine.run_function``" function. This +method JIT compiles the specified LLVM Function and returns a function +pointer to the generated machine code. In our case, this means that we +can change the code that parses a top-level expression to look like +this: + +.. code-block:: ocaml + + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + +Recall that we compile top-level expressions into a self-contained LLVM +function that takes no arguments and returns the computed double. +Because the LLVM JIT compiler matches the native platform ABI, this +means that you can just cast the result pointer to a function pointer of +that type and call it directly. This means, there is no difference +between JIT compiled code and native machine code that is statically +linked into your application. + +With just these two changes, lets see how Kaleidoscope works now! + +:: + + ready> 4+5; + define double @""() { + entry: + ret double 9.000000e+00 + } + + Evaluated to 9.000000 + +Well this looks like it is basically working. The dump of the function +shows the "no argument function that always returns double" that we +synthesize for each top level expression that is typed in. This +demonstrates very basic functionality, but can we do more? + +:: + + ready> def testfunc(x y) x + y*2; + Read function definition: + define double @testfunc(double %x, double %y) { + entry: + %multmp = fmul double %y, 2.000000e+00 + %addtmp = fadd double %multmp, %x + ret double %addtmp + } + + ready> testfunc(4, 10); + define double @""() { + entry: + %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01) + ret double %calltmp + } + + Evaluated to 24.000000 + +This illustrates that we can now call user code, but there is something +a bit subtle going on here. Note that we only invoke the JIT on the +anonymous functions that *call testfunc*, but we never invoked it on +*testfunc* itself. What actually happened here is that the JIT scanned +for all non-JIT'd functions transitively called from the anonymous +function and compiled all of them before returning from +``run_function``. + +The JIT provides a number of other more advanced interfaces for things +like freeing allocated machine code, rejit'ing functions to update them, +etc. However, even with this simple code, we get some surprisingly +powerful capabilities - check this out (I removed the dump of the +anonymous functions, you should get the idea by now :) : + +:: + + ready> extern sin(x); + Read extern: + declare double @sin(double) + + ready> extern cos(x); + Read extern: + declare double @cos(double) + + ready> sin(1.0); + Evaluated to 0.841471 + + ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x); + Read function definition: + define double @foo(double %x) { + entry: + %calltmp = call double @sin(double %x) + %multmp = fmul double %calltmp, %calltmp + %calltmp2 = call double @cos(double %x) + %multmp4 = fmul double %calltmp2, %calltmp2 + %addtmp = fadd double %multmp, %multmp4 + ret double %addtmp + } + + ready> foo(4.0); + Evaluated to 1.000000 + +Whoa, how does the JIT know about sin and cos? The answer is +surprisingly simple: in this example, the JIT started execution of a +function and got to a function call. It realized that the function was +not yet JIT compiled and invoked the standard set of routines to resolve +the function. In this case, there is no body defined for the function, +so the JIT ended up calling "``dlsym("sin")``" on the Kaleidoscope +process itself. Since "``sin``" is defined within the JIT's address +space, it simply patches up calls in the module to call the libm version +of ``sin`` directly. + +The LLVM JIT provides a number of interfaces (look in the +``llvm_executionengine.mli`` file) for controlling how unknown functions +get resolved. It allows you to establish explicit mappings between IR +objects and addresses (useful for LLVM global variables that you want to +map to static tables, for example), allows you to dynamically decide on +the fly based on the function name, and even allows you to have the JIT +compile functions lazily the first time they're called. + +One interesting application of this is that we can now extend the +language by writing arbitrary C code to implement operations. For +example, if we add: + +.. code-block:: c++ + + /* putchard - putchar that takes a double and returns 0. */ + extern "C" + double putchard(double X) { + putchar((char)X); + return 0; + } + +Now we can produce simple output to the console by using things like: +"``extern putchard(x); putchard(120);``", which prints a lowercase 'x' +on the console (120 is the ASCII code for 'x'). Similar code could be +used to implement file I/O, console input, and many other capabilities +in Kaleidoscope. + +This completes the JIT and optimizer chapter of the Kaleidoscope +tutorial. At this point, we can compile a non-Turing-complete +programming language, optimize and JIT compile it in a user-driven way. +Next up we'll look into `extending the language with control flow +constructs `_, tackling some interesting LLVM IR +issues along the way. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the LLVM JIT and optimizer. To build this example, use: + +.. code-block:: bash + + # Compile + ocamlbuild toy.byte + # Run + ./toy.byte + +Here is the code: + +\_tags: + :: + + <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) + <*.{byte,native}>: g++, use_llvm, use_llvm_analysis + <*.{byte,native}>: use_llvm_executionengine, use_llvm_target + <*.{byte,native}>: use_llvm_scalar_opts, use_bindings + +myocamlbuild.ml: + .. code-block:: ocaml + + open Ocamlbuild_plugin;; + + ocaml_lib ~extern:true "llvm";; + ocaml_lib ~extern:true "llvm_analysis";; + ocaml_lib ~extern:true "llvm_executionengine";; + ocaml_lib ~extern:true "llvm_target";; + ocaml_lib ~extern:true "llvm_scalar_opts";; + + flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; + dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; + +token.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + + (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) + type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + +lexer.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + + let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + + and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + + and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + + and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] + +ast.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + + (* expr - Base type for all expression nodes. *) + type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = Prototype of string * string array + + (* func - This type represents a function definition itself. *) + type func = Function of proto * expr + +parser.ml: + .. code-block:: ocaml + + (*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + + (* binop_precedence - This holds the precedence for each binary operator that is + * defined *) + let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + + (* precedence - Get the precedence of the pending binary operator token. *) + let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) + let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + + (* prototype + * ::= id '(' id* ')' *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + + (* definition ::= 'def' prototype expression *) + let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + + (* toplevelexpr ::= expression *) + let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + + (* external ::= 'extern' prototype *) + let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e + +codegen.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + + open Llvm + + exception Error of string + + let context = global_context () + let the_module = create_module context "my cool jit" + let builder = builder context + let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 + let double_type = double_type context + + let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + + let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + + let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e + +toplevel.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + + (* top ::= definition | external | expression | ';' *) + let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream + +toy.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + open Llvm_target + open Llvm_scalar_opts + + let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + DataLayout.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module + ;; + + main () + +bindings.c + .. code-block:: c + + #include + + /* putchard - putchar that takes a double and returns 0. */ + extern double putchard(double X) { + putchar((char)X); + return 0; + } + +`Next: Extending the language: control flow `_ + diff --git a/docs/tutorial/OCamlLangImpl5.rst b/docs/tutorial/OCamlLangImpl5.rst new file mode 100644 index 00000000..b8ae3c58 --- /dev/null +++ b/docs/tutorial/OCamlLangImpl5.rst @@ -0,0 +1,1362 @@ +================================================== +Kaleidoscope: Extending the Language: Control Flow +================================================== + +.. contents:: + :local: + +Chapter 5 Introduction +====================== + +Welcome to Chapter 5 of the "`Implementing a language with +LLVM `_" tutorial. Parts 1-4 described the implementation of +the simple Kaleidoscope language and included support for generating +LLVM IR, followed by optimizations and a JIT compiler. Unfortunately, as +presented, Kaleidoscope is mostly useless: it has no control flow other +than call and return. This means that you can't have conditional +branches in the code, significantly limiting its power. In this episode +of "build that compiler", we'll extend Kaleidoscope to have an +if/then/else expression plus a simple 'for' loop. + +If/Then/Else +============ + +Extending Kaleidoscope to support if/then/else is quite straightforward. +It basically requires adding lexer support for this "new" concept to the +lexer, parser, AST, and LLVM code emitter. This example is nice, because +it shows how easy it is to "grow" a language over time, incrementally +extending it as new ideas are discovered. + +Before we get going on "how" we add this extension, lets talk about +"what" we want. The basic idea is that we want to be able to write this +sort of thing: + +:: + + def fib(x) + if x < 3 then + 1 + else + fib(x-1)+fib(x-2); + +In Kaleidoscope, every construct is an expression: there are no +statements. As such, the if/then/else expression needs to return a value +like any other. Since we're using a mostly functional form, we'll have +it evaluate its conditional, then return the 'then' or 'else' value +based on how the condition was resolved. This is very similar to the C +"?:" expression. + +The semantics of the if/then/else expression is that it evaluates the +condition to a boolean equality value: 0.0 is considered to be false and +everything else is considered to be true. If the condition is true, the +first subexpression is evaluated and returned, if the condition is +false, the second subexpression is evaluated and returned. Since +Kaleidoscope allows side-effects, this behavior is important to nail +down. + +Now that we know what we "want", lets break this down into its +constituent pieces. + +Lexer Extensions for If/Then/Else +--------------------------------- + +The lexer extensions are straightforward. First we add new variants for +the relevant tokens: + +.. code-block:: ocaml + + (* control *) + | If | Then | Else | For | In + +Once we have that, we recognize the new keywords in the lexer. This is +pretty simple stuff: + +.. code-block:: ocaml + + ... + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | id -> [< 'Token.Ident id; stream >] + +AST Extensions for If/Then/Else +------------------------------- + +To represent the new expression we add a new AST variant for it: + +.. code-block:: ocaml + + type expr = + ... + (* variant for if/then/else. *) + | If of expr * expr * expr + +The AST variant just has pointers to the various subexpressions. + +Parser Extensions for If/Then/Else +---------------------------------- + +Now that we have the relevant tokens coming from the lexer and we have +the AST node to build, our parsing logic is relatively straightforward. +First we define a new parsing function: + +.. code-block:: ocaml + + let rec parse_primary = parser + ... + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + +Next we hook it up as a primary expression: + +.. code-block:: ocaml + + let rec parse_primary = parser + ... + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + +LLVM IR for If/Then/Else +------------------------ + +Now that we have it parsing and building the AST, the final piece is +adding LLVM code generation support. This is the most interesting part +of the if/then/else example, because this is where it starts to +introduce new concepts. All of the code above has been thoroughly +described in previous chapters. + +To motivate the code we want to produce, lets take a look at a simple +example. Consider: + +:: + + extern foo(); + extern bar(); + def baz(x) if x then foo() else bar(); + +If you disable optimizations, the code you'll (soon) get from +Kaleidoscope looks like this: + +.. code-block:: llvm + + declare double @foo() + + declare double @bar() + + define double @baz(double %x) { + entry: + %ifcond = fcmp one double %x, 0.000000e+00 + br i1 %ifcond, label %then, label %else + + then: ; preds = %entry + %calltmp = call double @foo() + br label %ifcont + + else: ; preds = %entry + %calltmp1 = call double @bar() + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ] + ret double %iftmp + } + +To visualize the control flow graph, you can use a nifty feature of the +LLVM '`opt `_' tool. If you put this LLVM +IR into "t.ll" and run "``llvm-as < t.ll | opt -analyze -view-cfg``", `a +window will pop up <../ProgrammersManual.html#ViewGraph>`_ and you'll +see this graph: + +.. figure:: LangImpl5-cfg.png + :align: center + :alt: Example CFG + + Example CFG + +Another way to get this is to call +"``Llvm_analysis.view_function_cfg f``" or +"``Llvm_analysis.view_function_cfg_only f``" (where ``f`` is a +"``Function``") either by inserting actual calls into the code and +recompiling or by calling these in the debugger. LLVM has many nice +features for visualizing various graphs. + +Getting back to the generated code, it is fairly simple: the entry block +evaluates the conditional expression ("x" in our case here) and compares +the result to 0.0 with the "``fcmp one``" instruction ('one' is "Ordered +and Not Equal"). Based on the result of this expression, the code jumps +to either the "then" or "else" blocks, which contain the expressions for +the true/false cases. + +Once the then/else blocks are finished executing, they both branch back +to the 'ifcont' block to execute the code that happens after the +if/then/else. In this case the only thing left to do is to return to the +caller of the function. The question then becomes: how does the code +know which expression to return? + +The answer to this question involves an important SSA operation: the +`Phi +operation `_. +If you're not familiar with SSA, `the wikipedia +article `_ +is a good introduction and there are various other introductions to it +available on your favorite search engine. The short version is that +"execution" of the Phi operation requires "remembering" which block +control came from. The Phi operation takes on the value corresponding to +the input control block. In this case, if control comes in from the +"then" block, it gets the value of "calltmp". If control comes from the +"else" block, it gets the value of "calltmp1". + +At this point, you are probably starting to think "Oh no! This means my +simple and elegant front-end will have to start generating SSA form in +order to use LLVM!". Fortunately, this is not the case, and we strongly +advise *not* implementing an SSA construction algorithm in your +front-end unless there is an amazingly good reason to do so. In +practice, there are two sorts of values that float around in code +written for your average imperative programming language that might need +Phi nodes: + +#. Code that involves user variables: ``x = 1; x = x + 1;`` +#. Values that are implicit in the structure of your AST, such as the + Phi node in this case. + +In `Chapter 7 `_ of this tutorial ("mutable +variables"), we'll talk about #1 in depth. For now, just believe me that +you don't need SSA construction to handle this case. For #2, you have +the choice of using the techniques that we will describe for #1, or you +can insert Phi nodes directly, if convenient. In this case, it is really +really easy to generate the Phi node, so we choose to do it directly. + +Okay, enough of the motivation and overview, lets generate code! + +Code Generation for If/Then/Else +-------------------------------- + +In order to generate code for this, we implement the ``Codegen`` method +for ``IfExprAST``: + +.. code-block:: ocaml + + let rec codegen_expr = function + ... + | Ast.If (cond, then_, else_) -> + let cond = codegen_expr cond in + + (* Convert condition to a bool by comparing equal to 0.0 *) + let zero = const_float double_type 0.0 in + let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in + +This code is straightforward and similar to what we saw before. We emit +the expression for the condition, then compare that value to zero to get +a truth value as a 1-bit (bool) value. + +.. code-block:: ocaml + + (* Grab the first block so that we might later add the conditional branch + * to it at the end of the function. *) + let start_bb = insertion_block builder in + let the_function = block_parent start_bb in + + let then_bb = append_block context "then" the_function in + position_at_end then_bb builder; + +As opposed to the `C++ tutorial `_, we have to build our +basic blocks bottom up since we can't have dangling BasicBlocks. We +start off by saving a pointer to the first block (which might not be the +entry block), which we'll need to build a conditional branch later. We +do this by asking the ``builder`` for the current BasicBlock. The fourth +line gets the current Function object that is being built. It gets this +by the ``start_bb`` for its "parent" (the function it is currently +embedded into). + +Once it has that, it creates one block. It is automatically appended +into the function's list of blocks. + +.. code-block:: ocaml + + (* Emit 'then' value. *) + position_at_end then_bb builder; + let then_val = codegen_expr then_ in + + (* Codegen of 'then' can change the current block, update then_bb for the + * phi. We create a new name because one is used for the phi node, and the + * other is used for the conditional branch. *) + let new_then_bb = insertion_block builder in + +We move the builder to start inserting into the "then" block. Strictly +speaking, this call moves the insertion point to be at the end of the +specified block. However, since the "then" block is empty, it also +starts out by inserting at the beginning of the block. :) + +Once the insertion point is set, we recursively codegen the "then" +expression from the AST. + +The final line here is quite subtle, but is very important. The basic +issue is that when we create the Phi node in the merge block, we need to +set up the block/value pairs that indicate how the Phi will work. +Importantly, the Phi node expects to have an entry for each predecessor +of the block in the CFG. Why then, are we getting the current block when +we just set it to ThenBB 5 lines above? The problem is that the "Then" +expression may actually itself change the block that the Builder is +emitting into if, for example, it contains a nested "if/then/else" +expression. Because calling Codegen recursively could arbitrarily change +the notion of the current block, we are required to get an up-to-date +value for code that will set up the Phi node. + +.. code-block:: ocaml + + (* Emit 'else' value. *) + let else_bb = append_block context "else" the_function in + position_at_end else_bb builder; + let else_val = codegen_expr else_ in + + (* Codegen of 'else' can change the current block, update else_bb for the + * phi. *) + let new_else_bb = insertion_block builder in + +Code generation for the 'else' block is basically identical to codegen +for the 'then' block. + +.. code-block:: ocaml + + (* Emit merge block. *) + let merge_bb = append_block context "ifcont" the_function in + position_at_end merge_bb builder; + let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in + let phi = build_phi incoming "iftmp" builder in + +The first two lines here are now familiar: the first adds the "merge" +block to the Function object. The second block changes the insertion +point so that newly created code will go into the "merge" block. Once +that is done, we need to create the PHI node and set up the block/value +pairs for the PHI. + +.. code-block:: ocaml + + (* Return to the start block to add the conditional branch. *) + position_at_end start_bb builder; + ignore (build_cond_br cond_val then_bb else_bb builder); + +Once the blocks are created, we can emit the conditional branch that +chooses between them. Note that creating new blocks does not implicitly +affect the IRBuilder, so it is still inserting into the block that the +condition went into. This is why we needed to save the "start" block. + +.. code-block:: ocaml + + (* Set a unconditional branch at the end of the 'then' block and the + * 'else' block to the 'merge' block. *) + position_at_end new_then_bb builder; ignore (build_br merge_bb builder); + position_at_end new_else_bb builder; ignore (build_br merge_bb builder); + + (* Finally, set the builder to the end of the merge block. *) + position_at_end merge_bb builder; + + phi + +To finish off the blocks, we create an unconditional branch to the merge +block. One interesting (and very important) aspect of the LLVM IR is +that it `requires all basic blocks to be +"terminated" <../LangRef.html#functionstructure>`_ with a `control flow +instruction <../LangRef.html#terminators>`_ such as return or branch. +This means that all control flow, *including fall throughs* must be made +explicit in the LLVM IR. If you violate this rule, the verifier will +emit an error. + +Finally, the CodeGen function returns the phi node as the value computed +by the if/then/else expression. In our example above, this returned +value will feed into the code for the top-level function, which will +create the return instruction. + +Overall, we now have the ability to execute conditional code in +Kaleidoscope. With this extension, Kaleidoscope is a fairly complete +language that can calculate a wide variety of numeric functions. Next up +we'll add another useful expression that is familiar from non-functional +languages... + +'for' Loop Expression +===================== + +Now that we know how to add basic control flow constructs to the +language, we have the tools to add more powerful things. Lets add +something more aggressive, a 'for' expression: + +:: + + extern putchard(char); + def printstar(n) + for i = 1, i < n, 1.0 in + putchard(42); # ascii 42 = '*' + + # print 100 '*' characters + printstar(100); + +This expression defines a new variable ("i" in this case) which iterates +from a starting value, while the condition ("i < n" in this case) is +true, incrementing by an optional step value ("1.0" in this case). If +the step value is omitted, it defaults to 1.0. While the loop is true, +it executes its body expression. Because we don't have anything better +to return, we'll just define the loop as always returning 0.0. In the +future when we have mutable variables, it will get more useful. + +As before, lets talk about the changes that we need to Kaleidoscope to +support this. + +Lexer Extensions for the 'for' Loop +----------------------------------- + +The lexer extensions are the same sort of thing as for if/then/else: + +.. code-block:: ocaml + + ... in Token.token ... + (* control *) + | If | Then | Else + | For | In + + ... in Lexer.lex_ident... + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | id -> [< 'Token.Ident id; stream >] + +AST Extensions for the 'for' Loop +--------------------------------- + +The AST variant is just as simple. It basically boils down to capturing +the variable name and the constituent expressions in the node. + +.. code-block:: ocaml + + type expr = + ... + (* variant for for/in. *) + | For of string * expr * expr * expr option * expr + +Parser Extensions for the 'for' Loop +------------------------------------ + +The parser code is also fairly standard. The only interesting thing here +is handling of the optional step value. The parser code handles it by +checking to see if the second comma is present. If not, it sets the step +value to null in the AST node: + +.. code-block:: ocaml + + let rec parse_primary = parser + ... + (* forexpr + ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) + | [< 'Token.For; + 'Token.Ident id ?? "expected identifier after for"; + 'Token.Kwd '=' ?? "expected '=' after for"; + stream >] -> + begin parser + | [< + start=parse_expr; + 'Token.Kwd ',' ?? "expected ',' after for"; + end_=parse_expr; + stream >] -> + let step = + begin parser + | [< 'Token.Kwd ','; step=parse_expr >] -> Some step + | [< >] -> None + end stream + in + begin parser + | [< 'Token.In; body=parse_expr >] -> + Ast.For (id, start, end_, step, body) + | [< >] -> + raise (Stream.Error "expected 'in' after for") + end stream + | [< >] -> + raise (Stream.Error "expected '=' after for") + end stream + +LLVM IR for the 'for' Loop +-------------------------- + +Now we get to the good part: the LLVM IR we want to generate for this +thing. With the simple example above, we get this LLVM IR (note that +this dump is generated with optimizations disabled for clarity): + +.. code-block:: llvm + + declare double @putchard(double) + + define double @printstar(double %n) { + entry: + ; initial value = 1.0 (inlined into phi) + br label %loop + + loop: ; preds = %loop, %entry + %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ] + ; body + %calltmp = call double @putchard(double 4.200000e+01) + ; increment + %nextvar = fadd double %i, 1.000000e+00 + + ; termination test + %cmptmp = fcmp ult double %i, %n + %booltmp = uitofp i1 %cmptmp to double + %loopcond = fcmp one double %booltmp, 0.000000e+00 + br i1 %loopcond, label %loop, label %afterloop + + afterloop: ; preds = %loop + ; loop always returns 0.0 + ret double 0.000000e+00 + } + +This loop contains all the same constructs we saw before: a phi node, +several expressions, and some basic blocks. Lets see how this fits +together. + +Code Generation for the 'for' Loop +---------------------------------- + +The first part of Codegen is very simple: we just output the start +expression for the loop value: + +.. code-block:: ocaml + + let rec codegen_expr = function + ... + | Ast.For (var_name, start, end_, step, body) -> + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + +With this out of the way, the next step is to set up the LLVM basic +block for the start of the loop body. In the case above, the whole loop +body is one block, but remember that the body code itself could consist +of multiple blocks (e.g. if it contains an if/then/else or a for/in +expression). + +.. code-block:: ocaml + + (* Make the new basic block for the loop header, inserting after current + * block. *) + let preheader_bb = insertion_block builder in + let the_function = block_parent preheader_bb in + let loop_bb = append_block context "loop" the_function in + + (* Insert an explicit fall through from the current block to the + * loop_bb. *) + ignore (build_br loop_bb builder); + +This code is similar to what we saw for if/then/else. Because we will +need it to create the Phi node, we remember the block that falls through +into the loop. Once we have that, we create the actual block that starts +the loop and create an unconditional branch for the fall-through between +the two blocks. + +.. code-block:: ocaml + + (* Start insertion in loop_bb. *) + position_at_end loop_bb builder; + + (* Start the PHI node with an entry for start. *) + let variable = build_phi [(start_val, preheader_bb)] var_name builder in + +Now that the "preheader" for the loop is set up, we switch to emitting +code for the loop body. To begin with, we move the insertion point and +create the PHI node for the loop induction variable. Since we already +know the incoming value for the starting value, we add it to the Phi +node. Note that the Phi will eventually get a second value for the +backedge, but we can't set it up yet (because it doesn't exist!). + +.. code-block:: ocaml + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name variable; + + (* Emit the body of the loop. This, like any other expr, can change the + * current BB. Note that we ignore the value computed by the body, but + * don't allow an error *) + ignore (codegen_expr body); + +Now the code starts to get more interesting. Our 'for' loop introduces a +new variable to the symbol table. This means that our symbol table can +now contain either function arguments or loop variables. To handle this, +before we codegen the body of the loop, we add the loop variable as the +current value for its name. Note that it is possible that there is a +variable of the same name in the outer scope. It would be easy to make +this an error (emit an error and return null if there is already an +entry for VarName) but we choose to allow shadowing of variables. In +order to handle this correctly, we remember the Value that we are +potentially shadowing in ``old_val`` (which will be None if there is no +shadowed variable). + +Once the loop variable is set into the symbol table, the code +recursively codegen's the body. This allows the body to use the loop +variable: any references to it will naturally find it in the symbol +table. + +.. code-block:: ocaml + + (* Emit the step value. *) + let step_val = + match step with + | Some step -> codegen_expr step + (* If not specified, use 1.0. *) + | None -> const_float double_type 1.0 + in + + let next_var = build_add variable step_val "nextvar" builder in + +Now that the body is emitted, we compute the next value of the iteration +variable by adding the step value, or 1.0 if it isn't present. +'``next_var``' will be the value of the loop variable on the next +iteration of the loop. + +.. code-block:: ocaml + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Convert condition to a bool by comparing equal to 0.0. *) + let zero = const_float double_type 0.0 in + let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in + +Finally, we evaluate the exit value of the loop, to determine whether +the loop should exit. This mirrors the condition evaluation for the +if/then/else statement. + +.. code-block:: ocaml + + (* Create the "after loop" block and insert it. *) + let loop_end_bb = insertion_block builder in + let after_bb = append_block context "afterloop" the_function in + + (* Insert the conditional branch into the end of loop_end_bb. *) + ignore (build_cond_br end_cond loop_bb after_bb builder); + + (* Any new code will be inserted in after_bb. *) + position_at_end after_bb builder; + +With the code for the body of the loop complete, we just need to finish +up the control flow for it. This code remembers the end block (for the +phi node), then creates the block for the loop exit ("afterloop"). Based +on the value of the exit condition, it creates a conditional branch that +chooses between executing the loop again and exiting the loop. Any +future code is emitted in the "afterloop" block, so it sets the +insertion position to it. + +.. code-block:: ocaml + + (* Add a new entry to the PHI node for the backedge. *) + add_incoming (next_var, loop_end_bb) variable; + + (* Restore the unshadowed variable. *) + begin match old_val with + | Some old_val -> Hashtbl.add named_values var_name old_val + | None -> () + end; + + (* for expr always returns 0.0. *) + const_null double_type + +The final code handles various cleanups: now that we have the +"``next_var``" value, we can add the incoming value to the loop PHI +node. After that, we remove the loop variable from the symbol table, so +that it isn't in scope after the for loop. Finally, code generation of +the for loop always returns 0.0, so that is what we return from +``Codegen.codegen_expr``. + +With this, we conclude the "adding control flow to Kaleidoscope" chapter +of the tutorial. In this chapter we added two control flow constructs, +and used them to motivate a couple of aspects of the LLVM IR that are +important for front-end implementors to know. In the next chapter of our +saga, we will get a bit crazier and add `user-defined +operators `_ to our poor innocent language. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the if/then/else and for expressions.. To build this example, use: + +.. code-block:: bash + + # Compile + ocamlbuild toy.byte + # Run + ./toy.byte + +Here is the code: + +\_tags: + :: + + <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) + <*.{byte,native}>: g++, use_llvm, use_llvm_analysis + <*.{byte,native}>: use_llvm_executionengine, use_llvm_target + <*.{byte,native}>: use_llvm_scalar_opts, use_bindings + +myocamlbuild.ml: + .. code-block:: ocaml + + open Ocamlbuild_plugin;; + + ocaml_lib ~extern:true "llvm";; + ocaml_lib ~extern:true "llvm_analysis";; + ocaml_lib ~extern:true "llvm_executionengine";; + ocaml_lib ~extern:true "llvm_target";; + ocaml_lib ~extern:true "llvm_scalar_opts";; + + flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; + dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; + +token.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + + (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) + type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + + (* control *) + | If | Then | Else + | For | In + +lexer.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + + let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + + and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + + and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | id -> [< 'Token.Ident id; stream >] + + and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] + +ast.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + + (* expr - Base type for all expression nodes. *) + type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* variant for if/then/else. *) + | If of expr * expr * expr + + (* variant for for/in. *) + | For of string * expr * expr * expr option * expr + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = Prototype of string * string array + + (* func - This type represents a function definition itself. *) + type func = Function of proto * expr + +parser.ml: + .. code-block:: ocaml + + (*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + + (* binop_precedence - This holds the precedence for each binary operator that is + * defined *) + let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + + (* precedence - Get the precedence of the pending binary operator token. *) + let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr + * ::= ifexpr + * ::= forexpr *) + let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + + (* forexpr + ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) + | [< 'Token.For; + 'Token.Ident id ?? "expected identifier after for"; + 'Token.Kwd '=' ?? "expected '=' after for"; + stream >] -> + begin parser + | [< + start=parse_expr; + 'Token.Kwd ',' ?? "expected ',' after for"; + end_=parse_expr; + stream >] -> + let step = + begin parser + | [< 'Token.Kwd ','; step=parse_expr >] -> Some step + | [< >] -> None + end stream + in + begin parser + | [< 'Token.In; body=parse_expr >] -> + Ast.For (id, start, end_, step, body) + | [< >] -> + raise (Stream.Error "expected 'in' after for") + end stream + | [< >] -> + raise (Stream.Error "expected '=' after for") + end stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + + (* prototype + * ::= id '(' id* ')' *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + + (* definition ::= 'def' prototype expression *) + let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + + (* toplevelexpr ::= expression *) + let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + + (* external ::= 'extern' prototype *) + let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e + +codegen.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + + open Llvm + + exception Error of string + + let context = global_context () + let the_module = create_module context "my cool jit" + let builder = builder context + let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 + let double_type = double_type context + + let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + | Ast.If (cond, then_, else_) -> + let cond = codegen_expr cond in + + (* Convert condition to a bool by comparing equal to 0.0 *) + let zero = const_float double_type 0.0 in + let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in + + (* Grab the first block so that we might later add the conditional branch + * to it at the end of the function. *) + let start_bb = insertion_block builder in + let the_function = block_parent start_bb in + + let then_bb = append_block context "then" the_function in + + (* Emit 'then' value. *) + position_at_end then_bb builder; + let then_val = codegen_expr then_ in + + (* Codegen of 'then' can change the current block, update then_bb for the + * phi. We create a new name because one is used for the phi node, and the + * other is used for the conditional branch. *) + let new_then_bb = insertion_block builder in + + (* Emit 'else' value. *) + let else_bb = append_block context "else" the_function in + position_at_end else_bb builder; + let else_val = codegen_expr else_ in + + (* Codegen of 'else' can change the current block, update else_bb for the + * phi. *) + let new_else_bb = insertion_block builder in + + (* Emit merge block. *) + let merge_bb = append_block context "ifcont" the_function in + position_at_end merge_bb builder; + let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in + let phi = build_phi incoming "iftmp" builder in + + (* Return to the start block to add the conditional branch. *) + position_at_end start_bb builder; + ignore (build_cond_br cond_val then_bb else_bb builder); + + (* Set a unconditional branch at the end of the 'then' block and the + * 'else' block to the 'merge' block. *) + position_at_end new_then_bb builder; ignore (build_br merge_bb builder); + position_at_end new_else_bb builder; ignore (build_br merge_bb builder); + + (* Finally, set the builder to the end of the merge block. *) + position_at_end merge_bb builder; + + phi + | Ast.For (var_name, start, end_, step, body) -> + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + + (* Make the new basic block for the loop header, inserting after current + * block. *) + let preheader_bb = insertion_block builder in + let the_function = block_parent preheader_bb in + let loop_bb = append_block context "loop" the_function in + + (* Insert an explicit fall through from the current block to the + * loop_bb. *) + ignore (build_br loop_bb builder); + + (* Start insertion in loop_bb. *) + position_at_end loop_bb builder; + + (* Start the PHI node with an entry for start. *) + let variable = build_phi [(start_val, preheader_bb)] var_name builder in + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name variable; + + (* Emit the body of the loop. This, like any other expr, can change the + * current BB. Note that we ignore the value computed by the body, but + * don't allow an error *) + ignore (codegen_expr body); + + (* Emit the step value. *) + let step_val = + match step with + | Some step -> codegen_expr step + (* If not specified, use 1.0. *) + | None -> const_float double_type 1.0 + in + + let next_var = build_add variable step_val "nextvar" builder in + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Convert condition to a bool by comparing equal to 0.0. *) + let zero = const_float double_type 0.0 in + let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in + + (* Create the "after loop" block and insert it. *) + let loop_end_bb = insertion_block builder in + let after_bb = append_block context "afterloop" the_function in + + (* Insert the conditional branch into the end of loop_end_bb. *) + ignore (build_cond_br end_cond loop_bb after_bb builder); + + (* Any new code will be inserted in after_bb. *) + position_at_end after_bb builder; + + (* Add a new entry to the PHI node for the backedge. *) + add_incoming (next_var, loop_end_bb) variable; + + (* Restore the unshadowed variable. *) + begin match old_val with + | Some old_val -> Hashtbl.add named_values var_name old_val + | None -> () + end; + + (* for expr always returns 0.0. *) + const_null double_type + + let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + + let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e + +toplevel.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + + (* top ::= definition | external | expression | ';' *) + let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream + +toy.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + open Llvm_target + open Llvm_scalar_opts + + let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + DataLayout.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module + ;; + + main () + +bindings.c + .. code-block:: c + + #include + + /* putchard - putchar that takes a double and returns 0. */ + extern double putchard(double X) { + putchar((char)X); + return 0; + } + +`Next: Extending the language: user-defined +operators `_ + diff --git a/docs/tutorial/OCamlLangImpl6.rst b/docs/tutorial/OCamlLangImpl6.rst new file mode 100644 index 00000000..36bffa8e --- /dev/null +++ b/docs/tutorial/OCamlLangImpl6.rst @@ -0,0 +1,1441 @@ +============================================================ +Kaleidoscope: Extending the Language: User-defined Operators +============================================================ + +.. contents:: + :local: + +Chapter 6 Introduction +====================== + +Welcome to Chapter 6 of the "`Implementing a language with +LLVM `_" tutorial. At this point in our tutorial, we now +have a fully functional language that is fairly minimal, but also +useful. There is still one big problem with it, however. Our language +doesn't have many useful operators (like division, logical negation, or +even any comparisons besides less-than). + +This chapter of the tutorial takes a wild digression into adding +user-defined operators to the simple and beautiful Kaleidoscope +language. This digression now gives us a simple and ugly language in +some ways, but also a powerful one at the same time. One of the great +things about creating your own language is that you get to decide what +is good or bad. In this tutorial we'll assume that it is okay to use +this as a way to show some interesting parsing techniques. + +At the end of this tutorial, we'll run through an example Kaleidoscope +application that `renders the Mandelbrot set <#example>`_. This gives an +example of what you can build with Kaleidoscope and its feature set. + +User-defined Operators: the Idea +================================ + +The "operator overloading" that we will add to Kaleidoscope is more +general than languages like C++. In C++, you are only allowed to +redefine existing operators: you can't programatically change the +grammar, introduce new operators, change precedence levels, etc. In this +chapter, we will add this capability to Kaleidoscope, which will let the +user round out the set of operators that are supported. + +The point of going into user-defined operators in a tutorial like this +is to show the power and flexibility of using a hand-written parser. +Thus far, the parser we have been implementing uses recursive descent +for most parts of the grammar and operator precedence parsing for the +expressions. See `Chapter 2 `_ for details. Without +using operator precedence parsing, it would be very difficult to allow +the programmer to introduce new operators into the grammar: the grammar +is dynamically extensible as the JIT runs. + +The two specific features we'll add are programmable unary operators +(right now, Kaleidoscope has no unary operators at all) as well as +binary operators. An example of this is: + +:: + + # Logical unary not. + def unary!(v) + if v then + 0 + else + 1; + + # Define > with the same precedence as <. + def binary> 10 (LHS RHS) + RHS < LHS; + + # Binary "logical or", (note that it does not "short circuit") + def binary| 5 (LHS RHS) + if LHS then + 1 + else if RHS then + 1 + else + 0; + + # Define = with slightly lower precedence than relationals. + def binary= 9 (LHS RHS) + !(LHS < RHS | LHS > RHS); + +Many languages aspire to being able to implement their standard runtime +library in the language itself. In Kaleidoscope, we can implement +significant parts of the language in the library! + +We will break down implementation of these features into two parts: +implementing support for user-defined binary operators and adding unary +operators. + +User-defined Binary Operators +============================= + +Adding support for user-defined binary operators is pretty simple with +our current framework. We'll first add support for the unary/binary +keywords: + +.. code-block:: ocaml + + type token = + ... + (* operators *) + | Binary | Unary + + ... + + and lex_ident buffer = parser + ... + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | "binary" -> [< 'Token.Binary; stream >] + | "unary" -> [< 'Token.Unary; stream >] + +This just adds lexer support for the unary and binary keywords, like we +did in `previous chapters `_. One nice +thing about our current AST, is that we represent binary operators with +full generalisation by using their ASCII code as the opcode. For our +extended operators, we'll use this same representation, so we don't need +any new AST or parser support. + +On the other hand, we have to be able to represent the definitions of +these new operators, in the "def binary\| 5" part of the function +definition. In our grammar so far, the "name" for the function +definition is parsed as the "prototype" production and into the +``Ast.Prototype`` AST node. To represent our new user-defined operators +as prototypes, we have to extend the ``Ast.Prototype`` AST node like +this: + +.. code-block:: ocaml + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = + | Prototype of string * string array + | BinOpPrototype of string * string array * int + +Basically, in addition to knowing a name for the prototype, we now keep +track of whether it was an operator, and if it was, what precedence +level the operator is at. The precedence is only used for binary +operators (as you'll see below, it just doesn't apply for unary +operators). Now that we have a way to represent the prototype for a +user-defined operator, we need to parse it: + +.. code-block:: ocaml + + (* prototype + * ::= id '(' id* ')' + * ::= binary LETTER number? (id, id) + * ::= unary LETTER number? (id) *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + let parse_operator = parser + | [< 'Token.Unary >] -> "unary", 1 + | [< 'Token.Binary >] -> "binary", 2 + in + let parse_binary_precedence = parser + | [< 'Token.Number n >] -> int_of_float n + | [< >] -> 30 + in + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + | [< (prefix, kind)=parse_operator; + 'Token.Kwd op ?? "expected an operator"; + (* Read the precedence if present. *) + binary_precedence=parse_binary_precedence; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + let name = prefix ^ (String.make 1 op) in + let args = Array.of_list (List.rev args) in + + (* Verify right number of arguments for operator. *) + if Array.length args != kind + then raise (Stream.Error "invalid number of operands for operator") + else + if kind == 1 then + Ast.Prototype (name, args) + else + Ast.BinOpPrototype (name, args, binary_precedence) + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +This is all fairly straightforward parsing code, and we have already +seen a lot of similar code in the past. One interesting part about the +code above is the couple lines that set up ``name`` for binary +operators. This builds names like "binary@" for a newly defined "@" +operator. This then takes advantage of the fact that symbol names in the +LLVM symbol table are allowed to have any character in them, including +embedded nul characters. + +The next interesting thing to add, is codegen support for these binary +operators. Given our current structure, this is a simple addition of a +default case for our existing binary operator node: + +.. code-block:: ocaml + + let codegen_expr = function + ... + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> + (* If it wasn't a builtin binary operator, it must be a user defined + * one. Emit a call to it. *) + let callee = "binary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "binary operator not found!") + in + build_call callee [|lhs_val; rhs_val|] "binop" builder + end + +As you can see above, the new code is actually really simple. It just +does a lookup for the appropriate operator in the symbol table and +generates a function call to it. Since user-defined operators are just +built as normal functions (because the "prototype" boils down to a +function with the right name) everything falls into place. + +The final piece of code we are missing, is a bit of top level magic: + +.. code-block:: ocaml + + let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* If this is an operator, install it. *) + begin match proto with + | Ast.BinOpPrototype (name, args, prec) -> + let op = name.[String.length name - 1] in + Hashtbl.add Parser.binop_precedence op prec; + | _ -> () + end; + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + ... + +Basically, before codegening a function, if it is a user-defined +operator, we register it in the precedence table. This allows the binary +operator parsing logic we already have in place to handle it. Since we +are working on a fully-general operator precedence parser, this is all +we need to do to "extend the grammar". + +Now we have useful user-defined binary operators. This builds a lot on +the previous framework we built for other operators. Adding unary +operators is a bit more challenging, because we don't have any framework +for it yet - lets see what it takes. + +User-defined Unary Operators +============================ + +Since we don't currently support unary operators in the Kaleidoscope +language, we'll need to add everything to support them. Above, we added +simple support for the 'unary' keyword to the lexer. In addition to +that, we need an AST node: + +.. code-block:: ocaml + + type expr = + ... + (* variant for a unary operator. *) + | Unary of char * expr + ... + +This AST node is very simple and obvious by now. It directly mirrors the +binary operator AST node, except that it only has one child. With this, +we need to add the parsing logic. Parsing a unary operator is pretty +simple: we'll add a new function to do it: + +.. code-block:: ocaml + + (* unary + * ::= primary + * ::= '!' unary *) + and parse_unary = parser + (* If this is a unary operator, read it. *) + | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] -> + Ast.Unary (op, operand) + + (* If the current token is not an operator, it must be a primary expr. *) + | [< stream >] -> parse_primary stream + +The grammar we add is pretty straightforward here. If we see a unary +operator when parsing a primary operator, we eat the operator as a +prefix and parse the remaining piece as another unary operator. This +allows us to handle multiple unary operators (e.g. "!!x"). Note that +unary operators can't have ambiguous parses like binary operators can, +so there is no need for precedence information. + +The problem with this function, is that we need to call ParseUnary from +somewhere. To do this, we change previous callers of ParsePrimary to +call ``parse_unary`` instead: + +.. code-block:: ocaml + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + ... + (* Parse the unary expression after the binary operator. *) + let rhs = parse_unary stream in + ... + + ... + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream + +With these two simple changes, we are now able to parse unary operators +and build the AST for them. Next up, we need to add parser support for +prototypes, to parse the unary operator prototype. We extend the binary +operator code above with: + +.. code-block:: ocaml + + (* prototype + * ::= id '(' id* ')' + * ::= binary LETTER number? (id, id) + * ::= unary LETTER number? (id) *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + let parse_operator = parser + | [< 'Token.Unary >] -> "unary", 1 + | [< 'Token.Binary >] -> "binary", 2 + in + let parse_binary_precedence = parser + | [< 'Token.Number n >] -> int_of_float n + | [< >] -> 30 + in + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + | [< (prefix, kind)=parse_operator; + 'Token.Kwd op ?? "expected an operator"; + (* Read the precedence if present. *) + binary_precedence=parse_binary_precedence; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + let name = prefix ^ (String.make 1 op) in + let args = Array.of_list (List.rev args) in + + (* Verify right number of arguments for operator. *) + if Array.length args != kind + then raise (Stream.Error "invalid number of operands for operator") + else + if kind == 1 then + Ast.Prototype (name, args) + else + Ast.BinOpPrototype (name, args, binary_precedence) + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +As with binary operators, we name unary operators with a name that +includes the operator character. This assists us at code generation +time. Speaking of, the final piece we need to add is codegen support for +unary operators. It looks like this: + +.. code-block:: ocaml + + let rec codegen_expr = function + ... + | Ast.Unary (op, operand) -> + let operand = codegen_expr operand in + let callee = "unary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown unary operator") + in + build_call callee [|operand|] "unop" builder + +This code is similar to, but simpler than, the code for binary +operators. It is simpler primarily because it doesn't need to handle any +predefined operators. + +Kicking the Tires +================= + +It is somewhat hard to believe, but with a few simple extensions we've +covered in the last chapters, we have grown a real-ish language. With +this, we can do a lot of interesting things, including I/O, math, and a +bunch of other things. For example, we can now add a nice sequencing +operator (printd is defined to print out the specified value and a +newline): + +:: + + ready> extern printd(x); + Read extern: declare double @printd(double) + ready> def binary : 1 (x y) 0; # Low-precedence operator that ignores operands. + .. + ready> printd(123) : printd(456) : printd(789); + 123.000000 + 456.000000 + 789.000000 + Evaluated to 0.000000 + +We can also define a bunch of other "primitive" operations, such as: + +:: + + # Logical unary not. + def unary!(v) + if v then + 0 + else + 1; + + # Unary negate. + def unary-(v) + 0-v; + + # Define > with the same precedence as <. + def binary> 10 (LHS RHS) + RHS < LHS; + + # Binary logical or, which does not short circuit. + def binary| 5 (LHS RHS) + if LHS then + 1 + else if RHS then + 1 + else + 0; + + # Binary logical and, which does not short circuit. + def binary& 6 (LHS RHS) + if !LHS then + 0 + else + !!RHS; + + # Define = with slightly lower precedence than relationals. + def binary = 9 (LHS RHS) + !(LHS < RHS | LHS > RHS); + +Given the previous if/then/else support, we can also define interesting +functions for I/O. For example, the following prints out a character +whose "density" reflects the value passed in: the lower the value, the +denser the character: + +:: + + ready> + + extern putchard(char) + def printdensity(d) + if d > 8 then + putchard(32) # ' ' + else if d > 4 then + putchard(46) # '.' + else if d > 2 then + putchard(43) # '+' + else + putchard(42); # '*' + ... + ready> printdensity(1): printdensity(2): printdensity(3) : + printdensity(4): printdensity(5): printdensity(9): putchard(10); + *++.. + Evaluated to 0.000000 + +Based on these simple primitive operations, we can start to define more +interesting things. For example, here's a little function that solves +for the number of iterations it takes a function in the complex plane to +converge: + +:: + + # determine whether the specific location diverges. + # Solve for z = z^2 + c in the complex plane. + def mandleconverger(real imag iters creal cimag) + if iters > 255 | (real*real + imag*imag > 4) then + iters + else + mandleconverger(real*real - imag*imag + creal, + 2*real*imag + cimag, + iters+1, creal, cimag); + + # return the number of iterations required for the iteration to escape + def mandleconverge(real imag) + mandleconverger(real, imag, 0, real, imag); + +This "z = z\ :sup:`2`\ + c" function is a beautiful little creature +that is the basis for computation of the `Mandelbrot +Set `_. Our +``mandelconverge`` function returns the number of iterations that it +takes for a complex orbit to escape, saturating to 255. This is not a +very useful function by itself, but if you plot its value over a +two-dimensional plane, you can see the Mandelbrot set. Given that we are +limited to using putchard here, our amazing graphical output is limited, +but we can whip together something using the density plotter above: + +:: + + # compute and plot the mandlebrot set with the specified 2 dimensional range + # info. + def mandelhelp(xmin xmax xstep ymin ymax ystep) + for y = ymin, y < ymax, ystep in ( + (for x = xmin, x < xmax, xstep in + printdensity(mandleconverge(x,y))) + : putchard(10) + ) + + # mandel - This is a convenient helper function for plotting the mandelbrot set + # from the specified position with the specified Magnification. + def mandel(realstart imagstart realmag imagmag) + mandelhelp(realstart, realstart+realmag*78, realmag, + imagstart, imagstart+imagmag*40, imagmag); + +Given this, we can try plotting out the mandlebrot set! Lets try it out: + +:: + + ready> mandel(-2.3, -1.3, 0.05, 0.07); + *******************************+++++++++++************************************* + *************************+++++++++++++++++++++++******************************* + **********************+++++++++++++++++++++++++++++**************************** + *******************+++++++++++++++++++++.. ...++++++++************************* + *****************++++++++++++++++++++++.... ...+++++++++*********************** + ***************+++++++++++++++++++++++..... ...+++++++++********************* + **************+++++++++++++++++++++++.... ....+++++++++******************** + *************++++++++++++++++++++++...... .....++++++++******************* + ************+++++++++++++++++++++....... .......+++++++****************** + ***********+++++++++++++++++++.... ... .+++++++***************** + **********+++++++++++++++++....... .+++++++**************** + *********++++++++++++++........... ...+++++++*************** + ********++++++++++++............ ...++++++++************** + ********++++++++++... .......... .++++++++************** + *******+++++++++..... .+++++++++************* + *******++++++++...... ..+++++++++************* + *******++++++....... ..+++++++++************* + *******+++++...... ..+++++++++************* + *******.... .... ...+++++++++************* + *******.... . ...+++++++++************* + *******+++++...... ...+++++++++************* + *******++++++....... ..+++++++++************* + *******++++++++...... .+++++++++************* + *******+++++++++..... ..+++++++++************* + ********++++++++++... .......... .++++++++************** + ********++++++++++++............ ...++++++++************** + *********++++++++++++++.......... ...+++++++*************** + **********++++++++++++++++........ .+++++++**************** + **********++++++++++++++++++++.... ... ..+++++++**************** + ***********++++++++++++++++++++++....... .......++++++++***************** + ************+++++++++++++++++++++++...... ......++++++++****************** + **************+++++++++++++++++++++++.... ....++++++++******************** + ***************+++++++++++++++++++++++..... ...+++++++++********************* + *****************++++++++++++++++++++++.... ...++++++++*********************** + *******************+++++++++++++++++++++......++++++++************************* + *********************++++++++++++++++++++++.++++++++*************************** + *************************+++++++++++++++++++++++******************************* + ******************************+++++++++++++************************************ + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + Evaluated to 0.000000 + ready> mandel(-2, -1, 0.02, 0.04); + **************************+++++++++++++++++++++++++++++++++++++++++++++++++++++ + ***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + *********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++. + *******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++... + *****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++..... + ***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........ + **************++++++++++++++++++++++++++++++++++++++++++++++++++++++........... + ************+++++++++++++++++++++++++++++++++++++++++++++++++++++.............. + ***********++++++++++++++++++++++++++++++++++++++++++++++++++........ . + **********++++++++++++++++++++++++++++++++++++++++++++++............. + ********+++++++++++++++++++++++++++++++++++++++++++.................. + *******+++++++++++++++++++++++++++++++++++++++....................... + ******+++++++++++++++++++++++++++++++++++........................... + *****++++++++++++++++++++++++++++++++............................ + *****++++++++++++++++++++++++++++............................... + ****++++++++++++++++++++++++++...... ......................... + ***++++++++++++++++++++++++......... ...... ........... + ***++++++++++++++++++++++............ + **+++++++++++++++++++++.............. + **+++++++++++++++++++................ + *++++++++++++++++++................. + *++++++++++++++++............ ... + *++++++++++++++.............. + *+++....++++................ + *.......... ........... + * + *.......... ........... + *+++....++++................ + *++++++++++++++.............. + *++++++++++++++++............ ... + *++++++++++++++++++................. + **+++++++++++++++++++................ + **+++++++++++++++++++++.............. + ***++++++++++++++++++++++............ + ***++++++++++++++++++++++++......... ...... ........... + ****++++++++++++++++++++++++++...... ......................... + *****++++++++++++++++++++++++++++............................... + *****++++++++++++++++++++++++++++++++............................ + ******+++++++++++++++++++++++++++++++++++........................... + *******+++++++++++++++++++++++++++++++++++++++....................... + ********+++++++++++++++++++++++++++++++++++++++++++.................. + Evaluated to 0.000000 + ready> mandel(-0.9, -1.4, 0.02, 0.03); + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + **********+++++++++++++++++++++************************************************ + *+++++++++++++++++++++++++++++++++++++++*************************************** + +++++++++++++++++++++++++++++++++++++++++++++********************************** + ++++++++++++++++++++++++++++++++++++++++++++++++++***************************** + ++++++++++++++++++++++++++++++++++++++++++++++++++++++************************* + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++********************** + +++++++++++++++++++++++++++++++++.........++++++++++++++++++******************* + +++++++++++++++++++++++++++++++.... ......+++++++++++++++++++**************** + +++++++++++++++++++++++++++++....... ........+++++++++++++++++++************** + ++++++++++++++++++++++++++++........ ........++++++++++++++++++++************ + +++++++++++++++++++++++++++......... .. ...+++++++++++++++++++++********** + ++++++++++++++++++++++++++........... ....++++++++++++++++++++++******** + ++++++++++++++++++++++++............. .......++++++++++++++++++++++****** + +++++++++++++++++++++++............. ........+++++++++++++++++++++++**** + ++++++++++++++++++++++........... ..........++++++++++++++++++++++*** + ++++++++++++++++++++........... .........++++++++++++++++++++++* + ++++++++++++++++++............ ...........++++++++++++++++++++ + ++++++++++++++++............... .............++++++++++++++++++ + ++++++++++++++................. ...............++++++++++++++++ + ++++++++++++.................. .................++++++++++++++ + +++++++++.................. .................+++++++++++++ + ++++++........ . ......... ..++++++++++++ + ++............ ...... ....++++++++++ + .............. ...++++++++++ + .............. ....+++++++++ + .............. .....++++++++ + ............. ......++++++++ + ........... .......++++++++ + ......... ........+++++++ + ......... ........+++++++ + ......... ....+++++++ + ........ ...+++++++ + ....... ...+++++++ + ....+++++++ + .....+++++++ + ....+++++++ + ....+++++++ + ....+++++++ + Evaluated to 0.000000 + ready> ^D + +At this point, you may be starting to realize that Kaleidoscope is a +real and powerful language. It may not be self-similar :), but it can be +used to plot things that are! + +With this, we conclude the "adding user-defined operators" chapter of +the tutorial. We have successfully augmented our language, adding the +ability to extend the language in the library, and we have shown how +this can be used to build a simple but interesting end-user application +in Kaleidoscope. At this point, Kaleidoscope can build a variety of +applications that are functional and can call functions with +side-effects, but it can't actually define and mutate a variable itself. + +Strikingly, variable mutation is an important feature of some languages, +and it is not at all obvious how to `add support for mutable +variables `_ without having to add an "SSA +construction" phase to your front-end. In the next chapter, we will +describe how you can add variable mutation without building SSA in your +front-end. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +the if/then/else and for expressions.. To build this example, use: + +.. code-block:: bash + + # Compile + ocamlbuild toy.byte + # Run + ./toy.byte + +Here is the code: + +\_tags: + :: + + <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) + <*.{byte,native}>: g++, use_llvm, use_llvm_analysis + <*.{byte,native}>: use_llvm_executionengine, use_llvm_target + <*.{byte,native}>: use_llvm_scalar_opts, use_bindings + +myocamlbuild.ml: + .. code-block:: ocaml + + open Ocamlbuild_plugin;; + + ocaml_lib ~extern:true "llvm";; + ocaml_lib ~extern:true "llvm_analysis";; + ocaml_lib ~extern:true "llvm_executionengine";; + ocaml_lib ~extern:true "llvm_target";; + ocaml_lib ~extern:true "llvm_scalar_opts";; + + flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);; + dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; + +token.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + + (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) + type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + + (* control *) + | If | Then | Else + | For | In + + (* operators *) + | Binary | Unary + +lexer.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + + let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + + and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + + and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | "binary" -> [< 'Token.Binary; stream >] + | "unary" -> [< 'Token.Unary; stream >] + | id -> [< 'Token.Ident id; stream >] + + and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] + +ast.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + + (* expr - Base type for all expression nodes. *) + type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a unary operator. *) + | Unary of char * expr + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* variant for if/then/else. *) + | If of expr * expr * expr + + (* variant for for/in. *) + | For of string * expr * expr * expr option * expr + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = + | Prototype of string * string array + | BinOpPrototype of string * string array * int + + (* func - This type represents a function definition itself. *) + type func = Function of proto * expr + +parser.ml: + .. code-block:: ocaml + + (*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + + (* binop_precedence - This holds the precedence for each binary operator that is + * defined *) + let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + + (* precedence - Get the precedence of the pending binary operator token. *) + let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr + * ::= ifexpr + * ::= forexpr *) + let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + + (* forexpr + ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) + | [< 'Token.For; + 'Token.Ident id ?? "expected identifier after for"; + 'Token.Kwd '=' ?? "expected '=' after for"; + stream >] -> + begin parser + | [< + start=parse_expr; + 'Token.Kwd ',' ?? "expected ',' after for"; + end_=parse_expr; + stream >] -> + let step = + begin parser + | [< 'Token.Kwd ','; step=parse_expr >] -> Some step + | [< >] -> None + end stream + in + begin parser + | [< 'Token.In; body=parse_expr >] -> + Ast.For (id, start, end_, step, body) + | [< >] -> + raise (Stream.Error "expected 'in' after for") + end stream + | [< >] -> + raise (Stream.Error "expected '=' after for") + end stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + + (* unary + * ::= primary + * ::= '!' unary *) + and parse_unary = parser + (* If this is a unary operator, read it. *) + | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] -> + Ast.Unary (op, operand) + + (* If the current token is not an operator, it must be a primary expr. *) + | [< stream >] -> parse_primary stream + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the unary expression after the binary operator. *) + let rhs = parse_unary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream + + (* prototype + * ::= id '(' id* ')' + * ::= binary LETTER number? (id, id) + * ::= unary LETTER number? (id) *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + let parse_operator = parser + | [< 'Token.Unary >] -> "unary", 1 + | [< 'Token.Binary >] -> "binary", 2 + in + let parse_binary_precedence = parser + | [< 'Token.Number n >] -> int_of_float n + | [< >] -> 30 + in + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + | [< (prefix, kind)=parse_operator; + 'Token.Kwd op ?? "expected an operator"; + (* Read the precedence if present. *) + binary_precedence=parse_binary_precedence; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + let name = prefix ^ (String.make 1 op) in + let args = Array.of_list (List.rev args) in + + (* Verify right number of arguments for operator. *) + if Array.length args != kind + then raise (Stream.Error "invalid number of operands for operator") + else + if kind == 1 then + Ast.Prototype (name, args) + else + Ast.BinOpPrototype (name, args, binary_precedence) + | [< >] -> + raise (Stream.Error "expected function name in prototype") + + (* definition ::= 'def' prototype expression *) + let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + + (* toplevelexpr ::= expression *) + let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + + (* external ::= 'extern' prototype *) + let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e + +codegen.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + + open Llvm + + exception Error of string + + let context = global_context () + let the_module = create_module context "my cool jit" + let builder = builder context + let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 + let double_type = double_type context + + let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Unary (op, operand) -> + let operand = codegen_expr operand in + let callee = "unary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown unary operator") + in + build_call callee [|operand|] "unop" builder + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> + (* If it wasn't a builtin binary operator, it must be a user defined + * one. Emit a call to it. *) + let callee = "binary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "binary operator not found!") + in + build_call callee [|lhs_val; rhs_val|] "binop" builder + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + | Ast.If (cond, then_, else_) -> + let cond = codegen_expr cond in + + (* Convert condition to a bool by comparing equal to 0.0 *) + let zero = const_float double_type 0.0 in + let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in + + (* Grab the first block so that we might later add the conditional branch + * to it at the end of the function. *) + let start_bb = insertion_block builder in + let the_function = block_parent start_bb in + + let then_bb = append_block context "then" the_function in + + (* Emit 'then' value. *) + position_at_end then_bb builder; + let then_val = codegen_expr then_ in + + (* Codegen of 'then' can change the current block, update then_bb for the + * phi. We create a new name because one is used for the phi node, and the + * other is used for the conditional branch. *) + let new_then_bb = insertion_block builder in + + (* Emit 'else' value. *) + let else_bb = append_block context "else" the_function in + position_at_end else_bb builder; + let else_val = codegen_expr else_ in + + (* Codegen of 'else' can change the current block, update else_bb for the + * phi. *) + let new_else_bb = insertion_block builder in + + (* Emit merge block. *) + let merge_bb = append_block context "ifcont" the_function in + position_at_end merge_bb builder; + let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in + let phi = build_phi incoming "iftmp" builder in + + (* Return to the start block to add the conditional branch. *) + position_at_end start_bb builder; + ignore (build_cond_br cond_val then_bb else_bb builder); + + (* Set a unconditional branch at the end of the 'then' block and the + * 'else' block to the 'merge' block. *) + position_at_end new_then_bb builder; ignore (build_br merge_bb builder); + position_at_end new_else_bb builder; ignore (build_br merge_bb builder); + + (* Finally, set the builder to the end of the merge block. *) + position_at_end merge_bb builder; + + phi + | Ast.For (var_name, start, end_, step, body) -> + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + + (* Make the new basic block for the loop header, inserting after current + * block. *) + let preheader_bb = insertion_block builder in + let the_function = block_parent preheader_bb in + let loop_bb = append_block context "loop" the_function in + + (* Insert an explicit fall through from the current block to the + * loop_bb. *) + ignore (build_br loop_bb builder); + + (* Start insertion in loop_bb. *) + position_at_end loop_bb builder; + + (* Start the PHI node with an entry for start. *) + let variable = build_phi [(start_val, preheader_bb)] var_name builder in + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name variable; + + (* Emit the body of the loop. This, like any other expr, can change the + * current BB. Note that we ignore the value computed by the body, but + * don't allow an error *) + ignore (codegen_expr body); + + (* Emit the step value. *) + let step_val = + match step with + | Some step -> codegen_expr step + (* If not specified, use 1.0. *) + | None -> const_float double_type 1.0 + in + + let next_var = build_add variable step_val "nextvar" builder in + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Convert condition to a bool by comparing equal to 0.0. *) + let zero = const_float double_type 0.0 in + let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in + + (* Create the "after loop" block and insert it. *) + let loop_end_bb = insertion_block builder in + let after_bb = append_block context "afterloop" the_function in + + (* Insert the conditional branch into the end of loop_end_bb. *) + ignore (build_cond_br end_cond loop_bb after_bb builder); + + (* Any new code will be inserted in after_bb. *) + position_at_end after_bb builder; + + (* Add a new entry to the PHI node for the backedge. *) + add_incoming (next_var, loop_end_bb) variable; + + (* Restore the unshadowed variable. *) + begin match old_val with + | Some old_val -> Hashtbl.add named_values var_name old_val + | None -> () + end; + + (* for expr always returns 0.0. *) + const_null double_type + + let codegen_proto = function + | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + + let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* If this is an operator, install it. *) + begin match proto with + | Ast.BinOpPrototype (name, args, prec) -> + let op = name.[String.length name - 1] in + Hashtbl.add Parser.binop_precedence op prec; + | _ -> () + end; + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e + +toplevel.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + + (* top ::= definition | external | expression | ';' *) + let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream + +toy.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + open Llvm_target + open Llvm_scalar_opts + + let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + DataLayout.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module + ;; + + main () + +bindings.c + .. code-block:: c + + #include + + /* putchard - putchar that takes a double and returns 0. */ + extern double putchard(double X) { + putchar((char)X); + return 0; + } + + /* printd - printf that takes a double prints it as "%f\n", returning 0. */ + extern double printd(double X) { + printf("%f\n", X); + return 0; + } + +`Next: Extending the language: mutable variables / SSA +construction `_ + diff --git a/docs/tutorial/OCamlLangImpl7.rst b/docs/tutorial/OCamlLangImpl7.rst new file mode 100644 index 00000000..cfb49312 --- /dev/null +++ b/docs/tutorial/OCamlLangImpl7.rst @@ -0,0 +1,1723 @@ +======================================================= +Kaleidoscope: Extending the Language: Mutable Variables +======================================================= + +.. contents:: + :local: + +Chapter 7 Introduction +====================== + +Welcome to Chapter 7 of the "`Implementing a language with +LLVM `_" tutorial. In chapters 1 through 6, we've built a +very respectable, albeit simple, `functional programming +language `_. In our +journey, we learned some parsing techniques, how to build and represent +an AST, how to build LLVM IR, and how to optimize the resultant code as +well as JIT compile it. + +While Kaleidoscope is interesting as a functional language, the fact +that it is functional makes it "too easy" to generate LLVM IR for it. In +particular, a functional language makes it very easy to build LLVM IR +directly in `SSA +form `_. +Since LLVM requires that the input code be in SSA form, this is a very +nice property and it is often unclear to newcomers how to generate code +for an imperative language with mutable variables. + +The short (and happy) summary of this chapter is that there is no need +for your front-end to build SSA form: LLVM provides highly tuned and +well tested support for this, though the way it works is a bit +unexpected for some. + +Why is this a hard problem? +=========================== + +To understand why mutable variables cause complexities in SSA +construction, consider this extremely simple C example: + +.. code-block:: c + + int G, H; + int test(_Bool Condition) { + int X; + if (Condition) + X = G; + else + X = H; + return X; + } + +In this case, we have the variable "X", whose value depends on the path +executed in the program. Because there are two different possible values +for X before the return instruction, a PHI node is inserted to merge the +two values. The LLVM IR that we want for this example looks like this: + +.. code-block:: llvm + + @G = weak global i32 0 ; type of @G is i32* + @H = weak global i32 0 ; type of @H is i32* + + define i32 @test(i1 %Condition) { + entry: + br i1 %Condition, label %cond_true, label %cond_false + + cond_true: + %X.0 = load i32* @G + br label %cond_next + + cond_false: + %X.1 = load i32* @H + br label %cond_next + + cond_next: + %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ] + ret i32 %X.2 + } + +In this example, the loads from the G and H global variables are +explicit in the LLVM IR, and they live in the then/else branches of the +if statement (cond\_true/cond\_false). In order to merge the incoming +values, the X.2 phi node in the cond\_next block selects the right value +to use based on where control flow is coming from: if control flow comes +from the cond\_false block, X.2 gets the value of X.1. Alternatively, if +control flow comes from cond\_true, it gets the value of X.0. The intent +of this chapter is not to explain the details of SSA form. For more +information, see one of the many `online +references `_. + +The question for this article is "who places the phi nodes when lowering +assignments to mutable variables?". The issue here is that LLVM +*requires* that its IR be in SSA form: there is no "non-ssa" mode for +it. However, SSA construction requires non-trivial algorithms and data +structures, so it is inconvenient and wasteful for every front-end to +have to reproduce this logic. + +Memory in LLVM +============== + +The 'trick' here is that while LLVM does require all register values to +be in SSA form, it does not require (or permit) memory objects to be in +SSA form. In the example above, note that the loads from G and H are +direct accesses to G and H: they are not renamed or versioned. This +differs from some other compiler systems, which do try to version memory +objects. In LLVM, instead of encoding dataflow analysis of memory into +the LLVM IR, it is handled with `Analysis +Passes <../WritingAnLLVMPass.html>`_ which are computed on demand. + +With this in mind, the high-level idea is that we want to make a stack +variable (which lives in memory, because it is on the stack) for each +mutable object in a function. To take advantage of this trick, we need +to talk about how LLVM represents stack variables. + +In LLVM, all memory accesses are explicit with load/store instructions, +and it is carefully designed not to have (or need) an "address-of" +operator. Notice how the type of the @G/@H global variables is actually +"i32\*" even though the variable is defined as "i32". What this means is +that @G defines *space* for an i32 in the global data area, but its +*name* actually refers to the address for that space. Stack variables +work the same way, except that instead of being declared with global +variable definitions, they are declared with the `LLVM alloca +instruction <../LangRef.html#i_alloca>`_: + +.. code-block:: llvm + + define i32 @example() { + entry: + %X = alloca i32 ; type of %X is i32*. + ... + %tmp = load i32* %X ; load the stack value %X from the stack. + %tmp2 = add i32 %tmp, 1 ; increment it + store i32 %tmp2, i32* %X ; store it back + ... + +This code shows an example of how you can declare and manipulate a stack +variable in the LLVM IR. Stack memory allocated with the alloca +instruction is fully general: you can pass the address of the stack slot +to functions, you can store it in other variables, etc. In our example +above, we could rewrite the example to use the alloca technique to avoid +using a PHI node: + +.. code-block:: llvm + + @G = weak global i32 0 ; type of @G is i32* + @H = weak global i32 0 ; type of @H is i32* + + define i32 @test(i1 %Condition) { + entry: + %X = alloca i32 ; type of %X is i32*. + br i1 %Condition, label %cond_true, label %cond_false + + cond_true: + %X.0 = load i32* @G + store i32 %X.0, i32* %X ; Update X + br label %cond_next + + cond_false: + %X.1 = load i32* @H + store i32 %X.1, i32* %X ; Update X + br label %cond_next + + cond_next: + %X.2 = load i32* %X ; Read X + ret i32 %X.2 + } + +With this, we have discovered a way to handle arbitrary mutable +variables without the need to create Phi nodes at all: + +#. Each mutable variable becomes a stack allocation. +#. Each read of the variable becomes a load from the stack. +#. Each update of the variable becomes a store to the stack. +#. Taking the address of a variable just uses the stack address + directly. + +While this solution has solved our immediate problem, it introduced +another one: we have now apparently introduced a lot of stack traffic +for very simple and common operations, a major performance problem. +Fortunately for us, the LLVM optimizer has a highly-tuned optimization +pass named "mem2reg" that handles this case, promoting allocas like this +into SSA registers, inserting Phi nodes as appropriate. If you run this +example through the pass, for example, you'll get: + +.. code-block:: bash + + $ llvm-as < example.ll | opt -mem2reg | llvm-dis + @G = weak global i32 0 + @H = weak global i32 0 + + define i32 @test(i1 %Condition) { + entry: + br i1 %Condition, label %cond_true, label %cond_false + + cond_true: + %X.0 = load i32* @G + br label %cond_next + + cond_false: + %X.1 = load i32* @H + br label %cond_next + + cond_next: + %X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ] + ret i32 %X.01 + } + +The mem2reg pass implements the standard "iterated dominance frontier" +algorithm for constructing SSA form and has a number of optimizations +that speed up (very common) degenerate cases. The mem2reg optimization +pass is the answer to dealing with mutable variables, and we highly +recommend that you depend on it. Note that mem2reg only works on +variables in certain circumstances: + +#. mem2reg is alloca-driven: it looks for allocas and if it can handle + them, it promotes them. It does not apply to global variables or heap + allocations. +#. mem2reg only looks for alloca instructions in the entry block of the + function. Being in the entry block guarantees that the alloca is only + executed once, which makes analysis simpler. +#. mem2reg only promotes allocas whose uses are direct loads and stores. + If the address of the stack object is passed to a function, or if any + funny pointer arithmetic is involved, the alloca will not be + promoted. +#. mem2reg only works on allocas of `first + class <../LangRef.html#t_classifications>`_ values (such as pointers, + scalars and vectors), and only if the array size of the allocation is + 1 (or missing in the .ll file). mem2reg is not capable of promoting + structs or arrays to registers. Note that the "scalarrepl" pass is + more powerful and can promote structs, "unions", and arrays in many + cases. + +All of these properties are easy to satisfy for most imperative +languages, and we'll illustrate it below with Kaleidoscope. The final +question you may be asking is: should I bother with this nonsense for my +front-end? Wouldn't it be better if I just did SSA construction +directly, avoiding use of the mem2reg optimization pass? In short, we +strongly recommend that you use this technique for building SSA form, +unless there is an extremely good reason not to. Using this technique +is: + +- Proven and well tested: llvm-gcc and clang both use this technique + for local mutable variables. As such, the most common clients of LLVM + are using this to handle a bulk of their variables. You can be sure + that bugs are found fast and fixed early. +- Extremely Fast: mem2reg has a number of special cases that make it + fast in common cases as well as fully general. For example, it has + fast-paths for variables that are only used in a single block, + variables that only have one assignment point, good heuristics to + avoid insertion of unneeded phi nodes, etc. +- Needed for debug info generation: `Debug information in + LLVM <../SourceLevelDebugging.html>`_ relies on having the address of + the variable exposed so that debug info can be attached to it. This + technique dovetails very naturally with this style of debug info. + +If nothing else, this makes it much easier to get your front-end up and +running, and is very simple to implement. Lets extend Kaleidoscope with +mutable variables now! + +Mutable Variables in Kaleidoscope +================================= + +Now that we know the sort of problem we want to tackle, lets see what +this looks like in the context of our little Kaleidoscope language. +We're going to add two features: + +#. The ability to mutate variables with the '=' operator. +#. The ability to define new variables. + +While the first item is really what this is about, we only have +variables for incoming arguments as well as for induction variables, and +redefining those only goes so far :). Also, the ability to define new +variables is a useful thing regardless of whether you will be mutating +them. Here's a motivating example that shows how we could use these: + +:: + + # Define ':' for sequencing: as a low-precedence operator that ignores operands + # and just returns the RHS. + def binary : 1 (x y) y; + + # Recursive fib, we could do this before. + def fib(x) + if (x < 3) then + 1 + else + fib(x-1)+fib(x-2); + + # Iterative fib. + def fibi(x) + var a = 1, b = 1, c in + (for i = 3, i < x in + c = a + b : + a = b : + b = c) : + b; + + # Call it. + fibi(10); + +In order to mutate variables, we have to change our existing variables +to use the "alloca trick". Once we have that, we'll add our new +operator, then extend Kaleidoscope to support new variable definitions. + +Adjusting Existing Variables for Mutation +========================================= + +The symbol table in Kaleidoscope is managed at code generation time by +the '``named_values``' map. This map currently keeps track of the LLVM +"Value\*" that holds the double value for the named variable. In order +to support mutation, we need to change this slightly, so that it +``named_values`` holds the *memory location* of the variable in +question. Note that this change is a refactoring: it changes the +structure of the code, but does not (by itself) change the behavior of +the compiler. All of these changes are isolated in the Kaleidoscope code +generator. + +At this point in Kaleidoscope's development, it only supports variables +for two things: incoming arguments to functions and the induction +variable of 'for' loops. For consistency, we'll allow mutation of these +variables in addition to other user-defined variables. This means that +these will both need memory locations. + +To start our transformation of Kaleidoscope, we'll change the +``named_values`` map so that it maps to AllocaInst\* instead of Value\*. +Once we do this, the C++ compiler will tell us what parts of the code we +need to update: + +**Note:** the ocaml bindings currently model both ``Value*``'s and +``AllocInst*``'s as ``Llvm.llvalue``'s, but this may change in the future +to be more type safe. + +.. code-block:: ocaml + + let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 + +Also, since we will need to create these alloca's, we'll use a helper +function that ensures that the allocas are created in the entry block of +the function: + +.. code-block:: ocaml + + (* Create an alloca instruction in the entry block of the function. This + * is used for mutable variables etc. *) + let create_entry_block_alloca the_function var_name = + let builder = builder_at (instr_begin (entry_block the_function)) in + build_alloca double_type var_name builder + +This funny looking code creates an ``Llvm.llbuilder`` object that is +pointing at the first instruction of the entry block. It then creates an +alloca with the expected name and returns it. Because all values in +Kaleidoscope are doubles, there is no need to pass in a type to use. + +With this in place, the first functionality change we want to make is to +variable references. In our new scheme, variables live on the stack, so +code generating a reference to them actually needs to produce a load +from the stack slot: + +.. code-block:: ocaml + + let rec codegen_expr = function + ... + | Ast.Variable name -> + let v = try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name") + in + (* Load the value. *) + build_load v name builder + +As you can see, this is pretty straightforward. Now we need to update +the things that define the variables to set up the alloca. We'll start +with ``codegen_expr Ast.For ...`` (see the `full code listing <#code>`_ +for the unabridged code): + +.. code-block:: ocaml + + | Ast.For (var_name, start, end_, step, body) -> + let the_function = block_parent (insertion_block builder) in + + (* Create an alloca for the variable in the entry block. *) + let alloca = create_entry_block_alloca the_function var_name in + + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + + (* Store the value into the alloca. *) + ignore(build_store start_val alloca builder); + + ... + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name alloca; + + ... + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Reload, increment, and restore the alloca. This handles the case where + * the body of the loop mutates the variable. *) + let cur_var = build_load alloca var_name builder in + let next_var = build_add cur_var step_val "nextvar" builder in + ignore(build_store next_var alloca builder); + ... + +This code is virtually identical to the code `before we allowed mutable +variables `_. The big difference is that +we no longer have to construct a PHI node, and we use load/store to +access the variable as needed. + +To support mutable argument variables, we need to also make allocas for +them. The code for this is also pretty simple: + +.. code-block:: ocaml + + (* Create an alloca for each argument and register the argument in the symbol + * table so that references to it will succeed. *) + let create_argument_allocas the_function proto = + let args = match proto with + | Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args + in + Array.iteri (fun i ai -> + let var_name = args.(i) in + (* Create an alloca for this variable. *) + let alloca = create_entry_block_alloca the_function var_name in + + (* Store the initial value into the alloca. *) + ignore(build_store ai alloca builder); + + (* Add arguments to variable symbol table. *) + Hashtbl.add named_values var_name alloca; + ) (params the_function) + +For each argument, we make an alloca, store the input value to the +function into the alloca, and register the alloca as the memory location +for the argument. This method gets invoked by ``Codegen.codegen_func`` +right after it sets up the entry block for the function. + +The final missing piece is adding the mem2reg pass, which allows us to +get good codegen once again: + +.. code-block:: ocaml + + let main () = + ... + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + DataLayout.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Promote allocas to registers. *) + add_memory_to_register_promotion the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combining the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + +It is interesting to see what the code looks like before and after the +mem2reg optimization runs. For example, this is the before/after code +for our recursive fib function. Before the optimization: + +.. code-block:: llvm + + define double @fib(double %x) { + entry: + %x1 = alloca double + store double %x, double* %x1 + %x2 = load double* %x1 + %cmptmp = fcmp ult double %x2, 3.000000e+00 + %booltmp = uitofp i1 %cmptmp to double + %ifcond = fcmp one double %booltmp, 0.000000e+00 + br i1 %ifcond, label %then, label %else + + then: ; preds = %entry + br label %ifcont + + else: ; preds = %entry + %x3 = load double* %x1 + %subtmp = fsub double %x3, 1.000000e+00 + %calltmp = call double @fib(double %subtmp) + %x4 = load double* %x1 + %subtmp5 = fsub double %x4, 2.000000e+00 + %calltmp6 = call double @fib(double %subtmp5) + %addtmp = fadd double %calltmp, %calltmp6 + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ] + ret double %iftmp + } + +Here there is only one variable (x, the input argument) but you can +still see the extremely simple-minded code generation strategy we are +using. In the entry block, an alloca is created, and the initial input +value is stored into it. Each reference to the variable does a reload +from the stack. Also, note that we didn't modify the if/then/else +expression, so it still inserts a PHI node. While we could make an +alloca for it, it is actually easier to create a PHI node for it, so we +still just make the PHI. + +Here is the code after the mem2reg pass runs: + +.. code-block:: llvm + + define double @fib(double %x) { + entry: + %cmptmp = fcmp ult double %x, 3.000000e+00 + %booltmp = uitofp i1 %cmptmp to double + %ifcond = fcmp one double %booltmp, 0.000000e+00 + br i1 %ifcond, label %then, label %else + + then: + br label %ifcont + + else: + %subtmp = fsub double %x, 1.000000e+00 + %calltmp = call double @fib(double %subtmp) + %subtmp5 = fsub double %x, 2.000000e+00 + %calltmp6 = call double @fib(double %subtmp5) + %addtmp = fadd double %calltmp, %calltmp6 + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ] + ret double %iftmp + } + +This is a trivial case for mem2reg, since there are no redefinitions of +the variable. The point of showing this is to calm your tension about +inserting such blatent inefficiencies :). + +After the rest of the optimizers run, we get: + +.. code-block:: llvm + + define double @fib(double %x) { + entry: + %cmptmp = fcmp ult double %x, 3.000000e+00 + %booltmp = uitofp i1 %cmptmp to double + %ifcond = fcmp ueq double %booltmp, 0.000000e+00 + br i1 %ifcond, label %else, label %ifcont + + else: + %subtmp = fsub double %x, 1.000000e+00 + %calltmp = call double @fib(double %subtmp) + %subtmp5 = fsub double %x, 2.000000e+00 + %calltmp6 = call double @fib(double %subtmp5) + %addtmp = fadd double %calltmp, %calltmp6 + ret double %addtmp + + ifcont: + ret double 1.000000e+00 + } + +Here we see that the simplifycfg pass decided to clone the return +instruction into the end of the 'else' block. This allowed it to +eliminate some branches and the PHI node. + +Now that all symbol table references are updated to use stack variables, +we'll add the assignment operator. + +New Assignment Operator +======================= + +With our current framework, adding a new assignment operator is really +simple. We will parse it just like any other binary operator, but handle +it internally (instead of allowing the user to define it). The first +step is to set a precedence: + +.. code-block:: ocaml + + let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '=' 2; + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + ... + +Now that the parser knows the precedence of the binary operator, it +takes care of all the parsing and AST generation. We just need to +implement codegen for the assignment operator. This looks like: + +.. code-block:: ocaml + + let rec codegen_expr = function + begin match op with + | '=' -> + (* Special case '=' because we don't want to emit the LHS as an + * expression. *) + let name = + match lhs with + | Ast.Variable name -> name + | _ -> raise (Error "destination of '=' must be a variable") + in + +Unlike the rest of the binary operators, our assignment operator doesn't +follow the "emit LHS, emit RHS, do computation" model. As such, it is +handled as a special case before the other binary operators are handled. +The other strange thing is that it requires the LHS to be a variable. It +is invalid to have "(x+1) = expr" - only things like "x = expr" are +allowed. + +.. code-block:: ocaml + + (* Codegen the rhs. *) + let val_ = codegen_expr rhs in + + (* Lookup the name. *) + let variable = try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name") + in + ignore(build_store val_ variable builder); + val_ + | _ -> + ... + +Once we have the variable, codegen'ing the assignment is +straightforward: we emit the RHS of the assignment, create a store, and +return the computed value. Returning a value allows for chained +assignments like "X = (Y = Z)". + +Now that we have an assignment operator, we can mutate loop variables +and arguments. For example, we can now run code like this: + +:: + + # Function to print a double. + extern printd(x); + + # Define ':' for sequencing: as a low-precedence operator that ignores operands + # and just returns the RHS. + def binary : 1 (x y) y; + + def test(x) + printd(x) : + x = 4 : + printd(x); + + test(123); + +When run, this example prints "123" and then "4", showing that we did +actually mutate the value! Okay, we have now officially implemented our +goal: getting this to work requires SSA construction in the general +case. However, to be really useful, we want the ability to define our +own local variables, lets add this next! + +User-defined Local Variables +============================ + +Adding var/in is just like any other other extensions we made to +Kaleidoscope: we extend the lexer, the parser, the AST and the code +generator. The first step for adding our new 'var/in' construct is to +extend the lexer. As before, this is pretty trivial, the code looks like +this: + +.. code-block:: ocaml + + type token = + ... + (* var definition *) + | Var + + ... + + and lex_ident buffer = parser + ... + | "in" -> [< 'Token.In; stream >] + | "binary" -> [< 'Token.Binary; stream >] + | "unary" -> [< 'Token.Unary; stream >] + | "var" -> [< 'Token.Var; stream >] + ... + +The next step is to define the AST node that we will construct. For +var/in, it looks like this: + +.. code-block:: ocaml + + type expr = + ... + (* variant for var/in. *) + | Var of (string * expr option) array * expr + ... + +var/in allows a list of names to be defined all at once, and each name +can optionally have an initializer value. As such, we capture this +information in the VarNames vector. Also, var/in has a body, this body +is allowed to access the variables defined by the var/in. + +With this in place, we can define the parser pieces. The first thing we +do is add it as a primary expression: + +.. code-block:: ocaml + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr + * ::= ifexpr + * ::= forexpr + * ::= varexpr *) + let rec parse_primary = parser + ... + (* varexpr + * ::= 'var' identifier ('=' expression? + * (',' identifier ('=' expression)?)* 'in' expression *) + | [< 'Token.Var; + (* At least one variable name is required. *) + 'Token.Ident id ?? "expected identifier after var"; + init=parse_var_init; + var_names=parse_var_names [(id, init)]; + (* At this point, we have to have 'in'. *) + 'Token.In ?? "expected 'in' keyword after 'var'"; + body=parse_expr >] -> + Ast.Var (Array.of_list (List.rev var_names), body) + + ... + + and parse_var_init = parser + (* read in the optional initializer. *) + | [< 'Token.Kwd '='; e=parse_expr >] -> Some e + | [< >] -> None + + and parse_var_names accumulator = parser + | [< 'Token.Kwd ','; + 'Token.Ident id ?? "expected identifier list after var"; + init=parse_var_init; + e=parse_var_names ((id, init) :: accumulator) >] -> e + | [< >] -> accumulator + +Now that we can parse and represent the code, we need to support +emission of LLVM IR for it. This code starts out with: + +.. code-block:: ocaml + + let rec codegen_expr = function + ... + | Ast.Var (var_names, body) + let old_bindings = ref [] in + + let the_function = block_parent (insertion_block builder) in + + (* Register all variables and emit their initializer. *) + Array.iter (fun (var_name, init) -> + +Basically it loops over all the variables, installing them one at a +time. For each variable we put into the symbol table, we remember the +previous value that we replace in OldBindings. + +.. code-block:: ocaml + + (* Emit the initializer before adding the variable to scope, this + * prevents the initializer from referencing the variable itself, and + * permits stuff like this: + * var a = 1 in + * var a = a in ... # refers to outer 'a'. *) + let init_val = + match init with + | Some init -> codegen_expr init + (* If not specified, use 0.0. *) + | None -> const_float double_type 0.0 + in + + let alloca = create_entry_block_alloca the_function var_name in + ignore(build_store init_val alloca builder); + + (* Remember the old variable binding so that we can restore the binding + * when we unrecurse. *) + + begin + try + let old_value = Hashtbl.find named_values var_name in + old_bindings := (var_name, old_value) :: !old_bindings; + with Not_found > () + end; + + (* Remember this binding. *) + Hashtbl.add named_values var_name alloca; + ) var_names; + +There are more comments here than code. The basic idea is that we emit +the initializer, create the alloca, then update the symbol table to +point to it. Once all the variables are installed in the symbol table, +we evaluate the body of the var/in expression: + +.. code-block:: ocaml + + (* Codegen the body, now that all vars are in scope. *) + let body_val = codegen_expr body in + +Finally, before returning, we restore the previous variable bindings: + +.. code-block:: ocaml + + (* Pop all our variables from scope. *) + List.iter (fun (var_name, old_value) -> + Hashtbl.add named_values var_name old_value + ) !old_bindings; + + (* Return the body computation. *) + body_val + +The end result of all of this is that we get properly scoped variable +definitions, and we even (trivially) allow mutation of them :). + +With this, we completed what we set out to do. Our nice iterative fib +example from the intro compiles and runs just fine. The mem2reg pass +optimizes all of our stack variables into SSA registers, inserting PHI +nodes where needed, and our front-end remains simple: no "iterated +dominance frontier" computation anywhere in sight. + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +mutable variables and var/in support. To build this example, use: + +.. code-block:: bash + + # Compile + ocamlbuild toy.byte + # Run + ./toy.byte + +Here is the code: + +\_tags: + :: + + <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) + <*.{byte,native}>: g++, use_llvm, use_llvm_analysis + <*.{byte,native}>: use_llvm_executionengine, use_llvm_target + <*.{byte,native}>: use_llvm_scalar_opts, use_bindings + +myocamlbuild.ml: + .. code-block:: ocaml + + open Ocamlbuild_plugin;; + + ocaml_lib ~extern:true "llvm";; + ocaml_lib ~extern:true "llvm_analysis";; + ocaml_lib ~extern:true "llvm_executionengine";; + ocaml_lib ~extern:true "llvm_target";; + ocaml_lib ~extern:true "llvm_scalar_opts";; + + flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);; + dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; + +token.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + + (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) + type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + + (* control *) + | If | Then | Else + | For | In + + (* operators *) + | Binary | Unary + + (* var definition *) + | Var + +lexer.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + + let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + + and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + + and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | "binary" -> [< 'Token.Binary; stream >] + | "unary" -> [< 'Token.Unary; stream >] + | "var" -> [< 'Token.Var; stream >] + | id -> [< 'Token.Ident id; stream >] + + and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] + +ast.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + + (* expr - Base type for all expression nodes. *) + type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a unary operator. *) + | Unary of char * expr + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* variant for if/then/else. *) + | If of expr * expr * expr + + (* variant for for/in. *) + | For of string * expr * expr * expr option * expr + + (* variant for var/in. *) + | Var of (string * expr option) array * expr + + (* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) + type proto = + | Prototype of string * string array + | BinOpPrototype of string * string array * int + + (* func - This type represents a function definition itself. *) + type func = Function of proto * expr + +parser.ml: + .. code-block:: ocaml + + (*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + + (* binop_precedence - This holds the precedence for each binary operator that is + * defined *) + let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + + (* precedence - Get the precedence of the pending binary operator token. *) + let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + + (* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr + * ::= ifexpr + * ::= forexpr + * ::= varexpr *) + let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + + (* forexpr + ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) + | [< 'Token.For; + 'Token.Ident id ?? "expected identifier after for"; + 'Token.Kwd '=' ?? "expected '=' after for"; + stream >] -> + begin parser + | [< + start=parse_expr; + 'Token.Kwd ',' ?? "expected ',' after for"; + end_=parse_expr; + stream >] -> + let step = + begin parser + | [< 'Token.Kwd ','; step=parse_expr >] -> Some step + | [< >] -> None + end stream + in + begin parser + | [< 'Token.In; body=parse_expr >] -> + Ast.For (id, start, end_, step, body) + | [< >] -> + raise (Stream.Error "expected 'in' after for") + end stream + | [< >] -> + raise (Stream.Error "expected '=' after for") + end stream + + (* varexpr + * ::= 'var' identifier ('=' expression? + * (',' identifier ('=' expression)?)* 'in' expression *) + | [< 'Token.Var; + (* At least one variable name is required. *) + 'Token.Ident id ?? "expected identifier after var"; + init=parse_var_init; + var_names=parse_var_names [(id, init)]; + (* At this point, we have to have 'in'. *) + 'Token.In ?? "expected 'in' keyword after 'var'"; + body=parse_expr >] -> + Ast.Var (Array.of_list (List.rev var_names), body) + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + + (* unary + * ::= primary + * ::= '!' unary *) + and parse_unary = parser + (* If this is a unary operator, read it. *) + | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] -> + Ast.Unary (op, operand) + + (* If the current token is not an operator, it must be a primary expr. *) + | [< stream >] -> parse_primary stream + + (* binoprhs + * ::= ('+' primary)* *) + and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_unary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + + and parse_var_init = parser + (* read in the optional initializer. *) + | [< 'Token.Kwd '='; e=parse_expr >] -> Some e + | [< >] -> None + + and parse_var_names accumulator = parser + | [< 'Token.Kwd ','; + 'Token.Ident id ?? "expected identifier list after var"; + init=parse_var_init; + e=parse_var_names ((id, init) :: accumulator) >] -> e + | [< >] -> accumulator + + (* expression + * ::= primary binoprhs *) + and parse_expr = parser + | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream + + (* prototype + * ::= id '(' id* ')' + * ::= binary LETTER number? (id, id) + * ::= unary LETTER number? (id) *) + let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + let parse_operator = parser + | [< 'Token.Unary >] -> "unary", 1 + | [< 'Token.Binary >] -> "binary", 2 + in + let parse_binary_precedence = parser + | [< 'Token.Number n >] -> int_of_float n + | [< >] -> 30 + in + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + | [< (prefix, kind)=parse_operator; + 'Token.Kwd op ?? "expected an operator"; + (* Read the precedence if present. *) + binary_precedence=parse_binary_precedence; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + let name = prefix ^ (String.make 1 op) in + let args = Array.of_list (List.rev args) in + + (* Verify right number of arguments for operator. *) + if Array.length args != kind + then raise (Stream.Error "invalid number of operands for operator") + else + if kind == 1 then + Ast.Prototype (name, args) + else + Ast.BinOpPrototype (name, args, binary_precedence) + | [< >] -> + raise (Stream.Error "expected function name in prototype") + + (* definition ::= 'def' prototype expression *) + let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + + (* toplevelexpr ::= expression *) + let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + + (* external ::= 'extern' prototype *) + let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e + +codegen.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + + open Llvm + + exception Error of string + + let context = global_context () + let the_module = create_module context "my cool jit" + let builder = builder context + let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 + let double_type = double_type context + + (* Create an alloca instruction in the entry block of the function. This + * is used for mutable variables etc. *) + let create_entry_block_alloca the_function var_name = + let builder = builder_at context (instr_begin (entry_block the_function)) in + build_alloca double_type var_name builder + + let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + let v = try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name") + in + (* Load the value. *) + build_load v name builder + | Ast.Unary (op, operand) -> + let operand = codegen_expr operand in + let callee = "unary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown unary operator") + in + build_call callee [|operand|] "unop" builder + | Ast.Binary (op, lhs, rhs) -> + begin match op with + | '=' -> + (* Special case '=' because we don't want to emit the LHS as an + * expression. *) + let name = + match lhs with + | Ast.Variable name -> name + | _ -> raise (Error "destination of '=' must be a variable") + in + + (* Codegen the rhs. *) + let val_ = codegen_expr rhs in + + (* Lookup the name. *) + let variable = try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name") + in + ignore(build_store val_ variable builder); + val_ + | _ -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> + (* If it wasn't a builtin binary operator, it must be a user defined + * one. Emit a call to it. *) + let callee = "binary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "binary operator not found!") + in + build_call callee [|lhs_val; rhs_val|] "binop" builder + end + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + | Ast.If (cond, then_, else_) -> + let cond = codegen_expr cond in + + (* Convert condition to a bool by comparing equal to 0.0 *) + let zero = const_float double_type 0.0 in + let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in + + (* Grab the first block so that we might later add the conditional branch + * to it at the end of the function. *) + let start_bb = insertion_block builder in + let the_function = block_parent start_bb in + + let then_bb = append_block context "then" the_function in + + (* Emit 'then' value. *) + position_at_end then_bb builder; + let then_val = codegen_expr then_ in + + (* Codegen of 'then' can change the current block, update then_bb for the + * phi. We create a new name because one is used for the phi node, and the + * other is used for the conditional branch. *) + let new_then_bb = insertion_block builder in + + (* Emit 'else' value. *) + let else_bb = append_block context "else" the_function in + position_at_end else_bb builder; + let else_val = codegen_expr else_ in + + (* Codegen of 'else' can change the current block, update else_bb for the + * phi. *) + let new_else_bb = insertion_block builder in + + (* Emit merge block. *) + let merge_bb = append_block context "ifcont" the_function in + position_at_end merge_bb builder; + let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in + let phi = build_phi incoming "iftmp" builder in + + (* Return to the start block to add the conditional branch. *) + position_at_end start_bb builder; + ignore (build_cond_br cond_val then_bb else_bb builder); + + (* Set a unconditional branch at the end of the 'then' block and the + * 'else' block to the 'merge' block. *) + position_at_end new_then_bb builder; ignore (build_br merge_bb builder); + position_at_end new_else_bb builder; ignore (build_br merge_bb builder); + + (* Finally, set the builder to the end of the merge block. *) + position_at_end merge_bb builder; + + phi + | Ast.For (var_name, start, end_, step, body) -> + (* Output this as: + * var = alloca double + * ... + * start = startexpr + * store start -> var + * goto loop + * loop: + * ... + * bodyexpr + * ... + * loopend: + * step = stepexpr + * endcond = endexpr + * + * curvar = load var + * nextvar = curvar + step + * store nextvar -> var + * br endcond, loop, endloop + * outloop: *) + + let the_function = block_parent (insertion_block builder) in + + (* Create an alloca for the variable in the entry block. *) + let alloca = create_entry_block_alloca the_function var_name in + + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + + (* Store the value into the alloca. *) + ignore(build_store start_val alloca builder); + + (* Make the new basic block for the loop header, inserting after current + * block. *) + let loop_bb = append_block context "loop" the_function in + + (* Insert an explicit fall through from the current block to the + * loop_bb. *) + ignore (build_br loop_bb builder); + + (* Start insertion in loop_bb. *) + position_at_end loop_bb builder; + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name alloca; + + (* Emit the body of the loop. This, like any other expr, can change the + * current BB. Note that we ignore the value computed by the body, but + * don't allow an error *) + ignore (codegen_expr body); + + (* Emit the step value. *) + let step_val = + match step with + | Some step -> codegen_expr step + (* If not specified, use 1.0. *) + | None -> const_float double_type 1.0 + in + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Reload, increment, and restore the alloca. This handles the case where + * the body of the loop mutates the variable. *) + let cur_var = build_load alloca var_name builder in + let next_var = build_add cur_var step_val "nextvar" builder in + ignore(build_store next_var alloca builder); + + (* Convert condition to a bool by comparing equal to 0.0. *) + let zero = const_float double_type 0.0 in + let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in + + (* Create the "after loop" block and insert it. *) + let after_bb = append_block context "afterloop" the_function in + + (* Insert the conditional branch into the end of loop_end_bb. *) + ignore (build_cond_br end_cond loop_bb after_bb builder); + + (* Any new code will be inserted in after_bb. *) + position_at_end after_bb builder; + + (* Restore the unshadowed variable. *) + begin match old_val with + | Some old_val -> Hashtbl.add named_values var_name old_val + | None -> () + end; + + (* for expr always returns 0.0. *) + const_null double_type + | Ast.Var (var_names, body) -> + let old_bindings = ref [] in + + let the_function = block_parent (insertion_block builder) in + + (* Register all variables and emit their initializer. *) + Array.iter (fun (var_name, init) -> + (* Emit the initializer before adding the variable to scope, this + * prevents the initializer from referencing the variable itself, and + * permits stuff like this: + * var a = 1 in + * var a = a in ... # refers to outer 'a'. *) + let init_val = + match init with + | Some init -> codegen_expr init + (* If not specified, use 0.0. *) + | None -> const_float double_type 0.0 + in + + let alloca = create_entry_block_alloca the_function var_name in + ignore(build_store init_val alloca builder); + + (* Remember the old variable binding so that we can restore the binding + * when we unrecurse. *) + begin + try + let old_value = Hashtbl.find named_values var_name in + old_bindings := (var_name, old_value) :: !old_bindings; + with Not_found -> () + end; + + (* Remember this binding. *) + Hashtbl.add named_values var_name alloca; + ) var_names; + + (* Codegen the body, now that all vars are in scope. *) + let body_val = codegen_expr body in + + (* Pop all our variables from scope. *) + List.iter (fun (var_name, old_value) -> + Hashtbl.add named_values var_name old_value + ) !old_bindings; + + (* Return the body computation. *) + body_val + + let codegen_proto = function + | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + + (* Create an alloca for each argument and register the argument in the symbol + * table so that references to it will succeed. *) + let create_argument_allocas the_function proto = + let args = match proto with + | Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args + in + Array.iteri (fun i ai -> + let var_name = args.(i) in + (* Create an alloca for this variable. *) + let alloca = create_entry_block_alloca the_function var_name in + + (* Store the initial value into the alloca. *) + ignore(build_store ai alloca builder); + + (* Add arguments to variable symbol table. *) + Hashtbl.add named_values var_name alloca; + ) (params the_function) + + let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* If this is an operator, install it. *) + begin match proto with + | Ast.BinOpPrototype (name, args, prec) -> + let op = name.[String.length name - 1] in + Hashtbl.add Parser.binop_precedence op prec; + | _ -> () + end; + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + (* Add all arguments to the symbol table and create their allocas. *) + create_argument_allocas the_function proto; + + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e + +toplevel.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + + (* top ::= definition | external | expression | ';' *) + let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream + +toy.ml: + .. code-block:: ocaml + + (*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + + open Llvm + open Llvm_executionengine + open Llvm_target + open Llvm_scalar_opts + + let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '=' 2; + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + DataLayout.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Promote allocas to registers. *) + add_memory_to_register_promotion the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module + ;; + + main () + +bindings.c + .. code-block:: c + + #include + + /* putchard - putchar that takes a double and returns 0. */ + extern double putchard(double X) { + putchar((char)X); + return 0; + } + + /* printd - printf that takes a double prints it as "%f\n", returning 0. */ + extern double printd(double X) { + printf("%f\n", X); + return 0; + } + +`Next: Conclusion and other useful LLVM tidbits `_ + diff --git a/docs/tutorial/OCamlLangImpl8.rst b/docs/tutorial/OCamlLangImpl8.rst new file mode 100644 index 00000000..3534b2e0 --- /dev/null +++ b/docs/tutorial/OCamlLangImpl8.rst @@ -0,0 +1,267 @@ +====================================================== +Kaleidoscope: Conclusion and other useful LLVM tidbits +====================================================== + +.. contents:: + :local: + +Tutorial Conclusion +=================== + +Welcome to the final chapter of the "`Implementing a language with +LLVM `_" tutorial. In the course of this tutorial, we have +grown our little Kaleidoscope language from being a useless toy, to +being a semi-interesting (but probably still useless) toy. :) + +It is interesting to see how far we've come, and how little code it has +taken. We built the entire lexer, parser, AST, code generator, and an +interactive run-loop (with a JIT!) by-hand in under 700 lines of +(non-comment/non-blank) code. + +Our little language supports a couple of interesting features: it +supports user defined binary and unary operators, it uses JIT +compilation for immediate evaluation, and it supports a few control flow +constructs with SSA construction. + +Part of the idea of this tutorial was to show you how easy and fun it +can be to define, build, and play with languages. Building a compiler +need not be a scary or mystical process! Now that you've seen some of +the basics, I strongly encourage you to take the code and hack on it. +For example, try adding: + +- **global variables** - While global variables have questional value + in modern software engineering, they are often useful when putting + together quick little hacks like the Kaleidoscope compiler itself. + Fortunately, our current setup makes it very easy to add global + variables: just have value lookup check to see if an unresolved + variable is in the global variable symbol table before rejecting it. + To create a new global variable, make an instance of the LLVM + ``GlobalVariable`` class. +- **typed variables** - Kaleidoscope currently only supports variables + of type double. This gives the language a very nice elegance, because + only supporting one type means that you never have to specify types. + Different languages have different ways of handling this. The easiest + way is to require the user to specify types for every variable + definition, and record the type of the variable in the symbol table + along with its Value\*. +- **arrays, structs, vectors, etc** - Once you add types, you can start + extending the type system in all sorts of interesting ways. Simple + arrays are very easy and are quite useful for many different + applications. Adding them is mostly an exercise in learning how the + LLVM `getelementptr <../LangRef.html#i_getelementptr>`_ instruction + works: it is so nifty/unconventional, it `has its own + FAQ <../GetElementPtr.html>`_! If you add support for recursive types + (e.g. linked lists), make sure to read the `section in the LLVM + Programmer's Manual <../ProgrammersManual.html#TypeResolve>`_ that + describes how to construct them. +- **standard runtime** - Our current language allows the user to access + arbitrary external functions, and we use it for things like "printd" + and "putchard". As you extend the language to add higher-level + constructs, often these constructs make the most sense if they are + lowered to calls into a language-supplied runtime. For example, if + you add hash tables to the language, it would probably make sense to + add the routines to a runtime, instead of inlining them all the way. +- **memory management** - Currently we can only access the stack in + Kaleidoscope. It would also be useful to be able to allocate heap + memory, either with calls to the standard libc malloc/free interface + or with a garbage collector. If you would like to use garbage + collection, note that LLVM fully supports `Accurate Garbage + Collection <../GarbageCollection.html>`_ including algorithms that + move objects and need to scan/update the stack. +- **debugger support** - LLVM supports generation of `DWARF Debug + info <../SourceLevelDebugging.html>`_ which is understood by common + debuggers like GDB. Adding support for debug info is fairly + straightforward. The best way to understand it is to compile some + C/C++ code with "``llvm-gcc -g -O0``" and taking a look at what it + produces. +- **exception handling support** - LLVM supports generation of `zero + cost exceptions <../ExceptionHandling.html>`_ which interoperate with + code compiled in other languages. You could also generate code by + implicitly making every function return an error value and checking + it. You could also make explicit use of setjmp/longjmp. There are + many different ways to go here. +- **object orientation, generics, database access, complex numbers, + geometric programming, ...** - Really, there is no end of crazy + features that you can add to the language. +- **unusual domains** - We've been talking about applying LLVM to a + domain that many people are interested in: building a compiler for a + specific language. However, there are many other domains that can use + compiler technology that are not typically considered. For example, + LLVM has been used to implement OpenGL graphics acceleration, + translate C++ code to ActionScript, and many other cute and clever + things. Maybe you will be the first to JIT compile a regular + expression interpreter into native code with LLVM? + +Have fun - try doing something crazy and unusual. Building a language +like everyone else always has, is much less fun than trying something a +little crazy or off the wall and seeing how it turns out. If you get +stuck or want to talk about it, feel free to email the `llvmdev mailing +list `_: it has lots +of people who are interested in languages and are often willing to help +out. + +Before we end this tutorial, I want to talk about some "tips and tricks" +for generating LLVM IR. These are some of the more subtle things that +may not be obvious, but are very useful if you want to take advantage of +LLVM's capabilities. + +Properties of the LLVM IR +========================= + +We have a couple common questions about code in the LLVM IR form - lets +just get these out of the way right now, shall we? + +Target Independence +------------------- + +Kaleidoscope is an example of a "portable language": any program written +in Kaleidoscope will work the same way on any target that it runs on. +Many other languages have this property, e.g. lisp, java, haskell, +javascript, python, etc (note that while these languages are portable, +not all their libraries are). + +One nice aspect of LLVM is that it is often capable of preserving target +independence in the IR: you can take the LLVM IR for a +Kaleidoscope-compiled program and run it on any target that LLVM +supports, even emitting C code and compiling that on targets that LLVM +doesn't support natively. You can trivially tell that the Kaleidoscope +compiler generates target-independent code because it never queries for +any target-specific information when generating code. + +The fact that LLVM provides a compact, target-independent, +representation for code gets a lot of people excited. Unfortunately, +these people are usually thinking about C or a language from the C +family when they are asking questions about language portability. I say +"unfortunately", because there is really no way to make (fully general) +C code portable, other than shipping the source code around (and of +course, C source code is not actually portable in general either - ever +port a really old application from 32- to 64-bits?). + +The problem with C (again, in its full generality) is that it is heavily +laden with target specific assumptions. As one simple example, the +preprocessor often destructively removes target-independence from the +code when it processes the input text: + +.. code-block:: c + + #ifdef __i386__ + int X = 1; + #else + int X = 42; + #endif + +While it is possible to engineer more and more complex solutions to +problems like this, it cannot be solved in full generality in a way that +is better than shipping the actual source code. + +That said, there are interesting subsets of C that can be made portable. +If you are willing to fix primitive types to a fixed size (say int = +32-bits, and long = 64-bits), don't care about ABI compatibility with +existing binaries, and are willing to give up some other minor features, +you can have portable code. This can make sense for specialized domains +such as an in-kernel language. + +Safety Guarantees +----------------- + +Many of the languages above are also "safe" languages: it is impossible +for a program written in Java to corrupt its address space and crash the +process (assuming the JVM has no bugs). Safety is an interesting +property that requires a combination of language design, runtime +support, and often operating system support. + +It is certainly possible to implement a safe language in LLVM, but LLVM +IR does not itself guarantee safety. The LLVM IR allows unsafe pointer +casts, use after free bugs, buffer over-runs, and a variety of other +problems. Safety needs to be implemented as a layer on top of LLVM and, +conveniently, several groups have investigated this. Ask on the `llvmdev +mailing list `_ if +you are interested in more details. + +Language-Specific Optimizations +------------------------------- + +One thing about LLVM that turns off many people is that it does not +solve all the world's problems in one system (sorry 'world hunger', +someone else will have to solve you some other day). One specific +complaint is that people perceive LLVM as being incapable of performing +high-level language-specific optimization: LLVM "loses too much +information". + +Unfortunately, this is really not the place to give you a full and +unified version of "Chris Lattner's theory of compiler design". Instead, +I'll make a few observations: + +First, you're right that LLVM does lose information. For example, as of +this writing, there is no way to distinguish in the LLVM IR whether an +SSA-value came from a C "int" or a C "long" on an ILP32 machine (other +than debug info). Both get compiled down to an 'i32' value and the +information about what it came from is lost. The more general issue +here, is that the LLVM type system uses "structural equivalence" instead +of "name equivalence". Another place this surprises people is if you +have two types in a high-level language that have the same structure +(e.g. two different structs that have a single int field): these types +will compile down into a single LLVM type and it will be impossible to +tell what it came from. + +Second, while LLVM does lose information, LLVM is not a fixed target: we +continue to enhance and improve it in many different ways. In addition +to adding new features (LLVM did not always support exceptions or debug +info), we also extend the IR to capture important information for +optimization (e.g. whether an argument is sign or zero extended, +information about pointers aliasing, etc). Many of the enhancements are +user-driven: people want LLVM to include some specific feature, so they +go ahead and extend it. + +Third, it is *possible and easy* to add language-specific optimizations, +and you have a number of choices in how to do it. As one trivial +example, it is easy to add language-specific optimization passes that +"know" things about code compiled for a language. In the case of the C +family, there is an optimization pass that "knows" about the standard C +library functions. If you call "exit(0)" in main(), it knows that it is +safe to optimize that into "return 0;" because C specifies what the +'exit' function does. + +In addition to simple library knowledge, it is possible to embed a +variety of other language-specific information into the LLVM IR. If you +have a specific need and run into a wall, please bring the topic up on +the llvmdev list. At the very worst, you can always treat LLVM as if it +were a "dumb code generator" and implement the high-level optimizations +you desire in your front-end, on the language-specific AST. + +Tips and Tricks +=============== + +There is a variety of useful tips and tricks that you come to know after +working on/with LLVM that aren't obvious at first glance. Instead of +letting everyone rediscover them, this section talks about some of these +issues. + +Implementing portable offsetof/sizeof +------------------------------------- + +One interesting thing that comes up, if you are trying to keep the code +generated by your compiler "target independent", is that you often need +to know the size of some LLVM type or the offset of some field in an +llvm structure. For example, you might need to pass the size of a type +into a function that allocates memory. + +Unfortunately, this can vary widely across targets: for example the +width of a pointer is trivially target-specific. However, there is a +`clever way to use the getelementptr +instruction `_ +that allows you to compute this in a portable way. + +Garbage Collected Stack Frames +------------------------------ + +Some languages want to explicitly manage their stack frames, often so +that they are garbage collected or to allow easy implementation of +closures. There are often better ways to implement these features than +explicit stack frames, but `LLVM does support +them, `_ +if you want. It requires your front-end to convert the code into +`Continuation Passing +Style `_ and +the use of tail calls (which LLVM also supports). + diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst new file mode 100644 index 00000000..dde53bad --- /dev/null +++ b/docs/tutorial/index.rst @@ -0,0 +1,43 @@ +================================ +LLVM Tutorial: Table of Contents +================================ + +Kaleidoscope: Implementing a Language with LLVM +=============================================== + +.. toctree:: + :titlesonly: + :glob: + :numbered: + + LangImpl* + +Kaleidoscope: Implementing a Language with LLVM in Objective Caml +================================================================= + +.. toctree:: + :titlesonly: + :glob: + :numbered: + + OCamlLangImpl* + +External Tutorials +================== + +`Tutorial: Creating an LLVM Backend for the Cpu0 Architecture `_ + A step-by-step tutorial for developing an LLVM backend. Under + active development at ``_ (please + contribute!). + +`Howto: Implementing LLVM Integrated Assembler`_ + A simple guide for how to implement an LLVM integrated assembler for an + architecture. + +.. _`Howto: Implementing LLVM Integrated Assembler`: http://www.embecosm.com/appnotes/ean10/ean10-howto-llvmas-1.0.html + +Advanced Topics +=============== + +#. `Writing an Optimization for LLVM `_ + diff --git a/docs/yaml2obj.rst b/docs/yaml2obj.rst new file mode 100644 index 00000000..2c55f02f --- /dev/null +++ b/docs/yaml2obj.rst @@ -0,0 +1,220 @@ +yaml2obj +======== + +yaml2obj takes a YAML description of an object file and converts it to a binary +file. + + $ yaml2obj input-file + +.. program:: yaml2obj + +Outputs the binary to stdout. + +COFF Syntax +----------- + +Here's a sample COFF file. + +.. code-block:: yaml + + header: + Machine: IMAGE_FILE_MACHINE_I386 # (0x14C) + + sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE + , IMAGE_SCN_ALIGN_16BYTES + , IMAGE_SCN_MEM_EXECUTE + , IMAGE_SCN_MEM_READ + ] # 0x60500020 + SectionData: + "\x83\xEC\x0C\xC7\x44\x24\x08\x00\x00\x00\x00\xC7\x04\x24\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x8B\x44\x24\x08\x83\xC4\x0C\xC3" # |....D$.......$...............D$.....| + + symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL # (0) + ComplexType: IMAGE_SYM_DTYPE_NULL # (0) + StorageClass: IMAGE_SYM_CLASS_STATIC # (3) + NumberOfAuxSymbols: 1 + AuxiliaryData: + "\x24\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00" # |$.................| + + - Name: _main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL # (0) + ComplexType: IMAGE_SYM_DTYPE_NULL # (0) + StorageClass: IMAGE_SYM_CLASS_EXTERNAL # (2) + +Here's a simplified Kwalify_ schema with an extension to allow alternate types. + +.. _Kwalify: http://www.kuwata-lab.com/kwalify/ruby/users-guide.html + +.. code-block:: yaml + + type: map + mapping: + header: + type: map + mapping: + Machine: [ {type: str, enum: + [ IMAGE_FILE_MACHINE_UNKNOWN + , IMAGE_FILE_MACHINE_AM33 + , IMAGE_FILE_MACHINE_AMD64 + , IMAGE_FILE_MACHINE_ARM + , IMAGE_FILE_MACHINE_ARMV7 + , IMAGE_FILE_MACHINE_EBC + , IMAGE_FILE_MACHINE_I386 + , IMAGE_FILE_MACHINE_IA64 + , IMAGE_FILE_MACHINE_M32R + , IMAGE_FILE_MACHINE_MIPS16 + , IMAGE_FILE_MACHINE_MIPSFPU + , IMAGE_FILE_MACHINE_MIPSFPU16 + , IMAGE_FILE_MACHINE_POWERPC + , IMAGE_FILE_MACHINE_POWERPCFP + , IMAGE_FILE_MACHINE_R4000 + , IMAGE_FILE_MACHINE_SH3 + , IMAGE_FILE_MACHINE_SH3DSP + , IMAGE_FILE_MACHINE_SH4 + , IMAGE_FILE_MACHINE_SH5 + , IMAGE_FILE_MACHINE_THUMB + , IMAGE_FILE_MACHINE_WCEMIPSV2 + ]} + , {type: int} + ] + Characteristics: + - type: seq + sequence: + - type: str + enum: [ IMAGE_FILE_RELOCS_STRIPPED + , IMAGE_FILE_EXECUTABLE_IMAGE + , IMAGE_FILE_LINE_NUMS_STRIPPED + , IMAGE_FILE_LOCAL_SYMS_STRIPPED + , IMAGE_FILE_AGGRESSIVE_WS_TRIM + , IMAGE_FILE_LARGE_ADDRESS_AWARE + , IMAGE_FILE_BYTES_REVERSED_LO + , IMAGE_FILE_32BIT_MACHINE + , IMAGE_FILE_DEBUG_STRIPPED + , IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP + , IMAGE_FILE_NET_RUN_FROM_SWAP + , IMAGE_FILE_SYSTEM + , IMAGE_FILE_DLL + , IMAGE_FILE_UP_SYSTEM_ONLY + , IMAGE_FILE_BYTES_REVERSED_HI + ] + - type: int + sections: + type: seq + sequence: + - type: map + mapping: + Name: {type: str} + Characteristics: + - type: seq + sequence: + - type: str + enum: [ IMAGE_SCN_TYPE_NO_PAD + , IMAGE_SCN_CNT_CODE + , IMAGE_SCN_CNT_INITIALIZED_DATA + , IMAGE_SCN_CNT_UNINITIALIZED_DATA + , IMAGE_SCN_LNK_OTHER + , IMAGE_SCN_LNK_INFO + , IMAGE_SCN_LNK_REMOVE + , IMAGE_SCN_LNK_COMDAT + , IMAGE_SCN_GPREL + , IMAGE_SCN_MEM_PURGEABLE + , IMAGE_SCN_MEM_16BIT + , IMAGE_SCN_MEM_LOCKED + , IMAGE_SCN_MEM_PRELOAD + , IMAGE_SCN_ALIGN_1BYTES + , IMAGE_SCN_ALIGN_2BYTES + , IMAGE_SCN_ALIGN_4BYTES + , IMAGE_SCN_ALIGN_8BYTES + , IMAGE_SCN_ALIGN_16BYTES + , IMAGE_SCN_ALIGN_32BYTES + , IMAGE_SCN_ALIGN_64BYTES + , IMAGE_SCN_ALIGN_128BYTES + , IMAGE_SCN_ALIGN_256BYTES + , IMAGE_SCN_ALIGN_512BYTES + , IMAGE_SCN_ALIGN_1024BYTES + , IMAGE_SCN_ALIGN_2048BYTES + , IMAGE_SCN_ALIGN_4096BYTES + , IMAGE_SCN_ALIGN_8192BYTES + , IMAGE_SCN_LNK_NRELOC_OVFL + , IMAGE_SCN_MEM_DISCARDABLE + , IMAGE_SCN_MEM_NOT_CACHED + , IMAGE_SCN_MEM_NOT_PAGED + , IMAGE_SCN_MEM_SHARED + , IMAGE_SCN_MEM_EXECUTE + , IMAGE_SCN_MEM_READ + , IMAGE_SCN_MEM_WRITE + ] + - type: int + SectionData: {type: str} + symbols: + type: seq + sequence: + - type: map + mapping: + Name: {type: str} + Value: {type: int} + SectionNumber: {type: int} + SimpleType: [ {type: str, enum: [ IMAGE_SYM_TYPE_NULL + , IMAGE_SYM_TYPE_VOID + , IMAGE_SYM_TYPE_CHAR + , IMAGE_SYM_TYPE_SHORT + , IMAGE_SYM_TYPE_INT + , IMAGE_SYM_TYPE_LONG + , IMAGE_SYM_TYPE_FLOAT + , IMAGE_SYM_TYPE_DOUBLE + , IMAGE_SYM_TYPE_STRUCT + , IMAGE_SYM_TYPE_UNION + , IMAGE_SYM_TYPE_ENUM + , IMAGE_SYM_TYPE_MOE + , IMAGE_SYM_TYPE_BYTE + , IMAGE_SYM_TYPE_WORD + , IMAGE_SYM_TYPE_UINT + , IMAGE_SYM_TYPE_DWORD + ]} + , {type: int} + ] + ComplexType: [ {type: str, enum: [ IMAGE_SYM_DTYPE_NULL + , IMAGE_SYM_DTYPE_POINTER + , IMAGE_SYM_DTYPE_FUNCTION + , IMAGE_SYM_DTYPE_ARRAY + ]} + , {type: int} + ] + StorageClass: [ {type: str, enum: + [ IMAGE_SYM_CLASS_END_OF_FUNCTION + , IMAGE_SYM_CLASS_NULL + , IMAGE_SYM_CLASS_AUTOMATIC + , IMAGE_SYM_CLASS_EXTERNAL + , IMAGE_SYM_CLASS_STATIC + , IMAGE_SYM_CLASS_REGISTER + , IMAGE_SYM_CLASS_EXTERNAL_DEF + , IMAGE_SYM_CLASS_LABEL + , IMAGE_SYM_CLASS_UNDEFINED_LABEL + , IMAGE_SYM_CLASS_MEMBER_OF_STRUCT + , IMAGE_SYM_CLASS_ARGUMENT + , IMAGE_SYM_CLASS_STRUCT_TAG + , IMAGE_SYM_CLASS_MEMBER_OF_UNION + , IMAGE_SYM_CLASS_UNION_TAG + , IMAGE_SYM_CLASS_TYPE_DEFINITION + , IMAGE_SYM_CLASS_UNDEFINED_STATIC + , IMAGE_SYM_CLASS_ENUM_TAG + , IMAGE_SYM_CLASS_MEMBER_OF_ENUM + , IMAGE_SYM_CLASS_REGISTER_PARAM + , IMAGE_SYM_CLASS_BIT_FIELD + , IMAGE_SYM_CLASS_BLOCK + , IMAGE_SYM_CLASS_FUNCTION + , IMAGE_SYM_CLASS_END_OF_STRUCT + , IMAGE_SYM_CLASS_FILE + , IMAGE_SYM_CLASS_SECTION + , IMAGE_SYM_CLASS_WEAK_EXTERNAL + , IMAGE_SYM_CLASS_CLR_TOKEN + ]} + , {type: int} + ] diff --git a/examples/BrainF/BrainF.cpp b/examples/BrainF/BrainF.cpp new file mode 100644 index 00000000..f8129b81 --- /dev/null +++ b/examples/BrainF/BrainF.cpp @@ -0,0 +1,467 @@ +//===-- BrainF.cpp - BrainF compiler example ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +// This class compiles the BrainF language into LLVM assembly. +// +// The BrainF language has 8 commands: +// Command Equivalent C Action +// ------- ------------ ------ +// , *h=getchar(); Read a character from stdin, 255 on EOF +// . putchar(*h); Write a character to stdout +// - --*h; Decrement tape +// + ++*h; Increment tape +// < --h; Move head left +// > ++h; Move head right +// [ while(*h) { Start loop +// ] } End loop +// +//===--------------------------------------------------------------------===// + +#include "BrainF.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include +using namespace llvm; + +//Set the constants for naming +const char *BrainF::tapereg = "tape"; +const char *BrainF::headreg = "head"; +const char *BrainF::label = "brainf"; +const char *BrainF::testreg = "test"; + +Module *BrainF::parse(std::istream *in1, int mem, CompileFlags cf, + LLVMContext& Context) { + in = in1; + memtotal = mem; + comflag = cf; + + header(Context); + readloop(0, 0, 0, Context); + delete builder; + return module; +} + +void BrainF::header(LLVMContext& C) { + module = new Module("BrainF", C); + + //Function prototypes + + //declare void @llvm.memset.p0i8.i32(i8 *, i8, i32, i32, i1) + Type *Tys[] = { Type::getInt8PtrTy(C), Type::getInt32Ty(C) }; + Function *memset_func = Intrinsic::getDeclaration(module, Intrinsic::memset, + Tys); + + //declare i32 @getchar() + getchar_func = cast(module-> + getOrInsertFunction("getchar", IntegerType::getInt32Ty(C), NULL)); + + //declare i32 @putchar(i32) + putchar_func = cast(module-> + getOrInsertFunction("putchar", IntegerType::getInt32Ty(C), + IntegerType::getInt32Ty(C), NULL)); + + + //Function header + + //define void @brainf() + brainf_func = cast(module-> + getOrInsertFunction("brainf", Type::getVoidTy(C), NULL)); + + builder = new IRBuilder<>(BasicBlock::Create(C, label, brainf_func)); + + //%arr = malloc i8, i32 %d + ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal)); + BasicBlock* BB = builder->GetInsertBlock(); + Type* IntPtrTy = IntegerType::getInt32Ty(C); + Type* Int8Ty = IntegerType::getInt8Ty(C); + Constant* allocsize = ConstantExpr::getSizeOf(Int8Ty); + allocsize = ConstantExpr::getTruncOrBitCast(allocsize, IntPtrTy); + ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, Int8Ty, allocsize, val_mem, + NULL, "arr"); + BB->getInstList().push_back(cast(ptr_arr)); + + //call void @llvm.memset.p0i8.i32(i8 *%arr, i8 0, i32 %d, i32 1, i1 0) + { + Value *memset_params[] = { + ptr_arr, + ConstantInt::get(C, APInt(8, 0)), + val_mem, + ConstantInt::get(C, APInt(32, 1)), + ConstantInt::get(C, APInt(1, 0)) + }; + + CallInst *memset_call = builder-> + CreateCall(memset_func, memset_params); + memset_call->setTailCall(false); + } + + //%arrmax = getelementptr i8 *%arr, i32 %d + if (comflag & flag_arraybounds) { + ptr_arrmax = builder-> + CreateGEP(ptr_arr, ConstantInt::get(C, APInt(32, memtotal)), "arrmax"); + } + + //%head.%d = getelementptr i8 *%arr, i32 %d + curhead = builder->CreateGEP(ptr_arr, + ConstantInt::get(C, APInt(32, memtotal/2)), + headreg); + + + + //Function footer + + //brainf.end: + endbb = BasicBlock::Create(C, label, brainf_func); + + //call free(i8 *%arr) + endbb->getInstList().push_back(CallInst::CreateFree(ptr_arr, endbb)); + + //ret void + ReturnInst::Create(C, endbb); + + + + //Error block for array out of bounds + if (comflag & flag_arraybounds) + { + //@aberrormsg = internal constant [%d x i8] c"\00" + Constant *msg_0 = + ConstantDataArray::getString(C, "Error: The head has left the tape.", + true); + + GlobalVariable *aberrormsg = new GlobalVariable( + *module, + msg_0->getType(), + true, + GlobalValue::InternalLinkage, + msg_0, + "aberrormsg"); + + //declare i32 @puts(i8 *) + Function *puts_func = cast(module-> + getOrInsertFunction("puts", IntegerType::getInt32Ty(C), + PointerType::getUnqual(IntegerType::getInt8Ty(C)), NULL)); + + //brainf.aberror: + aberrorbb = BasicBlock::Create(C, label, brainf_func); + + //call i32 @puts(i8 *getelementptr([%d x i8] *@aberrormsg, i32 0, i32 0)) + { + Constant *zero_32 = Constant::getNullValue(IntegerType::getInt32Ty(C)); + + Constant *gep_params[] = { + zero_32, + zero_32 + }; + + Constant *msgptr = ConstantExpr:: + getGetElementPtr(aberrormsg, gep_params); + + Value *puts_params[] = { + msgptr + }; + + CallInst *puts_call = + CallInst::Create(puts_func, + puts_params, + "", aberrorbb); + puts_call->setTailCall(false); + } + + //br label %brainf.end + BranchInst::Create(endbb, aberrorbb); + } +} + +void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, + LLVMContext &C) { + Symbol cursym = SYM_NONE; + int curvalue = 0; + Symbol nextsym = SYM_NONE; + int nextvalue = 0; + char c; + int loop; + int direction; + + while(cursym != SYM_EOF && cursym != SYM_ENDLOOP) { + // Write out commands + switch(cursym) { + case SYM_NONE: + // Do nothing + break; + + case SYM_READ: + { + //%tape.%d = call i32 @getchar() + CallInst *getchar_call = builder->CreateCall(getchar_func, tapereg); + getchar_call->setTailCall(false); + Value *tape_0 = getchar_call; + + //%tape.%d = trunc i32 %tape.%d to i8 + Value *tape_1 = builder-> + CreateTrunc(tape_0, IntegerType::getInt8Ty(C), tapereg); + + //store i8 %tape.%d, i8 *%head.%d + builder->CreateStore(tape_1, curhead); + } + break; + + case SYM_WRITE: + { + //%tape.%d = load i8 *%head.%d + LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg); + + //%tape.%d = sext i8 %tape.%d to i32 + Value *tape_1 = builder-> + CreateSExt(tape_0, IntegerType::getInt32Ty(C), tapereg); + + //call i32 @putchar(i32 %tape.%d) + Value *putchar_params[] = { + tape_1 + }; + CallInst *putchar_call = builder-> + CreateCall(putchar_func, + putchar_params); + putchar_call->setTailCall(false); + } + break; + + case SYM_MOVE: + { + //%head.%d = getelementptr i8 *%head.%d, i32 %d + curhead = builder-> + CreateGEP(curhead, ConstantInt::get(C, APInt(32, curvalue)), + headreg); + + //Error block for array out of bounds + if (comflag & flag_arraybounds) + { + //%test.%d = icmp uge i8 *%head.%d, %arrmax + Value *test_0 = builder-> + CreateICmpUGE(curhead, ptr_arrmax, testreg); + + //%test.%d = icmp ult i8 *%head.%d, %arr + Value *test_1 = builder-> + CreateICmpULT(curhead, ptr_arr, testreg); + + //%test.%d = or i1 %test.%d, %test.%d + Value *test_2 = builder-> + CreateOr(test_0, test_1, testreg); + + //br i1 %test.%d, label %main.%d, label %main.%d + BasicBlock *nextbb = BasicBlock::Create(C, label, brainf_func); + builder->CreateCondBr(test_2, aberrorbb, nextbb); + + //main.%d: + builder->SetInsertPoint(nextbb); + } + } + break; + + case SYM_CHANGE: + { + //%tape.%d = load i8 *%head.%d + LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg); + + //%tape.%d = add i8 %tape.%d, %d + Value *tape_1 = builder-> + CreateAdd(tape_0, ConstantInt::get(C, APInt(8, curvalue)), tapereg); + + //store i8 %tape.%d, i8 *%head.%d\n" + builder->CreateStore(tape_1, curhead); + } + break; + + case SYM_LOOP: + { + //br label %main.%d + BasicBlock *testbb = BasicBlock::Create(C, label, brainf_func); + builder->CreateBr(testbb); + + //main.%d: + BasicBlock *bb_0 = builder->GetInsertBlock(); + BasicBlock *bb_1 = BasicBlock::Create(C, label, brainf_func); + builder->SetInsertPoint(bb_1); + + // Make part of PHI instruction now, wait until end of loop to finish + PHINode *phi_0 = + PHINode::Create(PointerType::getUnqual(IntegerType::getInt8Ty(C)), + 2, headreg, testbb); + phi_0->addIncoming(curhead, bb_0); + curhead = phi_0; + + readloop(phi_0, bb_1, testbb, C); + } + break; + + default: + std::cerr << "Error: Unknown symbol.\n"; + abort(); + break; + } + + cursym = nextsym; + curvalue = nextvalue; + nextsym = SYM_NONE; + + // Reading stdin loop + loop = (cursym == SYM_NONE) + || (cursym == SYM_MOVE) + || (cursym == SYM_CHANGE); + while(loop) { + *in>>c; + if (in->eof()) { + if (cursym == SYM_NONE) { + cursym = SYM_EOF; + } else { + nextsym = SYM_EOF; + } + loop = 0; + } else { + direction = 1; + switch(c) { + case '-': + direction = -1; + // Fall through + + case '+': + if (cursym == SYM_CHANGE) { + curvalue += direction; + // loop = 1 + } else { + if (cursym == SYM_NONE) { + cursym = SYM_CHANGE; + curvalue = direction; + // loop = 1 + } else { + nextsym = SYM_CHANGE; + nextvalue = direction; + loop = 0; + } + } + break; + + case '<': + direction = -1; + // Fall through + + case '>': + if (cursym == SYM_MOVE) { + curvalue += direction; + // loop = 1 + } else { + if (cursym == SYM_NONE) { + cursym = SYM_MOVE; + curvalue = direction; + // loop = 1 + } else { + nextsym = SYM_MOVE; + nextvalue = direction; + loop = 0; + } + } + break; + + case ',': + if (cursym == SYM_NONE) { + cursym = SYM_READ; + } else { + nextsym = SYM_READ; + } + loop = 0; + break; + + case '.': + if (cursym == SYM_NONE) { + cursym = SYM_WRITE; + } else { + nextsym = SYM_WRITE; + } + loop = 0; + break; + + case '[': + if (cursym == SYM_NONE) { + cursym = SYM_LOOP; + } else { + nextsym = SYM_LOOP; + } + loop = 0; + break; + + case ']': + if (cursym == SYM_NONE) { + cursym = SYM_ENDLOOP; + } else { + nextsym = SYM_ENDLOOP; + } + loop = 0; + break; + + // Ignore other characters + default: + break; + } + } + } + } + + if (cursym == SYM_ENDLOOP) { + if (!phi) { + std::cerr << "Error: Extra ']'\n"; + abort(); + } + + // Write loop test + { + //br label %main.%d + builder->CreateBr(testbb); + + //main.%d: + + //%head.%d = phi i8 *[%head.%d, %main.%d], [%head.%d, %main.%d] + //Finish phi made at beginning of loop + phi->addIncoming(curhead, builder->GetInsertBlock()); + Value *head_0 = phi; + + //%tape.%d = load i8 *%head.%d + LoadInst *tape_0 = new LoadInst(head_0, tapereg, testbb); + + //%test.%d = icmp eq i8 %tape.%d, 0 + ICmpInst *test_0 = new ICmpInst(*testbb, ICmpInst::ICMP_EQ, tape_0, + ConstantInt::get(C, APInt(8, 0)), testreg); + + //br i1 %test.%d, label %main.%d, label %main.%d + BasicBlock *bb_0 = BasicBlock::Create(C, label, brainf_func); + BranchInst::Create(bb_0, oldbb, test_0, testbb); + + //main.%d: + builder->SetInsertPoint(bb_0); + + //%head.%d = phi i8 *[%head.%d, %main.%d] + PHINode *phi_1 = builder-> + CreatePHI(PointerType::getUnqual(IntegerType::getInt8Ty(C)), 1, + headreg); + phi_1->addIncoming(head_0, testbb); + curhead = phi_1; + } + + return; + } + + //End of the program, so go to return block + builder->CreateBr(endbb); + + if (phi) { + std::cerr << "Error: Missing ']'\n"; + abort(); + } +} diff --git a/examples/BrainF/BrainF.h b/examples/BrainF/BrainF.h new file mode 100644 index 00000000..15e9e084 --- /dev/null +++ b/examples/BrainF/BrainF.h @@ -0,0 +1,94 @@ +//===-- BrainF.h - BrainF compiler class ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +// This class stores the data for the BrainF compiler so it doesn't have +// to pass all of it around. The main method is parse. +// +//===--------------------------------------------------------------------===// + +#ifndef BRAINF_H +#define BRAINF_H + +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" + +using namespace llvm; + +/// This class provides a parser for the BrainF language. +/// The class itself is made to store values during +/// parsing so they don't have to be passed around +/// as much. +class BrainF { + public: + /// Options for how BrainF should compile + enum CompileFlags { + flag_off = 0, + flag_arraybounds = 1 + }; + + /// This is the main method. It parses BrainF from in1 + /// and returns the module with a function + /// void brainf() + /// containing the resulting code. + /// On error, it calls abort. + /// The caller must delete the returned module. + Module *parse(std::istream *in1, int mem, CompileFlags cf, + LLVMContext& C); + + protected: + /// The different symbols in the BrainF language + enum Symbol { + SYM_NONE, + SYM_READ, + SYM_WRITE, + SYM_MOVE, + SYM_CHANGE, + SYM_LOOP, + SYM_ENDLOOP, + SYM_EOF + }; + + /// Names of the different parts of the language. + /// Tape is used for reading and writing the tape. + /// headreg is used for the position of the head. + /// label is used for the labels for the BasicBlocks. + /// testreg is used for testing the loop exit condition. + static const char *tapereg; + static const char *headreg; + static const char *label; + static const char *testreg; + + /// Put the brainf function preamble and other fixed pieces of code + void header(LLVMContext& C); + + /// The main loop for parsing. It calls itself recursively + /// to handle the depth of nesting of "[]". + void readloop(PHINode *phi, BasicBlock *oldbb, + BasicBlock *testbb, LLVMContext &Context); + + /// Constants during parsing + int memtotal; + CompileFlags comflag; + std::istream *in; + Module *module; + Function *brainf_func; + Function *getchar_func; + Function *putchar_func; + Value *ptr_arr; + Value *ptr_arrmax; + BasicBlock *endbb; + BasicBlock *aberrorbb; + + /// Variables + IRBuilder<> *builder; + Value *curhead; +}; + +#endif diff --git a/examples/BrainF/BrainFDriver.cpp b/examples/BrainF/BrainFDriver.cpp new file mode 100644 index 00000000..a6a109d5 --- /dev/null +++ b/examples/BrainF/BrainFDriver.cpp @@ -0,0 +1,159 @@ +//===-- BrainFDriver.cpp - BrainF compiler driver -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +// This program converts the BrainF language into LLVM assembly, +// which it can then run using the JIT or output as BitCode. +// +// This implementation has a tape of 65536 bytes, +// with the head starting in the middle. +// Range checking is off by default, so be careful. +// It can be enabled with -abc. +// +// Use: +// ./BrainF -jit prog.bf #Run program now +// ./BrainF -jit -abc prog.bf #Run program now safely +// ./BrainF prog.bf #Write as BitCode +// +// lli prog.bf.bc #Run generated BitCode +// +//===--------------------------------------------------------------------===// + +#include "BrainF.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/Constants.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +//Command line options + +static cl::opt +InputFilename(cl::Positional, cl::desc("")); + +static cl::opt +OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); + +static cl::opt +ArrayBoundsChecking("abc", cl::desc("Enable array bounds checking")); + +static cl::opt +JIT("jit", cl::desc("Run program Just-In-Time")); + + +//Add main function so can be fully compiled +void addMainFunction(Module *mod) { + //define i32 @main(i32 %argc, i8 **%argv) + Function *main_func = cast(mod-> + getOrInsertFunction("main", IntegerType::getInt32Ty(mod->getContext()), + IntegerType::getInt32Ty(mod->getContext()), + PointerType::getUnqual(PointerType::getUnqual( + IntegerType::getInt8Ty(mod->getContext()))), NULL)); + { + Function::arg_iterator args = main_func->arg_begin(); + Value *arg_0 = args++; + arg_0->setName("argc"); + Value *arg_1 = args++; + arg_1->setName("argv"); + } + + //main.0: + BasicBlock *bb = BasicBlock::Create(mod->getContext(), "main.0", main_func); + + //call void @brainf() + { + CallInst *brainf_call = CallInst::Create(mod->getFunction("brainf"), + "", bb); + brainf_call->setTailCall(false); + } + + //ret i32 0 + ReturnInst::Create(mod->getContext(), + ConstantInt::get(mod->getContext(), APInt(32, 0)), bb); +} + +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv, " BrainF compiler\n"); + + LLVMContext &Context = getGlobalContext(); + + if (InputFilename == "") { + errs() << "Error: You must specify the filename of the program to " + "be compiled. Use --help to see the options.\n"; + abort(); + } + + //Get the output stream + raw_ostream *out = &outs(); + if (!JIT) { + if (OutputFilename == "") { + std::string base = InputFilename; + if (InputFilename == "-") { base = "a"; } + + // Use default filename. + OutputFilename = base+".bc"; + } + if (OutputFilename != "-") { + std::string ErrInfo; + out = new raw_fd_ostream(OutputFilename.c_str(), ErrInfo, + sys::fs::F_Binary); + } + } + + //Get the input stream + std::istream *in = &std::cin; + if (InputFilename != "-") + in = new std::ifstream(InputFilename.c_str()); + + //Gather the compile flags + BrainF::CompileFlags cf = BrainF::flag_off; + if (ArrayBoundsChecking) + cf = BrainF::CompileFlags(cf | BrainF::flag_arraybounds); + + //Read the BrainF program + BrainF bf; + Module *mod = bf.parse(in, 65536, cf, Context); //64 KiB + if (in != &std::cin) + delete in; + addMainFunction(mod); + + //Verify generated code + if (verifyModule(*mod)) { + errs() << "Error: module failed verification. This shouldn't happen.\n"; + abort(); + } + + //Write it out + if (JIT) { + InitializeNativeTarget(); + + outs() << "------- Running JIT -------\n"; + ExecutionEngine *ee = EngineBuilder(mod).create(); + std::vector args; + Function *brainf_func = mod->getFunction("brainf"); + GenericValue gv = ee->runFunction(brainf_func, args); + } else { + WriteBitcodeToFile(mod, *out); + } + + //Clean up + if (out != &outs()) + delete out; + delete mod; + + llvm_shutdown(); + + return 0; +} diff --git a/examples/BrainF/CMakeLists.txt b/examples/BrainF/CMakeLists.txt new file mode 100644 index 00000000..7bec105c --- /dev/null +++ b/examples/BrainF/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS jit bitwriter nativecodegen interpreter) + +add_llvm_example(BrainF + BrainF.cpp + BrainFDriver.cpp + ) diff --git a/examples/BrainF/Makefile b/examples/BrainF/Makefile new file mode 100644 index 00000000..2c3e0662 --- /dev/null +++ b/examples/BrainF/Makefile @@ -0,0 +1,15 @@ +##===- examples/BrainF/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. +TOOLNAME = BrainF +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := jit bitwriter nativecodegen interpreter + +include $(LEVEL)/Makefile.common diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 00000000..54ee6cc3 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,13 @@ +add_subdirectory(BrainF) +add_subdirectory(Fibonacci) +add_subdirectory(HowToUseJIT) +add_subdirectory(Kaleidoscope) +add_subdirectory(ModuleMaker) + +if( NOT WIN32 ) + add_subdirectory(ExceptionDemo) +endif() + +if( HAVE_PTHREAD_H ) + add_subdirectory(ParallelJIT) +endif( HAVE_PTHREAD_H ) diff --git a/examples/ExceptionDemo/CMakeLists.txt b/examples/ExceptionDemo/CMakeLists.txt new file mode 100644 index 00000000..ea818faf --- /dev/null +++ b/examples/ExceptionDemo/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS jit mcjit nativecodegen) +set(LLVM_REQUIRES_EH 1) + +add_llvm_example(ExceptionDemo + ExceptionDemo.cpp + ) + +set_target_properties(ExceptionDemo PROPERTIES ENABLE_EXPORTS 1) diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp new file mode 100644 index 00000000..d6954e83 --- /dev/null +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -0,0 +1,2038 @@ +//===-- ExceptionDemo.cpp - An example using llvm Exceptions --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Demo program which implements an example LLVM exception implementation, and +// shows several test cases including the handling of foreign exceptions. +// It is run with type info types arguments to throw. A test will +// be run for each given type info type. While type info types with the value +// of -1 will trigger a foreign C++ exception to be thrown; type info types +// <= 6 and >= 1 will cause the associated generated exceptions to be thrown +// and caught by generated test functions; and type info types > 6 +// will result in exceptions which pass through to the test harness. All other +// type info types are not supported and could cause a crash. In all cases, +// the "finally" blocks of every generated test functions will executed +// regardless of whether or not that test function ignores or catches the +// thrown exception. +// +// examples: +// +// ExceptionDemo +// +// causes a usage to be printed to stderr +// +// ExceptionDemo 2 3 7 -1 +// +// results in the following cases: +// - Value 2 causes an exception with a type info type of 2 to be +// thrown and caught by an inner generated test function. +// - Value 3 causes an exception with a type info type of 3 to be +// thrown and caught by an outer generated test function. +// - Value 7 causes an exception with a type info type of 7 to be +// thrown and NOT be caught by any generated function. +// - Value -1 causes a foreign C++ exception to be thrown and not be +// caught by any generated function +// +// Cases -1 and 7 are caught by a C++ test harness where the validity of +// of a C++ catch(...) clause catching a generated exception with a +// type info type of 7 is explained by: example in rules 1.6.4 in +// http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22) +// +// This code uses code from the llvm compiler-rt project and the llvm +// Kaleidoscope project. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Scalar.h" + +// FIXME: Although all systems tested with (Linux, OS X), do not need this +// header file included. A user on ubuntu reported, undefined symbols +// for stderr, and fprintf, and the addition of this include fixed the +// issue for them. Given that LLVM's best practices include the goal +// of reducing the number of redundant header files included, the +// correct solution would be to find out why these symbols are not +// defined for the system in question, and fix the issue by finding out +// which LLVM header file, if any, would include these symbols. +#include + +#include +#include + + +#ifndef USE_GLOBAL_STR_CONSTS +#define USE_GLOBAL_STR_CONSTS true +#endif + +// System C++ ABI unwind types from: +// http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22) + +extern "C" { + + typedef enum { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 + } _Unwind_Reason_Code; + + typedef enum { + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + _UA_END_OF_STACK = 16 + } _Unwind_Action; + + struct _Unwind_Exception; + + typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + struct _Unwind_Exception *); + + struct _Unwind_Exception { + uint64_t exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + + uintptr_t private_1; + uintptr_t private_2; + + // @@@ The IA-64 ABI says that this structure must be double-word aligned. + // Taking that literally does not make much sense generically. Instead + // we provide the maximum alignment required by any type for the machine. + } __attribute__((__aligned__)); + + struct _Unwind_Context; + typedef struct _Unwind_Context *_Unwind_Context_t; + + extern const uint8_t *_Unwind_GetLanguageSpecificData (_Unwind_Context_t c); + extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i); + extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n); + extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value); + extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context); + extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context); + +} // extern "C" + +// +// Example types +// + +/// This is our simplistic type info +struct OurExceptionType_t { + /// type info type + int type; +}; + + +/// This is our Exception class which relies on a negative offset to calculate +/// pointers to its instances from pointers to its unwindException member. +/// +/// Note: The above unwind.h defines struct _Unwind_Exception to be aligned +/// on a double word boundary. This is necessary to match the standard: +/// http://mentorembedded.github.com/cxx-abi/abi-eh.html +struct OurBaseException_t { + struct OurExceptionType_t type; + + // Note: This is properly aligned in unwind.h + struct _Unwind_Exception unwindException; +}; + + +// Note: Not needed since we are C++ +typedef struct OurBaseException_t OurException; +typedef struct _Unwind_Exception OurUnwindException; + +// +// Various globals used to support typeinfo and generatted exceptions in +// general +// + +static std::map namedValues; + +int64_t ourBaseFromUnwindOffset; + +const unsigned char ourBaseExcpClassChars[] = +{'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'}; + + +static uint64_t ourBaseExceptionClass = 0; + +static std::vector ourTypeInfoNames; +static std::map ourTypeInfoNamesIndex; + +static llvm::StructType *ourTypeInfoType; +static llvm::StructType *ourCaughtResultType; +static llvm::StructType *ourExceptionType; +static llvm::StructType *ourUnwindExceptionType; + +static llvm::ConstantInt *ourExceptionNotThrownState; +static llvm::ConstantInt *ourExceptionThrownState; +static llvm::ConstantInt *ourExceptionCaughtState; + +typedef std::vector ArgNames; +typedef std::vector ArgTypes; + +// +// Code Generation Utilities +// + +/// Utility used to create a function, both declarations and definitions +/// @param module for module instance +/// @param retType function return type +/// @param theArgTypes function's ordered argument types +/// @param theArgNames function's ordered arguments needed if use of this +/// function corresponds to a function definition. Use empty +/// aggregate for function declarations. +/// @param functName function name +/// @param linkage function linkage +/// @param declarationOnly for function declarations +/// @param isVarArg function uses vararg arguments +/// @returns function instance +llvm::Function *createFunction(llvm::Module &module, + llvm::Type *retType, + const ArgTypes &theArgTypes, + const ArgNames &theArgNames, + const std::string &functName, + llvm::GlobalValue::LinkageTypes linkage, + bool declarationOnly, + bool isVarArg) { + llvm::FunctionType *functType = + llvm::FunctionType::get(retType, theArgTypes, isVarArg); + llvm::Function *ret = + llvm::Function::Create(functType, linkage, functName, &module); + if (!ret || declarationOnly) + return(ret); + + namedValues.clear(); + unsigned i = 0; + for (llvm::Function::arg_iterator argIndex = ret->arg_begin(); + i != theArgNames.size(); + ++argIndex, ++i) { + + argIndex->setName(theArgNames[i]); + namedValues[theArgNames[i]] = argIndex; + } + + return(ret); +} + + +/// Create an alloca instruction in the entry block of +/// the parent function. This is used for mutable variables etc. +/// @param function parent instance +/// @param varName stack variable name +/// @param type stack variable type +/// @param initWith optional constant initialization value +/// @returns AllocaInst instance +static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function, + const std::string &varName, + llvm::Type *type, + llvm::Constant *initWith = 0) { + llvm::BasicBlock &block = function.getEntryBlock(); + llvm::IRBuilder<> tmp(&block, block.begin()); + llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str()); + + if (initWith) + tmp.CreateStore(initWith, ret); + + return(ret); +} + + +// +// Code Generation Utilities End +// + +// +// Runtime C Library functions +// + +// Note: using an extern "C" block so that static functions can be used +extern "C" { + +// Note: Better ways to decide on bit width +// +/// Prints a 32 bit number, according to the format, to stderr. +/// @param intToPrint integer to print +/// @param format printf like format to use when printing +void print32Int(int intToPrint, const char *format) { + if (format) { + // Note: No NULL check + fprintf(stderr, format, intToPrint); + } + else { + // Note: No NULL check + fprintf(stderr, "::print32Int(...):NULL arg.\n"); + } +} + + +// Note: Better ways to decide on bit width +// +/// Prints a 64 bit number, according to the format, to stderr. +/// @param intToPrint integer to print +/// @param format printf like format to use when printing +void print64Int(long int intToPrint, const char *format) { + if (format) { + // Note: No NULL check + fprintf(stderr, format, intToPrint); + } + else { + // Note: No NULL check + fprintf(stderr, "::print64Int(...):NULL arg.\n"); + } +} + + +/// Prints a C string to stderr +/// @param toPrint string to print +void printStr(char *toPrint) { + if (toPrint) { + fprintf(stderr, "%s", toPrint); + } + else { + fprintf(stderr, "::printStr(...):NULL arg.\n"); + } +} + + +/// Deletes the true previosly allocated exception whose address +/// is calculated from the supplied OurBaseException_t::unwindException +/// member address. Handles (ignores), NULL pointers. +/// @param expToDelete exception to delete +void deleteOurException(OurUnwindException *expToDelete) { +#ifdef DEBUG + fprintf(stderr, + "deleteOurException(...).\n"); +#endif + + if (expToDelete && + (expToDelete->exception_class == ourBaseExceptionClass)) { + + free(((char*) expToDelete) + ourBaseFromUnwindOffset); + } +} + + +/// This function is the struct _Unwind_Exception API mandated delete function +/// used by foreign exception handlers when deleting our exception +/// (OurException), instances. +/// @param reason See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html +/// @unlink +/// @param expToDelete exception instance to delete +void deleteFromUnwindOurException(_Unwind_Reason_Code reason, + OurUnwindException *expToDelete) { +#ifdef DEBUG + fprintf(stderr, + "deleteFromUnwindOurException(...).\n"); +#endif + + deleteOurException(expToDelete); +} + + +/// Creates (allocates on the heap), an exception (OurException instance), +/// of the supplied type info type. +/// @param type type info type +OurUnwindException *createOurException(int type) { + size_t size = sizeof(OurException); + OurException *ret = (OurException*) memset(malloc(size), 0, size); + (ret->type).type = type; + (ret->unwindException).exception_class = ourBaseExceptionClass; + (ret->unwindException).exception_cleanup = deleteFromUnwindOurException; + + return(&(ret->unwindException)); +} + + +/// Read a uleb128 encoded value and advance pointer +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// @param data reference variable holding memory pointer to decode from +/// @returns decoded value +static uintptr_t readULEB128(const uint8_t **data) { + uintptr_t result = 0; + uintptr_t shift = 0; + unsigned char byte; + const uint8_t *p = *data; + + do { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *data = p; + + return result; +} + + +/// Read a sleb128 encoded value and advance pointer +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// @param data reference variable holding memory pointer to decode from +/// @returns decoded value +static uintptr_t readSLEB128(const uint8_t **data) { + uintptr_t result = 0; + uintptr_t shift = 0; + unsigned char byte; + const uint8_t *p = *data; + + do { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *data = p; + + if ((byte & 0x40) && (shift < (sizeof(result) << 3))) { + result |= (~0 << shift); + } + + return result; +} + +unsigned getEncodingSize(uint8_t Encoding) { + if (Encoding == llvm::dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x0F) { + case llvm::dwarf::DW_EH_PE_absptr: + return sizeof(uintptr_t); + case llvm::dwarf::DW_EH_PE_udata2: + return sizeof(uint16_t); + case llvm::dwarf::DW_EH_PE_udata4: + return sizeof(uint32_t); + case llvm::dwarf::DW_EH_PE_udata8: + return sizeof(uint64_t); + case llvm::dwarf::DW_EH_PE_sdata2: + return sizeof(int16_t); + case llvm::dwarf::DW_EH_PE_sdata4: + return sizeof(int32_t); + case llvm::dwarf::DW_EH_PE_sdata8: + return sizeof(int64_t); + default: + // not supported + abort(); + } +} + +/// Read a pointer encoded value and advance pointer +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// @param data reference variable holding memory pointer to decode from +/// @param encoding dwarf encoding type +/// @returns decoded value +static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { + uintptr_t result = 0; + const uint8_t *p = *data; + + if (encoding == llvm::dwarf::DW_EH_PE_omit) + return(result); + + // first get value + switch (encoding & 0x0F) { + case llvm::dwarf::DW_EH_PE_absptr: + result = *((uintptr_t*)p); + p += sizeof(uintptr_t); + break; + case llvm::dwarf::DW_EH_PE_uleb128: + result = readULEB128(&p); + break; + // Note: This case has not been tested + case llvm::dwarf::DW_EH_PE_sleb128: + result = readSLEB128(&p); + break; + case llvm::dwarf::DW_EH_PE_udata2: + result = *((uint16_t*)p); + p += sizeof(uint16_t); + break; + case llvm::dwarf::DW_EH_PE_udata4: + result = *((uint32_t*)p); + p += sizeof(uint32_t); + break; + case llvm::dwarf::DW_EH_PE_udata8: + result = *((uint64_t*)p); + p += sizeof(uint64_t); + break; + case llvm::dwarf::DW_EH_PE_sdata2: + result = *((int16_t*)p); + p += sizeof(int16_t); + break; + case llvm::dwarf::DW_EH_PE_sdata4: + result = *((int32_t*)p); + p += sizeof(int32_t); + break; + case llvm::dwarf::DW_EH_PE_sdata8: + result = *((int64_t*)p); + p += sizeof(int64_t); + break; + default: + // not supported + abort(); + break; + } + + // then add relative offset + switch (encoding & 0x70) { + case llvm::dwarf::DW_EH_PE_absptr: + // do nothing + break; + case llvm::dwarf::DW_EH_PE_pcrel: + result += (uintptr_t)(*data); + break; + case llvm::dwarf::DW_EH_PE_textrel: + case llvm::dwarf::DW_EH_PE_datarel: + case llvm::dwarf::DW_EH_PE_funcrel: + case llvm::dwarf::DW_EH_PE_aligned: + default: + // not supported + abort(); + break; + } + + // then apply indirection + if (encoding & llvm::dwarf::DW_EH_PE_indirect) { + result = *((uintptr_t*)result); + } + + *data = p; + + return result; +} + + +/// Deals with Dwarf actions matching our type infos +/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted +/// action matches the supplied exception type. If such a match succeeds, +/// the resultAction argument will be set with > 0 index value. Only +/// corresponding llvm.eh.selector type info arguments, cleanup arguments +/// are supported. Filters are not supported. +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// Also see @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink +/// @param resultAction reference variable which will be set with result +/// @param classInfo our array of type info pointers (to globals) +/// @param actionEntry index into above type info array or 0 (clean up). +/// We do not support filters. +/// @param exceptionClass exception class (_Unwind_Exception::exception_class) +/// of thrown exception. +/// @param exceptionObject thrown _Unwind_Exception instance. +/// @returns whether or not a type info was found. False is returned if only +/// a cleanup was found +static bool handleActionValue(int64_t *resultAction, + uint8_t TTypeEncoding, + const uint8_t *ClassInfo, + uintptr_t actionEntry, + uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject) { + bool ret = false; + + if (!resultAction || + !exceptionObject || + (exceptionClass != ourBaseExceptionClass)) + return(ret); + + struct OurBaseException_t *excp = (struct OurBaseException_t*) + (((char*) exceptionObject) + ourBaseFromUnwindOffset); + struct OurExceptionType_t *excpType = &(excp->type); + int type = excpType->type; + +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...): exceptionObject = <%p>, " + "excp = <%p>.\n", + exceptionObject, + excp); +#endif + + const uint8_t *actionPos = (uint8_t*) actionEntry, + *tempActionPos; + int64_t typeOffset = 0, + actionOffset; + + for (int i = 0; true; ++i) { + // Each emitted dwarf action corresponds to a 2 tuple of + // type info address offset, and action offset to the next + // emitted action. + typeOffset = readSLEB128(&actionPos); + tempActionPos = actionPos; + actionOffset = readSLEB128(&tempActionPos); + +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...):typeOffset: <%lld>, " + "actionOffset: <%lld>.\n", + typeOffset, + actionOffset); +#endif + assert((typeOffset >= 0) && + "handleActionValue(...):filters are not supported."); + + // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector + // argument has been matched. + if (typeOffset > 0) { +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...):actionValue <%d> found.\n", + i); +#endif + unsigned EncSize = getEncodingSize(TTypeEncoding); + const uint8_t *EntryP = ClassInfo - typeOffset * EncSize; + uintptr_t P = readEncodedPointer(&EntryP, TTypeEncoding); + struct OurExceptionType_t *ThisClassInfo = + reinterpret_cast(P); + if (ThisClassInfo->type == type) { + *resultAction = i + 1; + ret = true; + break; + } + } + +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...):actionValue not found.\n"); +#endif + if (!actionOffset) + break; + + actionPos += actionOffset; + } + + return(ret); +} + + +/// Deals with the Language specific data portion of the emitted dwarf code. +/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink +/// @param version unsupported (ignored), unwind version +/// @param lsda language specific data area +/// @param _Unwind_Action actions minimally supported unwind stage +/// (forced specifically not supported) +/// @param exceptionClass exception class (_Unwind_Exception::exception_class) +/// of thrown exception. +/// @param exceptionObject thrown _Unwind_Exception instance. +/// @param context unwind system context +/// @returns minimally supported unwinding control indicator +static _Unwind_Reason_Code handleLsda(int version, + const uint8_t *lsda, + _Unwind_Action actions, + uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, + _Unwind_Context_t context) { + _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND; + + if (!lsda) + return(ret); + +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...):lsda is non-zero.\n"); +#endif + + // Get the current instruction pointer and offset it before next + // instruction in the current frame which threw the exception. + uintptr_t pc = _Unwind_GetIP(context)-1; + + // Get beginning current frame's code (as defined by the + // emitted dwarf code) + uintptr_t funcStart = _Unwind_GetRegionStart(context); + uintptr_t pcOffset = pc - funcStart; + const uint8_t *ClassInfo = NULL; + + // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding + // dwarf emission + + // Parse LSDA header. + uint8_t lpStartEncoding = *lsda++; + + if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) { + readEncodedPointer(&lsda, lpStartEncoding); + } + + uint8_t ttypeEncoding = *lsda++; + uintptr_t classInfoOffset; + + if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) { + // Calculate type info locations in emitted dwarf code which + // were flagged by type info arguments to llvm.eh.selector + // intrinsic + classInfoOffset = readULEB128(&lsda); + ClassInfo = lsda + classInfoOffset; + } + + // Walk call-site table looking for range that + // includes current PC. + + uint8_t callSiteEncoding = *lsda++; + uint32_t callSiteTableLength = readULEB128(&lsda); + const uint8_t *callSiteTableStart = lsda; + const uint8_t *callSiteTableEnd = callSiteTableStart + + callSiteTableLength; + const uint8_t *actionTableStart = callSiteTableEnd; + const uint8_t *callSitePtr = callSiteTableStart; + + while (callSitePtr < callSiteTableEnd) { + uintptr_t start = readEncodedPointer(&callSitePtr, + callSiteEncoding); + uintptr_t length = readEncodedPointer(&callSitePtr, + callSiteEncoding); + uintptr_t landingPad = readEncodedPointer(&callSitePtr, + callSiteEncoding); + + // Note: Action value + uintptr_t actionEntry = readULEB128(&callSitePtr); + + if (exceptionClass != ourBaseExceptionClass) { + // We have been notified of a foreign exception being thrown, + // and we therefore need to execute cleanup landing pads + actionEntry = 0; + } + + if (landingPad == 0) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): No landing pad found.\n"); +#endif + + continue; // no landing pad for this entry + } + + if (actionEntry) { + actionEntry += ((uintptr_t) actionTableStart) - 1; + } + else { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...):No action table found.\n"); +#endif + } + + bool exceptionMatched = false; + + if ((start <= pcOffset) && (pcOffset < (start + length))) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): Landing pad found.\n"); +#endif + int64_t actionValue = 0; + + if (actionEntry) { + exceptionMatched = handleActionValue(&actionValue, + ttypeEncoding, + ClassInfo, + actionEntry, + exceptionClass, + exceptionObject); + } + + if (!(actions & _UA_SEARCH_PHASE)) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): installed landing pad " + "context.\n"); +#endif + + // Found landing pad for the PC. + // Set Instruction Pointer to so we re-enter function + // at landing pad. The landing pad is created by the + // compiler to take two parameters in registers. + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(0), + (uintptr_t)exceptionObject); + + // Note: this virtual register directly corresponds + // to the return of the llvm.eh.selector intrinsic + if (!actionEntry || !exceptionMatched) { + // We indicate cleanup only + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(1), + 0); + } + else { + // Matched type info index of llvm.eh.selector intrinsic + // passed here. + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(1), + actionValue); + } + + // To execute landing pad set here + _Unwind_SetIP(context, funcStart + landingPad); + ret = _URC_INSTALL_CONTEXT; + } + else if (exceptionMatched) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): setting handler found.\n"); +#endif + ret = _URC_HANDLER_FOUND; + } + else { + // Note: Only non-clean up handlers are marked as + // found. Otherwise the clean up handlers will be + // re-found and executed during the clean up + // phase. +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): cleanup handler found.\n"); +#endif + } + + break; + } + } + + return(ret); +} + + +/// This is the personality function which is embedded (dwarf emitted), in the +/// dwarf unwind info block. Again see: JITDwarfEmitter.cpp. +/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink +/// @param version unsupported (ignored), unwind version +/// @param _Unwind_Action actions minimally supported unwind stage +/// (forced specifically not supported) +/// @param exceptionClass exception class (_Unwind_Exception::exception_class) +/// of thrown exception. +/// @param exceptionObject thrown _Unwind_Exception instance. +/// @param context unwind system context +/// @returns minimally supported unwinding control indicator +_Unwind_Reason_Code ourPersonality(int version, + _Unwind_Action actions, + uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, + _Unwind_Context_t context) { +#ifdef DEBUG + fprintf(stderr, + "We are in ourPersonality(...):actions is <%d>.\n", + actions); + + if (actions & _UA_SEARCH_PHASE) { + fprintf(stderr, "ourPersonality(...):In search phase.\n"); + } + else { + fprintf(stderr, "ourPersonality(...):In non-search phase.\n"); + } +#endif + + const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context); + +#ifdef DEBUG + fprintf(stderr, + "ourPersonality(...):lsda = <%p>.\n", + lsda); +#endif + + // The real work of the personality function is captured here + return(handleLsda(version, + lsda, + actions, + exceptionClass, + exceptionObject, + context)); +} + + +/// Generates our _Unwind_Exception class from a given character array. +/// thereby handling arbitrary lengths (not in standard), and handling +/// embedded \0s. +/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink +/// @param classChars char array to encode. NULL values not checkedf +/// @param classCharsSize number of chars in classChars. Value is not checked. +/// @returns class value +uint64_t genClass(const unsigned char classChars[], size_t classCharsSize) +{ + uint64_t ret = classChars[0]; + + for (unsigned i = 1; i < classCharsSize; ++i) { + ret <<= 8; + ret += classChars[i]; + } + + return(ret); +} + +} // extern "C" + +// +// Runtime C Library functions End +// + +// +// Code generation functions +// + +/// Generates code to print given constant string +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param toPrint string to print +/// @param useGlobal A value of true (default) indicates a GlobalValue is +/// generated, and is used to hold the constant string. A value of +/// false indicates that the constant string will be stored on the +/// stack. +void generateStringPrint(llvm::LLVMContext &context, + llvm::Module &module, + llvm::IRBuilder<> &builder, + std::string toPrint, + bool useGlobal = true) { + llvm::Function *printFunct = module.getFunction("printStr"); + + llvm::Value *stringVar; + llvm::Constant *stringConstant = + llvm::ConstantDataArray::getString(context, toPrint); + + if (useGlobal) { + // Note: Does not work without allocation + stringVar = + new llvm::GlobalVariable(module, + stringConstant->getType(), + true, + llvm::GlobalValue::LinkerPrivateLinkage, + stringConstant, + ""); + } + else { + stringVar = builder.CreateAlloca(stringConstant->getType()); + builder.CreateStore(stringConstant, stringVar); + } + + llvm::Value *cast = builder.CreatePointerCast(stringVar, + builder.getInt8PtrTy()); + builder.CreateCall(printFunct, cast); +} + + +/// Generates code to print given runtime integer according to constant +/// string format, and a given print function. +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param printFunct function used to "print" integer +/// @param toPrint string to print +/// @param format printf like formating string for print +/// @param useGlobal A value of true (default) indicates a GlobalValue is +/// generated, and is used to hold the constant string. A value of +/// false indicates that the constant string will be stored on the +/// stack. +void generateIntegerPrint(llvm::LLVMContext &context, + llvm::Module &module, + llvm::IRBuilder<> &builder, + llvm::Function &printFunct, + llvm::Value &toPrint, + std::string format, + bool useGlobal = true) { + llvm::Constant *stringConstant = + llvm::ConstantDataArray::getString(context, format); + llvm::Value *stringVar; + + if (useGlobal) { + // Note: Does not seem to work without allocation + stringVar = + new llvm::GlobalVariable(module, + stringConstant->getType(), + true, + llvm::GlobalValue::LinkerPrivateLinkage, + stringConstant, + ""); + } + else { + stringVar = builder.CreateAlloca(stringConstant->getType()); + builder.CreateStore(stringConstant, stringVar); + } + + llvm::Value *cast = builder.CreateBitCast(stringVar, + builder.getInt8PtrTy()); + builder.CreateCall2(&printFunct, &toPrint, cast); +} + + +/// Generates code to handle finally block type semantics: always runs +/// regardless of whether a thrown exception is passing through or the +/// parent function is simply exiting. In addition to printing some state +/// to stderr, this code will resume the exception handling--runs the +/// unwind resume block, if the exception has not been previously caught +/// by a catch clause, and will otherwise execute the end block (terminator +/// block). In addition this function creates the corresponding function's +/// stack storage for the exception pointer and catch flag status. +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param toAddTo parent function to add block to +/// @param blockName block name of new "finally" block. +/// @param functionId output id used for printing +/// @param terminatorBlock terminator "end" block +/// @param unwindResumeBlock unwind resume block +/// @param exceptionCaughtFlag reference exception caught/thrown status storage +/// @param exceptionStorage reference to exception pointer storage +/// @param caughtResultStorage reference to landingpad result storage +/// @returns newly created block +static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, + llvm::Module &module, + llvm::IRBuilder<> &builder, + llvm::Function &toAddTo, + std::string &blockName, + std::string &functionId, + llvm::BasicBlock &terminatorBlock, + llvm::BasicBlock &unwindResumeBlock, + llvm::Value **exceptionCaughtFlag, + llvm::Value **exceptionStorage, + llvm::Value **caughtResultStorage) { + assert(exceptionCaughtFlag && + "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag " + "is NULL"); + assert(exceptionStorage && + "ExceptionDemo::createFinallyBlock(...):exceptionStorage " + "is NULL"); + assert(caughtResultStorage && + "ExceptionDemo::createFinallyBlock(...):caughtResultStorage " + "is NULL"); + + *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo, + "exceptionCaught", + ourExceptionNotThrownState->getType(), + ourExceptionNotThrownState); + + llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy(); + *exceptionStorage = createEntryBlockAlloca(toAddTo, + "exceptionStorage", + exceptionStorageType, + llvm::ConstantPointerNull::get( + exceptionStorageType)); + *caughtResultStorage = createEntryBlockAlloca(toAddTo, + "caughtResultStorage", + ourCaughtResultType, + llvm::ConstantAggregateZero::get( + ourCaughtResultType)); + + llvm::BasicBlock *ret = llvm::BasicBlock::Create(context, + blockName, + &toAddTo); + + builder.SetInsertPoint(ret); + + std::ostringstream bufferToPrint; + bufferToPrint << "Gen: Executing finally block " + << blockName << " in " << functionId << "\n"; + generateStringPrint(context, + module, + builder, + bufferToPrint.str(), + USE_GLOBAL_STR_CONSTS); + + llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad( + *exceptionCaughtFlag), + &terminatorBlock, + 2); + theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock); + theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock); + + return(ret); +} + + +/// Generates catch block semantics which print a string to indicate type of +/// catch executed, sets an exception caught flag, and executes passed in +/// end block (terminator block). +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param toAddTo parent function to add block to +/// @param blockName block name of new "catch" block. +/// @param functionId output id used for printing +/// @param terminatorBlock terminator "end" block +/// @param exceptionCaughtFlag exception caught/thrown status +/// @returns newly created block +static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context, + llvm::Module &module, + llvm::IRBuilder<> &builder, + llvm::Function &toAddTo, + std::string &blockName, + std::string &functionId, + llvm::BasicBlock &terminatorBlock, + llvm::Value &exceptionCaughtFlag) { + + llvm::BasicBlock *ret = llvm::BasicBlock::Create(context, + blockName, + &toAddTo); + + builder.SetInsertPoint(ret); + + std::ostringstream bufferToPrint; + bufferToPrint << "Gen: Executing catch block " + << blockName + << " in " + << functionId + << std::endl; + generateStringPrint(context, + module, + builder, + bufferToPrint.str(), + USE_GLOBAL_STR_CONSTS); + builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag); + builder.CreateBr(&terminatorBlock); + + return(ret); +} + + +/// Generates a function which invokes a function (toInvoke) and, whose +/// unwind block will "catch" the type info types correspondingly held in the +/// exceptionTypesToCatch argument. If the toInvoke function throws an +/// exception which does not match any type info types contained in +/// exceptionTypesToCatch, the generated code will call _Unwind_Resume +/// with the raised exception. On the other hand the generated code will +/// normally exit if the toInvoke function does not throw an exception. +/// The generated "finally" block is always run regardless of the cause of +/// the generated function exit. +/// The generated function is returned after being verified. +/// @param module code for module instance +/// @param builder builder instance +/// @param fpm a function pass manager holding optional IR to IR +/// transformations +/// @param toInvoke inner function to invoke +/// @param ourId id used to printing purposes +/// @param numExceptionsToCatch length of exceptionTypesToCatch array +/// @param exceptionTypesToCatch array of type info types to "catch" +/// @returns generated function +static +llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, + llvm::IRBuilder<> &builder, + llvm::FunctionPassManager &fpm, + llvm::Function &toInvoke, + std::string ourId, + unsigned numExceptionsToCatch, + unsigned exceptionTypesToCatch[]) { + + llvm::LLVMContext &context = module.getContext(); + llvm::Function *toPrint32Int = module.getFunction("print32Int"); + + ArgTypes argTypes; + argTypes.push_back(builder.getInt32Ty()); + + ArgNames argNames; + argNames.push_back("exceptTypeToThrow"); + + llvm::Function *ret = createFunction(module, + builder.getVoidTy(), + argTypes, + argNames, + ourId, + llvm::Function::ExternalLinkage, + false, + false); + + // Block which calls invoke + llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, + "entry", + ret); + // Normal block for invoke + llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context, + "normal", + ret); + // Unwind block for invoke + llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context, + "exception", + ret); + + // Block which routes exception to correct catch handler block + llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context, + "exceptionRoute", + ret); + + // Foreign exception handler + llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context, + "externalException", + ret); + + // Block which calls _Unwind_Resume + llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context, + "unwindResume", + ret); + + // Clean up block which delete exception if needed + llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret); + + std::string nextName; + std::vector catchBlocks(numExceptionsToCatch); + llvm::Value *exceptionCaughtFlag = NULL; + llvm::Value *exceptionStorage = NULL; + llvm::Value *caughtResultStorage = NULL; + + // Finally block which will branch to unwindResumeBlock if + // exception is not caught. Initializes/allocates stack locations. + llvm::BasicBlock *finallyBlock = createFinallyBlock(context, + module, + builder, + *ret, + nextName = "finally", + ourId, + *endBlock, + *unwindResumeBlock, + &exceptionCaughtFlag, + &exceptionStorage, + &caughtResultStorage + ); + + for (unsigned i = 0; i < numExceptionsToCatch; ++i) { + nextName = ourTypeInfoNames[exceptionTypesToCatch[i]]; + + // One catch block per type info to be caught + catchBlocks[i] = createCatchBlock(context, + module, + builder, + *ret, + nextName, + ourId, + *finallyBlock, + *exceptionCaughtFlag); + } + + // Entry Block + + builder.SetInsertPoint(entryBlock); + + std::vector args; + args.push_back(namedValues["exceptTypeToThrow"]); + builder.CreateInvoke(&toInvoke, + normalBlock, + exceptionBlock, + args); + + // End Block + + builder.SetInsertPoint(endBlock); + + generateStringPrint(context, + module, + builder, + "Gen: In end block: exiting in " + ourId + ".\n", + USE_GLOBAL_STR_CONSTS); + llvm::Function *deleteOurException = module.getFunction("deleteOurException"); + + // Note: function handles NULL exceptions + builder.CreateCall(deleteOurException, + builder.CreateLoad(exceptionStorage)); + builder.CreateRetVoid(); + + // Normal Block + + builder.SetInsertPoint(normalBlock); + + generateStringPrint(context, + module, + builder, + "Gen: No exception in " + ourId + "!\n", + USE_GLOBAL_STR_CONSTS); + + // Finally block is always called + builder.CreateBr(finallyBlock); + + // Unwind Resume Block + + builder.SetInsertPoint(unwindResumeBlock); + + builder.CreateResume(builder.CreateLoad(caughtResultStorage)); + + // Exception Block + + builder.SetInsertPoint(exceptionBlock); + + llvm::Function *personality = module.getFunction("ourPersonality"); + + llvm::LandingPadInst *caughtResult = + builder.CreateLandingPad(ourCaughtResultType, + personality, + numExceptionsToCatch, + "landingPad"); + + caughtResult->setCleanup(true); + + for (unsigned i = 0; i < numExceptionsToCatch; ++i) { + // Set up type infos to be caught + caughtResult->addClause(module.getGlobalVariable( + ourTypeInfoNames[exceptionTypesToCatch[i]])); + } + + llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0); + llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1); + + // FIXME: Redundant storage which, beyond utilizing value of + // caughtResultStore for unwindException storage, may be alleviated + // altogether with a block rearrangement + builder.CreateStore(caughtResult, caughtResultStorage); + builder.CreateStore(unwindException, exceptionStorage); + builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag); + + // Retrieve exception_class member from thrown exception + // (_Unwind_Exception instance). This member tells us whether or not + // the exception is foreign. + llvm::Value *unwindExceptionClass = + builder.CreateLoad(builder.CreateStructGEP( + builder.CreatePointerCast(unwindException, + ourUnwindExceptionType->getPointerTo()), + 0)); + + // Branch to the externalExceptionBlock if the exception is foreign or + // to a catch router if not. Either way the finally block will be run. + builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass, + llvm::ConstantInt::get(builder.getInt64Ty(), + ourBaseExceptionClass)), + exceptionRouteBlock, + externalExceptionBlock); + + // External Exception Block + + builder.SetInsertPoint(externalExceptionBlock); + + generateStringPrint(context, + module, + builder, + "Gen: Foreign exception received.\n", + USE_GLOBAL_STR_CONSTS); + + // Branch to the finally block + builder.CreateBr(finallyBlock); + + // Exception Route Block + + builder.SetInsertPoint(exceptionRouteBlock); + + // Casts exception pointer (_Unwind_Exception instance) to parent + // (OurException instance). + // + // Note: ourBaseFromUnwindOffset is usually negative + llvm::Value *typeInfoThrown = builder.CreatePointerCast( + builder.CreateConstGEP1_64(unwindException, + ourBaseFromUnwindOffset), + ourExceptionType->getPointerTo()); + + // Retrieve thrown exception type info type + // + // Note: Index is not relative to pointer but instead to structure + // unlike a true getelementptr (GEP) instruction + typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0); + + llvm::Value *typeInfoThrownType = + builder.CreateStructGEP(typeInfoThrown, 0); + + generateIntegerPrint(context, + module, + builder, + *toPrint32Int, + *(builder.CreateLoad(typeInfoThrownType)), + "Gen: Exception type <%d> received (stack unwound) " + " in " + + ourId + + ".\n", + USE_GLOBAL_STR_CONSTS); + + // Route to matched type info catch block or run cleanup finally block + llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex, + finallyBlock, + numExceptionsToCatch); + + unsigned nextTypeToCatch; + + for (unsigned i = 1; i <= numExceptionsToCatch; ++i) { + nextTypeToCatch = i - 1; + switchToCatchBlock->addCase(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(context), i), + catchBlocks[nextTypeToCatch]); + } + + llvm::verifyFunction(*ret); + fpm.run(*ret); + + return(ret); +} + + +/// Generates function which throws either an exception matched to a runtime +/// determined type info type (argument to generated function), or if this +/// runtime value matches nativeThrowType, throws a foreign exception by +/// calling nativeThrowFunct. +/// @param module code for module instance +/// @param builder builder instance +/// @param fpm a function pass manager holding optional IR to IR +/// transformations +/// @param ourId id used to printing purposes +/// @param nativeThrowType a runtime argument of this value results in +/// nativeThrowFunct being called to generate/throw exception. +/// @param nativeThrowFunct function which will throw a foreign exception +/// if the above nativeThrowType matches generated function's arg. +/// @returns generated function +static +llvm::Function *createThrowExceptionFunction(llvm::Module &module, + llvm::IRBuilder<> &builder, + llvm::FunctionPassManager &fpm, + std::string ourId, + int32_t nativeThrowType, + llvm::Function &nativeThrowFunct) { + llvm::LLVMContext &context = module.getContext(); + namedValues.clear(); + ArgTypes unwindArgTypes; + unwindArgTypes.push_back(builder.getInt32Ty()); + ArgNames unwindArgNames; + unwindArgNames.push_back("exceptTypeToThrow"); + + llvm::Function *ret = createFunction(module, + builder.getVoidTy(), + unwindArgTypes, + unwindArgNames, + ourId, + llvm::Function::ExternalLinkage, + false, + false); + + // Throws either one of our exception or a native C++ exception depending + // on a runtime argument value containing a type info type. + llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, + "entry", + ret); + // Throws a foreign exception + llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context, + "nativeThrow", + ret); + // Throws one of our Exceptions + llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context, + "generatedThrow", + ret); + // Retrieved runtime type info type to throw + llvm::Value *exceptionType = namedValues["exceptTypeToThrow"]; + + // nativeThrowBlock block + + builder.SetInsertPoint(nativeThrowBlock); + + // Throws foreign exception + builder.CreateCall(&nativeThrowFunct, exceptionType); + builder.CreateUnreachable(); + + // entry block + + builder.SetInsertPoint(entryBlock); + + llvm::Function *toPrint32Int = module.getFunction("print32Int"); + generateIntegerPrint(context, + module, + builder, + *toPrint32Int, + *exceptionType, + "\nGen: About to throw exception type <%d> in " + + ourId + + ".\n", + USE_GLOBAL_STR_CONSTS); + + // Switches on runtime type info type value to determine whether or not + // a foreign exception is thrown. Defaults to throwing one of our + // generated exceptions. + llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType, + generatedThrowBlock, + 1); + + theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + nativeThrowType), + nativeThrowBlock); + + // generatedThrow block + + builder.SetInsertPoint(generatedThrowBlock); + + llvm::Function *createOurException = module.getFunction("createOurException"); + llvm::Function *raiseOurException = module.getFunction( + "_Unwind_RaiseException"); + + // Creates exception to throw with runtime type info type. + llvm::Value *exception = builder.CreateCall(createOurException, + namedValues["exceptTypeToThrow"]); + + // Throw generated Exception + builder.CreateCall(raiseOurException, exception); + builder.CreateUnreachable(); + + llvm::verifyFunction(*ret); + fpm.run(*ret); + + return(ret); +} + +static void createStandardUtilityFunctions(unsigned numTypeInfos, + llvm::Module &module, + llvm::IRBuilder<> &builder); + +/// Creates test code by generating and organizing these functions into the +/// test case. The test case consists of an outer function setup to invoke +/// an inner function within an environment having multiple catch and single +/// finally blocks. This inner function is also setup to invoke a throw +/// function within an evironment similar in nature to the outer function's +/// catch and finally blocks. Each of these two functions catch mutually +/// exclusive subsets (even or odd) of the type info types configured +/// for this this. All generated functions have a runtime argument which +/// holds a type info type to throw that each function takes and passes it +/// to the inner one if such a inner function exists. This type info type is +/// looked at by the generated throw function to see whether or not it should +/// throw a generated exception with the same type info type, or instead call +/// a supplied a function which in turn will throw a foreign exception. +/// @param module code for module instance +/// @param builder builder instance +/// @param fpm a function pass manager holding optional IR to IR +/// transformations +/// @param nativeThrowFunctName name of external function which will throw +/// a foreign exception +/// @returns outermost generated test function. +llvm::Function *createUnwindExceptionTest(llvm::Module &module, + llvm::IRBuilder<> &builder, + llvm::FunctionPassManager &fpm, + std::string nativeThrowFunctName) { + // Number of type infos to generate + unsigned numTypeInfos = 6; + + // Initialze intrisics and external functions to use along with exception + // and type info globals. + createStandardUtilityFunctions(numTypeInfos, + module, + builder); + llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName); + + // Create exception throw function using the value ~0 to cause + // foreign exceptions to be thrown. + llvm::Function *throwFunct = createThrowExceptionFunction(module, + builder, + fpm, + "throwFunct", + ~0, + *nativeThrowFunct); + // Inner function will catch even type infos + unsigned innerExceptionTypesToCatch[] = {6, 2, 4}; + size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) / + sizeof(unsigned); + + // Generate inner function. + llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module, + builder, + fpm, + *throwFunct, + "innerCatchFunct", + numExceptionTypesToCatch, + innerExceptionTypesToCatch); + + // Outer function will catch odd type infos + unsigned outerExceptionTypesToCatch[] = {3, 1, 5}; + numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) / + sizeof(unsigned); + + // Generate outer function + llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module, + builder, + fpm, + *innerCatchFunct, + "outerCatchFunct", + numExceptionTypesToCatch, + outerExceptionTypesToCatch); + + // Return outer function to run + return(outerCatchFunct); +} + +namespace { +/// Represents our foreign exceptions +class OurCppRunException : public std::runtime_error { +public: + OurCppRunException(const std::string reason) : + std::runtime_error(reason) {} + + OurCppRunException (const OurCppRunException &toCopy) : + std::runtime_error(toCopy) {} + + OurCppRunException &operator = (const OurCppRunException &toCopy) { + return(reinterpret_cast( + std::runtime_error::operator=(toCopy))); + } + + virtual ~OurCppRunException (void) throw () {} +}; +} // end anonymous namespace + +/// Throws foreign C++ exception. +/// @param ignoreIt unused parameter that allows function to match implied +/// generated function contract. +extern "C" +void throwCppException (int32_t ignoreIt) { + throw(OurCppRunException("thrown by throwCppException(...)")); +} + +typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); + +/// This is a test harness which runs test by executing generated +/// function with a type info type to throw. Harness wraps the execution +/// of generated function in a C++ try catch clause. +/// @param engine execution engine to use for executing generated function. +/// This demo program expects this to be a JIT instance for demo +/// purposes. +/// @param function generated test function to run +/// @param typeToThrow type info type of generated exception to throw, or +/// indicator to cause foreign exception to be thrown. +static +void runExceptionThrow(llvm::ExecutionEngine *engine, + llvm::Function *function, + int32_t typeToThrow) { + + // Find test's function pointer + OurExceptionThrowFunctType functPtr = + reinterpret_cast( + reinterpret_cast(engine->getPointerToFunction(function))); + + try { + // Run test + (*functPtr)(typeToThrow); + } + catch (OurCppRunException exc) { + // Catch foreign C++ exception + fprintf(stderr, + "\nrunExceptionThrow(...):In C++ catch OurCppRunException " + "with reason: %s.\n", + exc.what()); + } + catch (...) { + // Catch all exceptions including our generated ones. This latter + // functionality works according to the example in rules 1.6.4 of + // http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22), + // given that these will be exceptions foreign to C++ + // (the _Unwind_Exception::exception_class should be different from + // the one used by C++). + fprintf(stderr, + "\nrunExceptionThrow(...):In C++ catch all.\n"); + } +} + +// +// End test functions +// + +typedef llvm::ArrayRef TypeArray; + +/// This initialization routine creates type info globals and +/// adds external function declarations to module. +/// @param numTypeInfos number of linear type info associated type info types +/// to create as GlobalVariable instances, starting with the value 1. +/// @param module code for module instance +/// @param builder builder instance +static void createStandardUtilityFunctions(unsigned numTypeInfos, + llvm::Module &module, + llvm::IRBuilder<> &builder) { + + llvm::LLVMContext &context = module.getContext(); + + // Exception initializations + + // Setup exception catch state + ourExceptionNotThrownState = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0), + ourExceptionThrownState = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1), + ourExceptionCaughtState = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2), + + + + // Create our type info type + ourTypeInfoType = llvm::StructType::get(context, + TypeArray(builder.getInt32Ty())); + + llvm::Type *caughtResultFieldTypes[] = { + builder.getInt8PtrTy(), + builder.getInt32Ty() + }; + + // Create our landingpad result type + ourCaughtResultType = llvm::StructType::get(context, + TypeArray(caughtResultFieldTypes)); + + // Create OurException type + ourExceptionType = llvm::StructType::get(context, + TypeArray(ourTypeInfoType)); + + // Create portion of _Unwind_Exception type + // + // Note: Declaring only a portion of the _Unwind_Exception struct. + // Does this cause problems? + ourUnwindExceptionType = + llvm::StructType::get(context, + TypeArray(builder.getInt64Ty())); + + struct OurBaseException_t dummyException; + + // Calculate offset of OurException::unwindException member. + ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) - + ((uintptr_t) &(dummyException.unwindException)); + +#ifdef DEBUG + fprintf(stderr, + "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset " + "= %lld, sizeof(struct OurBaseException_t) - " + "sizeof(struct _Unwind_Exception) = %lu.\n", + ourBaseFromUnwindOffset, + sizeof(struct OurBaseException_t) - + sizeof(struct _Unwind_Exception)); +#endif + + size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char); + + // Create our _Unwind_Exception::exception_class value + ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars); + + // Type infos + + std::string baseStr = "typeInfo", typeInfoName; + std::ostringstream typeInfoNameBuilder; + std::vector structVals; + + llvm::Constant *nextStruct; + + // Generate each type info + // + // Note: First type info is not used. + for (unsigned i = 0; i <= numTypeInfos; ++i) { + structVals.clear(); + structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i)); + nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals); + + typeInfoNameBuilder.str(""); + typeInfoNameBuilder << baseStr << i; + typeInfoName = typeInfoNameBuilder.str(); + + // Note: Does not seem to work without allocation + new llvm::GlobalVariable(module, + ourTypeInfoType, + true, + llvm::GlobalValue::ExternalLinkage, + nextStruct, + typeInfoName); + + ourTypeInfoNames.push_back(typeInfoName); + ourTypeInfoNamesIndex[i] = typeInfoName; + } + + ArgNames argNames; + ArgTypes argTypes; + llvm::Function *funct = NULL; + + // print32Int + + llvm::Type *retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + argTypes.push_back(builder.getInt8PtrTy()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "print32Int", + llvm::Function::ExternalLinkage, + true, + false); + + // print64Int + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt64Ty()); + argTypes.push_back(builder.getInt8PtrTy()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "print64Int", + llvm::Function::ExternalLinkage, + true, + false); + + // printStr + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8PtrTy()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "printStr", + llvm::Function::ExternalLinkage, + true, + false); + + // throwCppException + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "throwCppException", + llvm::Function::ExternalLinkage, + true, + false); + + // deleteOurException + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8PtrTy()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "deleteOurException", + llvm::Function::ExternalLinkage, + true, + false); + + // createOurException + + retType = builder.getInt8PtrTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "createOurException", + llvm::Function::ExternalLinkage, + true, + false); + + // _Unwind_RaiseException + + retType = builder.getInt32Ty(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8PtrTy()); + + argNames.clear(); + + funct = createFunction(module, + retType, + argTypes, + argNames, + "_Unwind_RaiseException", + llvm::Function::ExternalLinkage, + true, + false); + + funct->setDoesNotReturn(); + + // _Unwind_Resume + + retType = builder.getInt32Ty(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8PtrTy()); + + argNames.clear(); + + funct = createFunction(module, + retType, + argTypes, + argNames, + "_Unwind_Resume", + llvm::Function::ExternalLinkage, + true, + false); + + funct->setDoesNotReturn(); + + // ourPersonality + + retType = builder.getInt32Ty(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + argTypes.push_back(builder.getInt32Ty()); + argTypes.push_back(builder.getInt64Ty()); + argTypes.push_back(builder.getInt8PtrTy()); + argTypes.push_back(builder.getInt8PtrTy()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "ourPersonality", + llvm::Function::ExternalLinkage, + true, + false); + + // llvm.eh.typeid.for intrinsic + + getDeclaration(&module, llvm::Intrinsic::eh_typeid_for); +} + + +//===----------------------------------------------------------------------===// +// Main test driver code. +//===----------------------------------------------------------------------===// + +/// Demo main routine which takes the type info types to throw. A test will +/// be run for each given type info type. While type info types with the value +/// of -1 will trigger a foreign C++ exception to be thrown; type info types +/// <= 6 and >= 1 will be caught by test functions; and type info types > 6 +/// will result in exceptions which pass through to the test harness. All other +/// type info types are not supported and could cause a crash. +int main(int argc, char *argv[]) { + if (argc == 1) { + fprintf(stderr, + "\nUsage: ExceptionDemo " + "[...].\n" + " Each type must have the value of 1 - 6 for " + "generated exceptions to be caught;\n" + " the value -1 for foreign C++ exceptions to be " + "generated and thrown;\n" + " or the values > 6 for exceptions to be ignored.\n" + "\nTry: ExceptionDemo 2 3 7 -1\n" + " for a full test.\n\n"); + return(0); + } + + // If not set, exception handling will not be turned on + llvm::TargetOptions Opts; + + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); + llvm::LLVMContext &context = llvm::getGlobalContext(); + llvm::IRBuilder<> theBuilder(context); + + // Make the module, which holds all the code. + llvm::Module *module = new llvm::Module("my cool jit", context); + + llvm::RTDyldMemoryManager *MemMgr = new llvm::SectionMemoryManager(); + + // Build engine with JIT + llvm::EngineBuilder factory(module); + factory.setEngineKind(llvm::EngineKind::JIT); + factory.setAllocateGVsWithCode(false); + factory.setTargetOptions(Opts); + factory.setMCJITMemoryManager(MemMgr); + factory.setUseMCJIT(true); + llvm::ExecutionEngine *executionEngine = factory.create(); + + { + llvm::FunctionPassManager fpm(module); + + // Set up the optimizer pipeline. + // Start with registering info about how the + // target lays out data structures. + fpm.add(new llvm::DataLayout(*executionEngine->getDataLayout())); + + // Optimizations turned on +#ifdef ADD_OPT_PASSES + + // Basic AliasAnslysis support for GVN. + fpm.add(llvm::createBasicAliasAnalysisPass()); + + // Promote allocas to registers. + fpm.add(llvm::createPromoteMemoryToRegisterPass()); + + // Do simple "peephole" optimizations and bit-twiddling optzns. + fpm.add(llvm::createInstructionCombiningPass()); + + // Reassociate expressions. + fpm.add(llvm::createReassociatePass()); + + // Eliminate Common SubExpressions. + fpm.add(llvm::createGVNPass()); + + // Simplify the control flow graph (deleting unreachable + // blocks, etc). + fpm.add(llvm::createCFGSimplificationPass()); +#endif // ADD_OPT_PASSES + + fpm.doInitialization(); + + // Generate test code using function throwCppException(...) as + // the function which throws foreign exceptions. + llvm::Function *toRun = + createUnwindExceptionTest(*module, + theBuilder, + fpm, + "throwCppException"); + + executionEngine->finalizeObject(); + + fprintf(stderr, "\nBegin module dump:\n\n"); + + module->dump(); + + fprintf(stderr, "\nEnd module dump:\n"); + + fprintf(stderr, "\n\nBegin Test:\n"); + + for (int i = 1; i < argc; ++i) { + // Run test for each argument whose value is the exception + // type to throw. + runExceptionThrow(executionEngine, + toRun, + (unsigned) strtoul(argv[i], NULL, 10)); + } + + fprintf(stderr, "\nEnd Test:\n\n"); + } + + delete executionEngine; + + return 0; +} diff --git a/examples/ExceptionDemo/Makefile b/examples/ExceptionDemo/Makefile new file mode 100644 index 00000000..58d9def0 --- /dev/null +++ b/examples/ExceptionDemo/Makefile @@ -0,0 +1,16 @@ +##===- examples/ExceptionDemo/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===---------------------------------------------------------------------===## +LEVEL = ../.. +TOOLNAME = ExceptionDemo +EXAMPLE_TOOL = 1 +REQUIRES_EH = 1 + +LINK_COMPONENTS := jit mcjit nativecodegen + +include $(LEVEL)/Makefile.common diff --git a/examples/Fibonacci/CMakeLists.txt b/examples/Fibonacci/CMakeLists.txt new file mode 100644 index 00000000..69376124 --- /dev/null +++ b/examples/Fibonacci/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS jit interpreter nativecodegen) + +add_llvm_example(Fibonacci + fibonacci.cpp + ) diff --git a/examples/Fibonacci/Makefile b/examples/Fibonacci/Makefile new file mode 100644 index 00000000..71f6ba0e --- /dev/null +++ b/examples/Fibonacci/Makefile @@ -0,0 +1,17 @@ +##===- examples/Fibonacci/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = Fibonacci +EXAMPLE_TOOL = 1 + +# Link in JIT support +LINK_COMPONENTS := jit interpreter nativecodegen + +include $(LEVEL)/Makefile.common diff --git a/examples/Fibonacci/fibonacci.cpp b/examples/Fibonacci/fibonacci.cpp new file mode 100644 index 00000000..8cbf7d15 --- /dev/null +++ b/examples/Fibonacci/fibonacci.cpp @@ -0,0 +1,137 @@ +//===--- examples/Fibonacci/fibonacci.cpp - An example use of the JIT -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This small program provides an example of how to build quickly a small module +// with function Fibonacci and execute it with the JIT. +// +// The goal of this snippet is to create in the memory the LLVM module +// consisting of one function as follow: +// +// int fib(int x) { +// if(x<=2) return 1; +// return fib(x-1)+fib(x-2); +// } +// +// Once we have this, we compile the module via JIT, then execute the `fib' +// function and return result to a driver, i.e. to a "host program". +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static Function *CreateFibFunction(Module *M, LLVMContext &Context) { + // Create the fib function and insert it into module M. This function is said + // to return an int and take an int parameter. + Function *FibF = + cast(M->getOrInsertFunction("fib", Type::getInt32Ty(Context), + Type::getInt32Ty(Context), + (Type *)0)); + + // Add a basic block to the function. + BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF); + + // Get pointers to the constants. + Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1); + Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2); + + // Get pointer to the integer argument of the add1 function... + Argument *ArgX = FibF->arg_begin(); // Get the arg. + ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. + + // Create the true_block. + BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF); + // Create an exit block. + BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF); + + // Create the "if (arg <= 2) goto exitbb" + Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond"); + BranchInst::Create(RetBB, RecurseBB, CondInst, BB); + + // Create: ret int 1 + ReturnInst::Create(Context, One, RetBB); + + // create fib(x-1) + Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB); + CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB); + CallFibX1->setTailCall(); + + // create fib(x-2) + Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB); + CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB); + CallFibX2->setTailCall(); + + + // fib(x-1)+fib(x-2) + Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2, + "addresult", RecurseBB); + + // Create the return instruction and add it to the basic block + ReturnInst::Create(Context, Sum, RecurseBB); + + return FibF; +} + + +int main(int argc, char **argv) { + int n = argc > 1 ? atol(argv[1]) : 24; + + InitializeNativeTarget(); + LLVMContext Context; + + // Create some module to put our function into it. + OwningPtr M(new Module("test", Context)); + + // We are about to create the "fib" function: + Function *FibF = CreateFibFunction(M.get(), Context); + + // Now we going to create JIT + std::string errStr; + ExecutionEngine *EE = + EngineBuilder(M.get()) + .setErrorStr(&errStr) + .setEngineKind(EngineKind::JIT) + .create(); + + if (!EE) { + errs() << argv[0] << ": Failed to construct ExecutionEngine: " << errStr + << "\n"; + return 1; + } + + errs() << "verifying... "; + if (verifyModule(*M)) { + errs() << argv[0] << ": Error constructing function!\n"; + return 1; + } + + errs() << "OK\n"; + errs() << "We just constructed this LLVM module:\n\n---------\n" << *M; + errs() << "---------\nstarting fibonacci(" << n << ") with JIT...\n"; + + // Call the Fibonacci function with argument n: + std::vector Args(1); + Args[0].IntVal = APInt(32, n); + GenericValue GV = EE->runFunction(FibF, Args); + + // import result of execution + outs() << "Result: " << GV.IntVal << "\n"; + + return 0; +} diff --git a/examples/HowToUseJIT/CMakeLists.txt b/examples/HowToUseJIT/CMakeLists.txt new file mode 100644 index 00000000..428b53ff --- /dev/null +++ b/examples/HowToUseJIT/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS jit interpreter nativecodegen) + +add_llvm_example(HowToUseJIT + HowToUseJIT.cpp + ) diff --git a/examples/HowToUseJIT/HowToUseJIT.cpp b/examples/HowToUseJIT/HowToUseJIT.cpp new file mode 100644 index 00000000..7125a156 --- /dev/null +++ b/examples/HowToUseJIT/HowToUseJIT.cpp @@ -0,0 +1,133 @@ +//===-- examples/HowToUseJIT/HowToUseJIT.cpp - An example use of the JIT --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This small program provides an example of how to quickly build a small +// module with two functions and execute it with the JIT. +// +// Goal: +// The goal of this snippet is to create in the memory +// the LLVM module consisting of two functions as follow: +// +// int add1(int x) { +// return x+1; +// } +// +// int foo() { +// return add1(10); +// } +// +// then compile the module via JIT, then execute the `foo' +// function and return result to a driver, i.e. to a "host program". +// +// Some remarks and questions: +// +// - could we invoke some code using noname functions too? +// e.g. evaluate "foo()+foo()" without fears to introduce +// conflict of temporary function name with some real +// existing function name? +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +int main() { + + InitializeNativeTarget(); + + LLVMContext Context; + + // Create some module to put our function into it. + Module *M = new Module("test", Context); + + // Create the add1 function entry and insert this entry into module M. The + // function will have a return type of "int" and take an argument of "int". + // The '0' terminates the list of argument types. + Function *Add1F = + cast(M->getOrInsertFunction("add1", Type::getInt32Ty(Context), + Type::getInt32Ty(Context), + (Type *)0)); + + // Add a basic block to the function. As before, it automatically inserts + // because of the last argument. + BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", Add1F); + + // Create a basic block builder with default parameters. The builder will + // automatically append instructions to the basic block `BB'. + IRBuilder<> builder(BB); + + // Get pointers to the constant `1'. + Value *One = builder.getInt32(1); + + // Get pointers to the integer argument of the add1 function... + assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg + Argument *ArgX = Add1F->arg_begin(); // Get the arg + ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. + + // Create the add instruction, inserting it into the end of BB. + Value *Add = builder.CreateAdd(One, ArgX); + + // Create the return instruction and add it to the basic block + builder.CreateRet(Add); + + // Now, function add1 is ready. + + + // Now we're going to create function `foo', which returns an int and takes no + // arguments. + Function *FooF = + cast(M->getOrInsertFunction("foo", Type::getInt32Ty(Context), + (Type *)0)); + + // Add a basic block to the FooF function. + BB = BasicBlock::Create(Context, "EntryBlock", FooF); + + // Tell the basic block builder to attach itself to the new basic block + builder.SetInsertPoint(BB); + + // Get pointer to the constant `10'. + Value *Ten = builder.getInt32(10); + + // Pass Ten to the call to Add1F + CallInst *Add1CallRes = builder.CreateCall(Add1F, Ten); + Add1CallRes->setTailCall(true); + + // Create the return instruction and add it to the basic block. + builder.CreateRet(Add1CallRes); + + // Now we create the JIT. + ExecutionEngine* EE = EngineBuilder(M).create(); + + outs() << "We just constructed this LLVM module:\n\n" << *M; + outs() << "\n\nRunning foo: "; + outs().flush(); + + // Call the `foo' function with no arguments: + std::vector noargs; + GenericValue gv = EE->runFunction(FooF, noargs); + + // Import result of execution: + outs() << "Result: " << gv.IntVal << "\n"; + EE->freeMachineCodeForFunction(FooF); + delete EE; + llvm_shutdown(); + return 0; +} diff --git a/examples/HowToUseJIT/Makefile b/examples/HowToUseJIT/Makefile new file mode 100644 index 00000000..c8919db9 --- /dev/null +++ b/examples/HowToUseJIT/Makefile @@ -0,0 +1,15 @@ +##===- examples/HowToUseJIT/Makefile -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. +TOOLNAME = HowToUseJIT +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := jit interpreter nativecodegen + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/CMakeLists.txt b/examples/Kaleidoscope/CMakeLists.txt new file mode 100644 index 00000000..8c87ac50 --- /dev/null +++ b/examples/Kaleidoscope/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(Chapter2) +add_subdirectory(Chapter3) +add_subdirectory(Chapter4) +add_subdirectory(Chapter5) +add_subdirectory(Chapter6) +add_subdirectory(Chapter7) diff --git a/examples/Kaleidoscope/Chapter2/CMakeLists.txt b/examples/Kaleidoscope/Chapter2/CMakeLists.txt new file mode 100644 index 00000000..79f2b172 --- /dev/null +++ b/examples/Kaleidoscope/Chapter2/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_example(Kaleidoscope-Ch2 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter2/Makefile b/examples/Kaleidoscope/Chapter2/Makefile new file mode 100644 index 00000000..1a9b94ce --- /dev/null +++ b/examples/Kaleidoscope/Chapter2/Makefile @@ -0,0 +1,13 @@ +##===- examples/Kaleidoscope/Chapter2/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch2 +EXAMPLE_TOOL = 1 + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter2/toy.cpp b/examples/Kaleidoscope/Chapter2/toy.cpp new file mode 100644 index 00000000..cd901394 --- /dev/null +++ b/examples/Kaleidoscope/Chapter2/toy.cpp @@ -0,0 +1,391 @@ +#include +#include +#include +#include +#include +#include + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { +public: + NumberExprAST(double val) {} +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) {} +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) {} +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (ParseDefinition()) { + fprintf(stderr, "Parsed a function definition.\n"); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (ParseExtern()) { + fprintf(stderr, "Parsed an extern\n"); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (ParseTopLevelExpr()) { + fprintf(stderr, "Parsed a top-level expr\n"); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} diff --git a/examples/Kaleidoscope/Chapter3/CMakeLists.txt b/examples/Kaleidoscope/Chapter3/CMakeLists.txt new file mode 100644 index 00000000..1af8db00 --- /dev/null +++ b/examples/Kaleidoscope/Chapter3/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core) + +add_llvm_example(Kaleidoscope-Ch3 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter3/Makefile b/examples/Kaleidoscope/Chapter3/Makefile new file mode 100644 index 00000000..4cc6948d --- /dev/null +++ b/examples/Kaleidoscope/Chapter3/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter3/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch3 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter3/toy.cpp b/examples/Kaleidoscope/Chapter3/toy.cpp new file mode 100644 index 00000000..a7b60ba3 --- /dev/null +++ b/examples/Kaleidoscope/Chapter3/toy.cpp @@ -0,0 +1,565 @@ +#include "llvm/Analysis/Verifier.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: return ErrorV("invalid binary operator"); + } +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read top-level expression:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/Chapter4/CMakeLists.txt b/examples/Kaleidoscope/Chapter4/CMakeLists.txt new file mode 100644 index 00000000..0d1ac533 --- /dev/null +++ b/examples/Kaleidoscope/Chapter4/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) + +add_llvm_example(Kaleidoscope-Ch4 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter4/Makefile b/examples/Kaleidoscope/Chapter4/Makefile new file mode 100644 index 00000000..30162d94 --- /dev/null +++ b/examples/Kaleidoscope/Chapter4/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter4/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch4 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp new file mode 100644 index 00000000..27c3f4f2 --- /dev/null +++ b/examples/Kaleidoscope/Chapter4/toy.cpp @@ -0,0 +1,615 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: return ErrorV("invalid binary operator"); + } +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/Chapter5/CMakeLists.txt b/examples/Kaleidoscope/Chapter5/CMakeLists.txt new file mode 100644 index 00000000..2d75ad35 --- /dev/null +++ b/examples/Kaleidoscope/Chapter5/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) + +add_llvm_example(Kaleidoscope-Ch5 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter5/Makefile b/examples/Kaleidoscope/Chapter5/Makefile new file mode 100644 index 00000000..d1f5e203 --- /dev/null +++ b/examples/Kaleidoscope/Chapter5/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter5/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch5 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp new file mode 100644 index 00000000..fe4cdfe7 --- /dev/null +++ b/examples/Kaleidoscope/Chapter5/toy.cpp @@ -0,0 +1,860 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: return ErrorV("invalid binary operator"); + } +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // ... + // start = startexpr + // goto loop + // loop: + // variable = phi [start, loopheader], [nextvariable, loopend] + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // nextvariable = variable + step + // endcond = endexpr + // br endcond, loop, endloop + // outloop: + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Make the new basic block for the loop header, inserting after current + // block. + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + BasicBlock *PreheaderBB = Builder.GetInsertBlock(); + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Start the PHI node with an entry for Start. + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); + Variable->addIncoming(StartVal, PreheaderBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + Value *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Variable; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *LoopEndBB = Builder.GetInsertBlock(); + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Add a new entry to the PHI node for the backedge. + Variable->addIncoming(NextVar, LoopEndBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/Chapter6/CMakeLists.txt b/examples/Kaleidoscope/Chapter6/CMakeLists.txt new file mode 100644 index 00000000..2e15a5f7 --- /dev/null +++ b/examples/Kaleidoscope/Chapter6/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) + +add_llvm_example(Kaleidoscope-Ch6 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter6/Makefile b/examples/Kaleidoscope/Chapter6/Makefile new file mode 100644 index 00000000..a5fbcbdf --- /dev/null +++ b/examples/Kaleidoscope/Chapter6/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter6/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch6 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp new file mode 100644 index 00000000..b7b347db --- /dev/null +++ b/examples/Kaleidoscope/Chapter6/toy.cpp @@ -0,0 +1,978 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // ... + // start = startexpr + // goto loop + // loop: + // variable = phi [start, loopheader], [nextvariable, loopend] + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // nextvariable = variable + step + // endcond = endexpr + // br endcond, loop, endloop + // outloop: + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Make the new basic block for the loop header, inserting after current + // block. + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + BasicBlock *PreheaderBB = Builder.GetInsertBlock(); + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Start the PHI node with an entry for Start. + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); + Variable->addIncoming(StartVal, PreheaderBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + Value *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Variable; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *LoopEndBB = Builder.GetInsertBlock(); + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Add a new entry to the PHI node for the backedge. + Variable->addIncoming(NextVar, LoopEndBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/Chapter7/CMakeLists.txt b/examples/Kaleidoscope/Chapter7/CMakeLists.txt new file mode 100644 index 00000000..da383984 --- /dev/null +++ b/examples/Kaleidoscope/Chapter7/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) +set(LLVM_REQUIRES_RTTI 1) + +add_llvm_example(Kaleidoscope-Ch7 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter7/Makefile b/examples/Kaleidoscope/Chapter7/Makefile new file mode 100644 index 00000000..6cec323e --- /dev/null +++ b/examples/Kaleidoscope/Chapter7/Makefile @@ -0,0 +1,16 @@ +##===- examples/Kaleidoscope/Chapter7/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch7 +EXAMPLE_TOOL = 1 +REQUIRES_RTTI := 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp new file mode 100644 index 00000000..5c66f5c8 --- /dev/null +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -0,0 +1,1144 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) return ErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = dynamic_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/README.txt b/examples/Kaleidoscope/MCJIT/README.txt new file mode 100644 index 00000000..ba742645 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/README.txt @@ -0,0 +1,12 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany a series of blog posts +that describe the process of porting the Kaleidoscope tutorial to use the MCJIT +execution engine instead of the older JIT engine. + +When the blog posts are ready this file will be updated with links to the posts. + +These directories contain Makefiles that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/cached/Makefile b/examples/Kaleidoscope/MCJIT/cached/Makefile new file mode 100644 index 00000000..dde39a75 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/Makefile @@ -0,0 +1,11 @@ +all: toy-mcjit toy-jit toy-ir-gen + +toy-mcjit : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native irreader` -o toy-mcjit + +toy-jit : toy-jit.cpp + clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-jit + +# This is a special build for the purpose of converting Kaleidoscope input to an IR file +toy-ir-gen : toy-jit.cpp + clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti -DDUMP_FINAL_MODULE `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-ir-gen diff --git a/examples/Kaleidoscope/MCJIT/cached/README.txt b/examples/Kaleidoscope/MCJIT/cached/README.txt new file mode 100644 index 00000000..6acaf057 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/README.txt @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory demonstrates the third version of the +program, now modified to accept an input IR file on the command line and, +optionally, to use a basic caching mechanism to store generated object images. + +The toy-jit.cpp file contains a version of the original JIT-based source code +that has been modified to support the input IR file command line option. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required. + +This directory also contains a Python script that may be used to generate random +input for the program and test scripts to capture data for rough performance +comparisons. Another Python script will split generated input files into +definitions and function calls for the purpose of testing the IR input and +caching facilities. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/cached/genk-timing.py b/examples/Kaleidoscope/MCJIT/cached/genk-timing.py new file mode 100644 index 00000000..96dd6db5 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/genk-timing.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python + +import sys +import random + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.timeFile = outputname + self.shfile = open(scriptname, 'w') + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls): + """Echo some comments and invoke both versions of toy""" + rootname = filename + if '.' in filename: + rootname = filename[:filename.rfind('.')] + self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-jit < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class KScriptGenerator: + """Used to generate random Kaleidoscope code""" + def __init__(self, filename): + self.kfile = open(filename, 'w') + self.nextFuncNum = 1 + self.lastFuncNum = None + self.callWeighting = 0.1 + # A mapping of calls within functions with no duplicates + self.calledFunctionTable = {} + # A list of function calls which will actually be executed + self.calledFunctions = [] + # A comprehensive mapping of calls within functions + # used for computing the total number of calls + self.comprehensiveCalledFunctionTable = {} + self.totalCallsExecuted = 0 + + def updateTotalCallCount(self, callee): + # Count this call + self.totalCallsExecuted += 1 + # Then count all the functions it calls + if callee in self.comprehensiveCalledFunctionTable: + for child in self.comprehensiveCalledFunctionTable[callee]: + self.updateTotalCallCount(child) + + def updateFunctionCallMap(self, caller, callee): + """Maintains a map of functions that are called from other functions""" + if not caller in self.calledFunctionTable: + self.calledFunctionTable[caller] = [] + if not callee in self.calledFunctionTable[caller]: + self.calledFunctionTable[caller].append(callee) + if not caller in self.comprehensiveCalledFunctionTable: + self.comprehensiveCalledFunctionTable[caller] = [] + self.comprehensiveCalledFunctionTable[caller].append(callee) + + def updateCalledFunctionList(self, callee): + """Maintains a list of functions that will actually be called""" + # Update the total call count + self.updateTotalCallCount(callee) + # If this function is already in the list, don't do anything else + if callee in self.calledFunctions: + return + # Add this function to the list of those that will be called. + self.calledFunctions.append(callee) + # If this function calls other functions, add them too + if callee in self.calledFunctionTable: + for subCallee in self.calledFunctionTable[callee]: + self.updateCalledFunctionList(subCallee) + + def setCallWeighting(self, weight): + """ Sets the probably of generating a function call""" + self.callWeighting = weight + + def writeln(self, line): + self.kfile.write(line + '\n') + + def writeComment(self, comment): + self.writeln('# ' + comment) + + def writeEmptyLine(self): + self.writeln("") + + def writePredefinedFunctions(self): + self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands") + self.writeComment("and just returns the RHS.") + self.writeln("def binary : 1 (x y) y;") + self.writeEmptyLine() + self.writeComment("Helper functions defined within toy") + self.writeln("extern putchard(x);") + self.writeln("extern printd(d);") + self.writeln("extern printlf();") + self.writeEmptyLine() + self.writeComment("Print the result of a function call") + self.writeln("def printresult(N Result)") + self.writeln(" # 'result('") + self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :") + self.writeln(" printd(N) :"); + self.writeln(" # ') = '") + self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :") + self.writeln(" printd(Result) :"); + self.writeln(" printlf();") + self.writeEmptyLine() + + def writeRandomOperation(self, LValue, LHS, RHS): + shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting) + if shouldCallFunc: + funcToCall = random.randrange(1, self.lastFuncNum - 1) + self.updateFunctionCallMap(self.lastFuncNum, funcToCall) + self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS)) + else: + possibleOperations = ["+", "-", "*", "/"] + operation = random.choice(possibleOperations) + if operation == "-": + # Don't let our intermediate value become zero + # This is complicated by the fact that '<' is our only comparison operator + self.writeln(" if %s < %s then" % (LHS, RHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else if %s < %s then" % (RHS, LHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else") + self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100))) + else: + self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS)) + + def getNextFuncNum(self): + result = self.nextFuncNum + self.nextFuncNum += 1 + self.lastFuncNum = result + return result + + def writeFunction(self, elements): + funcNum = self.getNextFuncNum() + self.writeComment("Auto-generated function number %d" % funcNum) + self.writeln("def func%d(X Y)" % funcNum) + self.writeln(" var temp1 = X,") + self.writeln(" temp2 = Y,") + self.writeln(" temp3 in") + # Initialize the variable names to be rotated + first = "temp3" + second = "temp1" + third = "temp2" + # Write some random operations + for i in range(elements): + self.writeRandomOperation(first, second, third) + # Rotate the variables + temp = first + first = second + second = third + third = temp + self.writeln(" " + third + ";") + self.writeEmptyLine() + + def writeFunctionCall(self): + self.writeComment("Call the last function") + arg1 = random.uniform(1, 100) + arg2 = random.uniform(1, 100) + self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2)) + self.writeEmptyLine() + self.updateCalledFunctionList(self.lastFuncNum) + + def writeFinalFunctionCounts(self): + self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum)) + +def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript): + """ Generate a random Kaleidoscope script based on the given parameters """ + print "Generating " + filename + print(" %d functions, %d elements per function, %d functions between execution" % + (numFuncs, elementsPerFunc, funcsBetweenExec)) + print(" Call weighting = %f" % callWeighting) + script = KScriptGenerator(filename) + script.setCallWeighting(callWeighting) + script.writeComment("===========================================================================") + script.writeComment("Auto-generated script") + script.writeComment(" %d functions, %d elements per function, %d functions between execution" + % (numFuncs, elementsPerFunc, funcsBetweenExec)) + script.writeComment(" call weighting = %f" % callWeighting) + script.writeComment("===========================================================================") + script.writeEmptyLine() + script.writePredefinedFunctions() + funcsSinceLastExec = 0 + for i in range(numFuncs): + script.writeFunction(elementsPerFunc) + funcsSinceLastExec += 1 + if funcsSinceLastExec == funcsBetweenExec: + script.writeFunctionCall() + funcsSinceLastExec = 0 + # Always end with a function call + if funcsSinceLastExec > 0: + script.writeFunctionCall() + script.writeEmptyLine() + script.writeFinalFunctionCounts() + funcsCalled = len(script.calledFunctions) + print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted) + timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted) + +# Execution begins here +random.seed() + +timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt") + +dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0), + (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0), + ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)] + +# Generate the code +for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets: + filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100)) + generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/cached/split-lib.py b/examples/Kaleidoscope/MCJIT/cached/split-lib.py new file mode 100644 index 00000000..5cdcc6d4 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/split-lib.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.shfile = open(scriptname, 'w') + self.timeFile = outputname + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, irname, callname): + """Echo some comments and invoke both versions of toy""" + rootname = irname + if '.' in irname: + rootname = irname[:irname.rfind('.')] + self.shfile.write("echo \"%s: Calls %s\" >> %s\n" % (callname, irname, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT again\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-jit -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class LibScriptGenerator: + """Used to generate a bash script which will convert Kaleidoscope files to IR""" + def __init__(self, filename): + self.shfile = open(filename, 'w') + + def writeLibGenCall(self, libname, irname): + self.shfile.write("./toy-ir-gen < %s 2> %s\n" % (libname, irname)) + +def splitScript(inputname, libGenScript, timingScript): + rootname = inputname[:-2] + libname = rootname + "-lib.k" + irname = rootname + "-lib.ir" + callname = rootname + "-call.k" + infile = open(inputname, "r") + libfile = open(libname, "w") + callfile = open(callname, "w") + print "Splitting %s into %s and %s" % (inputname, callname, libname) + for line in infile: + if not line.startswith("#"): + if line.startswith("print"): + callfile.write(line) + else: + libfile.write(line) + libGenScript.writeLibGenCall(libname, irname) + timingScript.writeTimingCall(irname, callname) + +# Execution begins here +libGenScript = LibScriptGenerator("make-libs.sh") +timingScript = TimingScriptGenerator("time-lib.sh", "lib-timing.txt") + +script_list = ["test-5000-3-50-50.k", "test-5000-10-100-10.k", "test-5000-10-5-10.k", "test-5000-10-1-0.k", + "test-1000-3-10-50.k", "test-1000-10-100-10.k", "test-1000-10-5-10.k", "test-1000-10-1-0.k", + "test-200-3-2-50.k", "test-200-10-40-10.k", "test-200-10-2-10.k", "test-200-10-1-0.k"] + +for script in script_list: + splitScript(script, libGenScript, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp new file mode 100644 index 00000000..784781bd --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp @@ -0,0 +1,1208 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Command-line options +//===----------------------------------------------------------------------===// + +namespace { + cl::opt + InputIR("input-IR", + cl::desc("Specify the name of an IR file to load for function definitions"), + cl::value_desc("input IR file name")); +} // namespace + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static FunctionPassManager *TheFPM; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) return ErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; +#ifdef USE_MCJIT + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); +#else + Function *F = TheModule->getFunction(std::string("unary")+Opcode); +#endif + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + // For now, I'm building without RTTI because LLVM builds that way by + // default and so we need to build that way to use the command line supprt. + // If you build LLVM with RTTI this can be changed back to a dynamic_cast. + VariableExprAST *LHSE = reinterpret_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '/': return Builder.CreateFDiv(L, R, "divtmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) { + char error_str[64]; + sprintf(error_str, "Unknown function referenced %s", Callee.c_str()); + return ErrorV(error_str); + } + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Command line input file handlers +//===----------------------------------------------------------------------===// + +Module* parseInputIR(std::string InputFile) { + SMDiagnostic Err; + Module *M = ParseIRFile(InputFile, Err, getGlobalContext()); + if (!M) { + Err.print("IR parsing failed: ", errs()); + return NULL; + } + + return M; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + cl::ParseCommandLineOptions(argc, argv, + "Kaleidoscope example program\n"); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Make the module, which holds all the code. + if (!InputIR.empty()) { + TheModule = parseInputIR(InputIR); + } else { + TheModule = new Module("my cool jit", Context); + } + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + TheFPM = 0; +#if !defined(MINIMAL_STDERR_OUTPUT) || defined(DUMP_FINAL_MODULE) + TheModule->dump(); +#endif + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/cached/toy.cpp b/examples/Kaleidoscope/MCJIT/cached/toy.cpp new file mode 100644 index 00000000..5bc49d7d --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/toy.cpp @@ -0,0 +1,1552 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Command-line options +//===----------------------------------------------------------------------===// + +cl::opt +InputIR("input-IR", + cl::desc("Specify the name of an IR file to load for function definitions"), + cl::value_desc("input IR file name")); + +cl::opt +UseObjectCache("use-object-cache", + cl::desc("Enable use of the MCJIT object caching"), + cl::init(false)); + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT object cache class +//===----------------------------------------------------------------------===// + +class MCJITObjectCache : public ObjectCache { +public: + MCJITObjectCache() { + // Set IR cache directory + sys::fs::current_path(CacheDir); + sys::path::append(CacheDir, "toy_object_cache"); + } + + virtual ~MCJITObjectCache() { + } + + virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128>IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(CacheDir.str()) && sys::fs::create_directory(CacheDir.str())) { + fprintf(stderr, "Unable to create cache directory\n"); + return; + } + std::string ErrStr; + raw_fd_ostream IRObjectFile(IRCacheFile.c_str(), ErrStr, raw_fd_ostream::F_Binary); + IRObjectFile << Obj->getBuffer(); + } + } + + // MCJIT will call this function before compiling any module + // MCJIT takes ownership of both the MemoryBuffer object and the memory + // to which it refers. + virtual MemoryBuffer* getObject(const Module* M) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128> IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(IRCacheFile.str())) { + // This file isn't in our cache + return NULL; + } + OwningPtr IRObjectBuffer; + MemoryBuffer::getFile(IRCacheFile.c_str(), IRObjectBuffer, -1, false); + // MCJIT will want to write into this buffer, and we don't want that + // because the file has probably just been mmapped. Instead we make + // a copy. The filed-based buffer will be released when it goes + // out of scope. + return MemoryBuffer::getMemBufferCopy(IRObjectBuffer->getBuffer()); + } + + return NULL; + } + +private: + SmallString<128> CacheDir; +}; + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), OpenModule(NULL) {} + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + ExecutionEngine *compileModule(Module *M); + void closeCurrentModule(); + void addModule(Module *M); + void dump(); + +private: + typedef std::vector ModuleVector; + + LLVMContext &Context; + Module *OpenModule; + ModuleVector Modules; + std::map EngineMap; + MCJITObjectCache OurObjectCache; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = SectionMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + // Walk the vector of modules. + ModuleVector::iterator it, end; + for (it = Modules.begin(), end = Modules.end(); + it != end; ++it) { + // See if we have an execution engine for this module. + std::map::iterator mapIt = EngineMap.find(*it); + // If we have an EE, the EE owns the module so just delete the EE. + if (mapIt != EngineMap.end()) { + delete mapIt->second; + } else { + // Otherwise, we still own the module. Delete it now. + delete *it; + } + } +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == OpenModule) + return F; + + assert(OpenModule != NULL); + + // This function is in a module that has already been JITed. + // We need to generate a new prototype for external linkage. + Function *PF = OpenModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + OpenModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (OpenModule) + return OpenModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + OpenModule = M; + return M; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // Look for this function in an existing module + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + std::string FnName = F->getName(); + for (it = begin; it != end; ++it) { + Function *MF = (*it)->getFunction(FnName); + if (MF == F) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::closeCurrentModule() { + OpenModule = NULL; +} + +ExecutionEngine *MCJITHelper::compileModule(Module *M) { + if (M == OpenModule) + closeCurrentModule(); + + std::string ErrStr; + ExecutionEngine *NewEngine = EngineBuilder(M) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!NewEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + if (UseObjectCache) + NewEngine->setObjectCache(&OurObjectCache); + + // Get the ModuleID so we can identify IR input files + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, it doesn't need function passes run. + if (0 != ModuleID.compare(0, 3, "IR:")) { + // Create a function pass manager for this engine + FunctionPassManager *FPM = new FunctionPassManager(M); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*NewEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = M->end(); + for (it = M->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + // We don't need this anymore + delete FPM; + } + + // Store this engine + EngineMap[M] = NewEngine; + NewEngine->finalizeObject(); + + return NewEngine; +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the functions in our modules, compiling only as necessary + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(Name); + if (F && !F->empty()) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::addModule(Module* M) { + Modules.push_back(M); +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static MCJITHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + char ErrStr[256]; + sprintf(ErrStr, "Unknown variable name %s", Name.c_str()); + if (V == 0) return ErrorV(ErrStr); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = reinterpret_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '/': return Builder.CreateFDiv(L, R, "divtmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + std::string FnName = MakeLegalFunctionName(Name); + + Module* M = TheHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + TheHelper->closeCurrentModule(); + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheHelper->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Command line input file handler +//===----------------------------------------------------------------------===// + +Module* parseInputIR(std::string InputFile) { + SMDiagnostic Err; + Module *M = ParseIRFile(InputFile, Err, getGlobalContext()); + if (!M) { + Err.print("IR parsing failed: ", errs()); + return NULL; + } + + char ModID[256]; + sprintf(ModID, "IR:%s", InputFile.c_str()); + M->setModuleIdentifier(ModID); + + TheHelper->addModule(M); + return M; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + cl::ParseCommandLineOptions(argc, argv, + "Kaleidoscope example program\n"); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Make the helper, which holds all the code. + TheHelper = new MCJITHelper(Context); + + if (!InputIR.empty()) { + parseInputIR(InputIR); + } + + // Run the main "interpreter loop" now. + MainLoop(); + +#ifndef MINIMAL_STDERR_OUTPUT + // Print out all of the generated code. + TheHelper->dump(); +#endif + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/complete/Makefile b/examples/Kaleidoscope/MCJIT/complete/Makefile new file mode 100644 index 00000000..9e45d17a --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/Makefile @@ -0,0 +1,4 @@ +all: toy + +toy : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit mcjit native irreader` -o toy diff --git a/examples/Kaleidoscope/MCJIT/complete/README.txt b/examples/Kaleidoscope/MCJIT/complete/README.txt new file mode 100644 index 00000000..82bc397a --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/README.txt @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory combines all previous versions, including the +old JIT-based implementation, into a single file for easy comparison with +command line options to select between the various possibilities. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required. + +This directory also contains a Python script that may be used to generate random +input for the program and test scripts to capture data for rough performance +comparisons. Another Python script will split generated input files into +definitions and function calls for the purpose of testing the IR input and +caching facilities. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/complete/genk-timing.py b/examples/Kaleidoscope/MCJIT/complete/genk-timing.py new file mode 100644 index 00000000..72591fe8 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/genk-timing.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python + +import sys +import random + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.timeFile = outputname + self.shfile = open(scriptname, 'w') + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls): + """Echo some comments and invoke both versions of toy""" + rootname = filename + if '.' in filename: + rootname = filename[:filename.rfind('.')] + self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT (original)\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=false < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT (lazy)\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true < %s > %s-mcjit-lazy.out 2> %s-mcjit-lazy.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=false < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class KScriptGenerator: + """Used to generate random Kaleidoscope code""" + def __init__(self, filename): + self.kfile = open(filename, 'w') + self.nextFuncNum = 1 + self.lastFuncNum = None + self.callWeighting = 0.1 + # A mapping of calls within functions with no duplicates + self.calledFunctionTable = {} + # A list of function calls which will actually be executed + self.calledFunctions = [] + # A comprehensive mapping of calls within functions + # used for computing the total number of calls + self.comprehensiveCalledFunctionTable = {} + self.totalCallsExecuted = 0 + + def updateTotalCallCount(self, callee): + # Count this call + self.totalCallsExecuted += 1 + # Then count all the functions it calls + if callee in self.comprehensiveCalledFunctionTable: + for child in self.comprehensiveCalledFunctionTable[callee]: + self.updateTotalCallCount(child) + + def updateFunctionCallMap(self, caller, callee): + """Maintains a map of functions that are called from other functions""" + if not caller in self.calledFunctionTable: + self.calledFunctionTable[caller] = [] + if not callee in self.calledFunctionTable[caller]: + self.calledFunctionTable[caller].append(callee) + if not caller in self.comprehensiveCalledFunctionTable: + self.comprehensiveCalledFunctionTable[caller] = [] + self.comprehensiveCalledFunctionTable[caller].append(callee) + + def updateCalledFunctionList(self, callee): + """Maintains a list of functions that will actually be called""" + # Update the total call count + self.updateTotalCallCount(callee) + # If this function is already in the list, don't do anything else + if callee in self.calledFunctions: + return + # Add this function to the list of those that will be called. + self.calledFunctions.append(callee) + # If this function calls other functions, add them too + if callee in self.calledFunctionTable: + for subCallee in self.calledFunctionTable[callee]: + self.updateCalledFunctionList(subCallee) + + def setCallWeighting(self, weight): + """ Sets the probably of generating a function call""" + self.callWeighting = weight + + def writeln(self, line): + self.kfile.write(line + '\n') + + def writeComment(self, comment): + self.writeln('# ' + comment) + + def writeEmptyLine(self): + self.writeln("") + + def writePredefinedFunctions(self): + self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands") + self.writeComment("and just returns the RHS.") + self.writeln("def binary : 1 (x y) y;") + self.writeEmptyLine() + self.writeComment("Helper functions defined within toy") + self.writeln("extern putchard(x);") + self.writeln("extern printd(d);") + self.writeln("extern printlf();") + self.writeEmptyLine() + self.writeComment("Print the result of a function call") + self.writeln("def printresult(N Result)") + self.writeln(" # 'result('") + self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :") + self.writeln(" printd(N) :"); + self.writeln(" # ') = '") + self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :") + self.writeln(" printd(Result) :"); + self.writeln(" printlf();") + self.writeEmptyLine() + + def writeRandomOperation(self, LValue, LHS, RHS): + shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting) + if shouldCallFunc: + funcToCall = random.randrange(1, self.lastFuncNum - 1) + self.updateFunctionCallMap(self.lastFuncNum, funcToCall) + self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS)) + else: + possibleOperations = ["+", "-", "*", "/"] + operation = random.choice(possibleOperations) + if operation == "-": + # Don't let our intermediate value become zero + # This is complicated by the fact that '<' is our only comparison operator + self.writeln(" if %s < %s then" % (LHS, RHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else if %s < %s then" % (RHS, LHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else") + self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100))) + else: + self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS)) + + def getNextFuncNum(self): + result = self.nextFuncNum + self.nextFuncNum += 1 + self.lastFuncNum = result + return result + + def writeFunction(self, elements): + funcNum = self.getNextFuncNum() + self.writeComment("Auto-generated function number %d" % funcNum) + self.writeln("def func%d(X Y)" % funcNum) + self.writeln(" var temp1 = X,") + self.writeln(" temp2 = Y,") + self.writeln(" temp3 in") + # Initialize the variable names to be rotated + first = "temp3" + second = "temp1" + third = "temp2" + # Write some random operations + for i in range(elements): + self.writeRandomOperation(first, second, third) + # Rotate the variables + temp = first + first = second + second = third + third = temp + self.writeln(" " + third + ";") + self.writeEmptyLine() + + def writeFunctionCall(self): + self.writeComment("Call the last function") + arg1 = random.uniform(1, 100) + arg2 = random.uniform(1, 100) + self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2)) + self.writeEmptyLine() + self.updateCalledFunctionList(self.lastFuncNum) + + def writeFinalFunctionCounts(self): + self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum)) + +def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript): + """ Generate a random Kaleidoscope script based on the given parameters """ + print "Generating " + filename + print(" %d functions, %d elements per function, %d functions between execution" % + (numFuncs, elementsPerFunc, funcsBetweenExec)) + print(" Call weighting = %f" % callWeighting) + script = KScriptGenerator(filename) + script.setCallWeighting(callWeighting) + script.writeComment("===========================================================================") + script.writeComment("Auto-generated script") + script.writeComment(" %d functions, %d elements per function, %d functions between execution" + % (numFuncs, elementsPerFunc, funcsBetweenExec)) + script.writeComment(" call weighting = %f" % callWeighting) + script.writeComment("===========================================================================") + script.writeEmptyLine() + script.writePredefinedFunctions() + funcsSinceLastExec = 0 + for i in range(numFuncs): + script.writeFunction(elementsPerFunc) + funcsSinceLastExec += 1 + if funcsSinceLastExec == funcsBetweenExec: + script.writeFunctionCall() + funcsSinceLastExec = 0 + # Always end with a function call + if funcsSinceLastExec > 0: + script.writeFunctionCall() + script.writeEmptyLine() + script.writeFinalFunctionCounts() + funcsCalled = len(script.calledFunctions) + print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted) + timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted) + +# Execution begins here +random.seed() + +timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt") + +dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0), + (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0), + ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)] + +# Generate the code +for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets: + filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100)) + generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/complete/split-lib.py b/examples/Kaleidoscope/MCJIT/complete/split-lib.py new file mode 100644 index 00000000..f6bec027 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/split-lib.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.shfile = open(scriptname, 'w') + self.timeFile = outputname + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, irname, callname): + """Echo some comments and invoke both versions of toy""" + rootname = irname + if '.' in irname: + rootname = irname[:irname.rfind('.')] + self.shfile.write("echo \"%s: Calls %s\" >> %s\n" % (callname, irname, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT again\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=false -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class LibScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, filename): + self.shfile = open(filename, 'w') + + def writeLibGenCall(self, libname, irname): + self.shfile.write("./toy -suppress-prompts -use-mcjit=false -dump-modules < %s 2> %s\n" % (libname, irname)) + +def splitScript(inputname, libGenScript, timingScript): + rootname = inputname[:-2] + libname = rootname + "-lib.k" + irname = rootname + "-lib.ir" + callname = rootname + "-call.k" + infile = open(inputname, "r") + libfile = open(libname, "w") + callfile = open(callname, "w") + print "Splitting %s into %s and %s" % (inputname, callname, libname) + for line in infile: + if not line.startswith("#"): + if line.startswith("print"): + callfile.write(line) + else: + libfile.write(line) + libGenScript.writeLibGenCall(libname, irname) + timingScript.writeTimingCall(irname, callname) + +# Execution begins here +libGenScript = LibScriptGenerator("make-libs.sh") +timingScript = TimingScriptGenerator("time-lib.sh", "lib-timing.txt") + +script_list = ["test-5000-3-50-50.k", "test-5000-10-100-10.k", "test-5000-10-5-10.k", "test-5000-10-1-0.k", + "test-1000-3-10-50.k", "test-1000-10-100-10.k", "test-1000-10-5-10.k", "test-1000-10-1-0.k", + "test-200-3-2-50.k", "test-200-10-40-10.k", "test-200-10-2-10.k", "test-200-10-1-0.k"] + +for script in script_list: + splitScript(script, libGenScript, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/complete/toy.cpp b/examples/Kaleidoscope/MCJIT/complete/toy.cpp new file mode 100644 index 00000000..1f804d56 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/toy.cpp @@ -0,0 +1,1711 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Command-line options +//===----------------------------------------------------------------------===// + +namespace { + cl::opt + InputIR("input-IR", + cl::desc("Specify the name of an IR file to load for function definitions"), + cl::value_desc("input IR file name")); + + cl::opt + VerboseOutput("verbose", + cl::desc("Enable verbose output (results, IR, etc.) to stderr"), + cl::init(false)); + + cl::opt + SuppressPrompts("suppress-prompts", + cl::desc("Disable printing the 'ready' prompt"), + cl::init(false)); + + cl::opt + DumpModulesOnExit("dump-modules", + cl::desc("Dump IR from modules to stderr on shutdown"), + cl::init(false)); + + cl::opt UseMCJIT( + "use-mcjit", cl::desc("Use the MCJIT execution engine"), + cl::init(true)); + + cl::opt EnableLazyCompilation( + "enable-lazy-compilation", cl::desc("Enable lazy compilation when using the MCJIT engine"), + cl::init(true)); + + cl::opt UseObjectCache( + "use-object-cache", cl::desc("Enable use of the MCJIT object caching"), + cl::init(false)); +} // namespace + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT object cache class +//===----------------------------------------------------------------------===// + +class MCJITObjectCache : public ObjectCache { +public: + MCJITObjectCache() { + // Set IR cache directory + sys::fs::current_path(CacheDir); + sys::path::append(CacheDir, "toy_object_cache"); + } + + virtual ~MCJITObjectCache() { + } + + virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128>IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(CacheDir.str()) && sys::fs::create_directory(CacheDir.str())) { + fprintf(stderr, "Unable to create cache directory\n"); + return; + } + std::string ErrStr; + raw_fd_ostream IRObjectFile(IRCacheFile.c_str(), ErrStr, raw_fd_ostream::F_Binary); + IRObjectFile << Obj->getBuffer(); + } + } + + // MCJIT will call this function before compiling any module + // MCJIT takes ownership of both the MemoryBuffer object and the memory + // to which it refers. + virtual MemoryBuffer* getObject(const Module* M) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128> IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(IRCacheFile.str())) { + // This file isn't in our cache + return NULL; + } + OwningPtr IRObjectBuffer; + MemoryBuffer::getFile(IRCacheFile.c_str(), IRObjectBuffer, -1, false); + // MCJIT will want to write into this buffer, and we don't want that + // because the file has probably just been mmapped. Instead we make + // a copy. The filed-based buffer will be released when it goes + // out of scope. + return MemoryBuffer::getMemBufferCopy(IRObjectBuffer->getBuffer()); + } + + return NULL; + } + +private: + SmallString<128> CacheDir; +}; + +//===----------------------------------------------------------------------===// +// IR input file handler +//===----------------------------------------------------------------------===// + +Module* parseInputIR(std::string InputFile, LLVMContext &Context) { + SMDiagnostic Err; + Module *M = ParseIRFile(InputFile, Err, Context); + if (!M) { + Err.print("IR parsing failed: ", errs()); + return NULL; + } + + char ModID[256]; + sprintf(ModID, "IR:%s", InputFile.c_str()); + M->setModuleIdentifier(ModID); + return M; +} + +//===----------------------------------------------------------------------===// +// Helper class for execution engine abstraction +//===----------------------------------------------------------------------===// + +class BaseHelper +{ +public: + BaseHelper() {} + virtual ~BaseHelper() {} + + virtual Function *getFunction(const std::string FnName) = 0; + virtual Module *getModuleForNewFunction() = 0; + virtual void *getPointerToFunction(Function* F) = 0; + virtual void *getPointerToNamedFunction(const std::string &Name) = 0; + virtual void closeCurrentModule() = 0; + virtual void runFPM(Function &F) = 0; + virtual void dump(); +}; + +//===----------------------------------------------------------------------===// +// Helper class for JIT execution engine +//===----------------------------------------------------------------------===// + +class JITHelper : public BaseHelper { +public: + JITHelper(LLVMContext &Context) { + // Make the module, which holds all the code. + if (!InputIR.empty()) { + TheModule = parseInputIR(InputIR, Context); + } else { + TheModule = new Module("my cool jit", Context); + } + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + TheFPM = new FunctionPassManager(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + TheFPM->add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + TheFPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + TheFPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + TheFPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + TheFPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + TheFPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + TheFPM->add(createCFGSimplificationPass()); + + TheFPM->doInitialization(); + } + + virtual ~JITHelper() { + if (TheFPM) + delete TheFPM; + if (TheExecutionEngine) + delete TheExecutionEngine; + } + + virtual Function *getFunction(const std::string FnName) { + assert(TheModule); + return TheModule->getFunction(FnName); + } + + virtual Module *getModuleForNewFunction() { + assert(TheModule); + return TheModule; + } + + virtual void *getPointerToFunction(Function* F) { + assert(TheExecutionEngine); + return TheExecutionEngine->getPointerToFunction(F); + } + + virtual void *getPointerToNamedFunction(const std::string &Name) { + return TheExecutionEngine->getPointerToNamedFunction(Name); + } + + virtual void runFPM(Function &F) { + assert(TheFPM); + TheFPM->run(F); + } + + virtual void closeCurrentModule() { + // This should never be called for JIT + assert(false); + } + + virtual void dump() { + assert(TheModule); + TheModule->dump(); + } + +private: + Module *TheModule; + ExecutionEngine *TheExecutionEngine; + FunctionPassManager *TheFPM; +}; + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper : public BaseHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), CurrentModule(NULL) { + if (!InputIR.empty()) { + Module *M = parseInputIR(InputIR, Context); + Modules.push_back(M); + if (!EnableLazyCompilation) + compileModule(M); + } + } + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + void closeCurrentModule(); + virtual void runFPM(Function &F) {} // Not needed, see compileModule + void dump(); + +protected: + ExecutionEngine *compileModule(Module *M); + +private: + typedef std::vector ModuleVector; + + MCJITObjectCache OurObjectCache; + + LLVMContext &Context; + ModuleVector Modules; + + std::map EngineMap; + + Module *CurrentModule; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = RTDyldMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + // Walk the vector of modules. + ModuleVector::iterator it, end; + for (it = Modules.begin(), end = Modules.end(); + it != end; ++it) { + // See if we have an execution engine for this module. + std::map::iterator mapIt = EngineMap.find(*it); + // If we have an EE, the EE owns the module so just delete the EE. + if (mapIt != EngineMap.end()) { + delete mapIt->second; + } else { + // Otherwise, we still own the module. Delete it now. + delete *it; + } + } +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == CurrentModule) + return F; + + assert(CurrentModule != NULL); + + // This function is in a module that has already been JITed. + // We just need a prototype for external linkage. + Function *PF = CurrentModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + CurrentModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (CurrentModule) + return CurrentModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + CurrentModule = M; + + return M; +} + +ExecutionEngine *MCJITHelper::compileModule(Module *M) { + assert(EngineMap.find(M) == EngineMap.end()); + + if (M == CurrentModule) + closeCurrentModule(); + + std::string ErrStr; + ExecutionEngine *EE = EngineBuilder(M) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!EE) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + if (UseObjectCache) + EE->setObjectCache(&OurObjectCache); + // Get the ModuleID so we can identify IR input files + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, it doesn't need function passes run. + if (0 != ModuleID.compare(0, 3, "IR:")) { + FunctionPassManager *FPM = 0; + + // Create a FPM for this module + FPM = new FunctionPassManager(M); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*EE->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = M->end(); + for (it = M->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + delete FPM; + } + + EE->finalizeObject(); + + // Store this engine + EngineMap[M] = EE; + + return EE; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // Look for this function in an existing module + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + std::string FnName = F->getName(); + for (it = begin; it != end; ++it) { + Function *MF = (*it)->getFunction(FnName); + if (MF == F) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::closeCurrentModule() { + // If we have an open module (and we should), pack it up + if (CurrentModule) { + CurrentModule = NULL; + } +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the functions in our modules, compiling only as necessary + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(Name); + if (F && !F->empty()) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static BaseHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) return ErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + Function *F; + if (UseMCJIT) + F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); + else + F = TheHelper->getFunction(std::string("unary")+Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = reinterpret_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '/': return Builder.CreateFDiv(L, R, "divtmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F; + if (UseMCJIT) + F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + else + F = TheHelper->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->getFunction(Callee); + if (CalleeF == 0) { + char error_str[64]; + sprintf(error_str, "Unknown function referenced %s", Callee.c_str()); + return ErrorV(error_str); + } + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + std::string FnName; + if (UseMCJIT) + FnName = MakeLegalFunctionName(Name); + else + FnName = Name; + + Module* M = TheHelper->getModuleForNewFunction(); + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // FIXME: Implement duplicate function detection. + // The check below will only work if the duplicate is in the open module. + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->getFunction(FnName); + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + if (!UseMCJIT) + TheHelper->runFPM(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (UseMCJIT && EnableLazyCompilation) + TheHelper->closeCurrentModule(); + Function *LF = F->Codegen(); + if (LF && VerboseOutput) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + Function *F = P->Codegen(); + if (F && VerboseOutput) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheHelper->getPointerToFunction(LF); + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + double Result = FP(); + if (VerboseOutput) + fprintf(stderr, "Evaluated to %f\n", Result); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + if (!SuppressPrompts) + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + if (UseMCJIT) { + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + } + LLVMContext &Context = getGlobalContext(); + + cl::ParseCommandLineOptions(argc, argv, + "Kaleidoscope example program\n"); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Make the Helper, which holds all the code. + if (UseMCJIT) + TheHelper = new MCJITHelper(Context); + else + TheHelper = new JITHelper(Context); + + // Prime the first token. + if (!SuppressPrompts) + fprintf(stderr, "ready> "); + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + if (DumpModulesOnExit) + TheHelper->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/initial/Makefile b/examples/Kaleidoscope/MCJIT/initial/Makefile new file mode 100644 index 00000000..2989832d --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/initial/Makefile @@ -0,0 +1,4 @@ +all: toy-mcjit + +toy-mcjit : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native` -o toy-mcjit diff --git a/examples/Kaleidoscope/MCJIT/initial/README.txt b/examples/Kaleidoscope/MCJIT/initial/README.txt new file mode 100644 index 00000000..b352a784 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/initial/README.txt @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory demonstrates the initial working version of +the program before subsequent performance improvements are applied. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required, as mentioned in the blog posts. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/initial/toy.cpp b/examples/Kaleidoscope/MCJIT/initial/toy.cpp new file mode 100644 index 00000000..7e2f7df0 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/initial/toy.cpp @@ -0,0 +1,1382 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), OpenModule(NULL) {} + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + void dump(); + +private: + typedef std::vector ModuleVector; + typedef std::vector EngineVector; + + LLVMContext &Context; + Module *OpenModule; + ModuleVector Modules; + EngineVector Engines; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = SectionMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + if (OpenModule) + delete OpenModule; + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) + delete *it; +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == OpenModule) + return F; + + assert(OpenModule != NULL); + + // This function is in a module that has already been JITed. + // We need to generate a new prototype for external linkage. + Function *PF = OpenModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + OpenModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (OpenModule) + return OpenModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + OpenModule = M; + return M; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // See if an existing instance of MCJIT has this function. + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) { + void *P = (*it)->getPointerToFunction(F); + if (P) + return P; + } + + // If we didn't find the function, see if we can generate it. + if (OpenModule) { + std::string ErrStr; + ExecutionEngine *NewEngine = EngineBuilder(OpenModule) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!NewEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + // Create a function pass manager for this engine + FunctionPassManager *FPM = new FunctionPassManager(OpenModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*NewEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = OpenModule->end(); + for (it = OpenModule->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + // We don't need this anymore + delete FPM; + + OpenModule = NULL; + Engines.push_back(NewEngine); + NewEngine->finalizeObject(); + return NewEngine->getPointerToFunction(F); + } + return NULL; +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the function in each of our execution engines. + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) { + if (Function *F = (*it)->FindFunctionNamed(Name.c_str())) + return (*it)->getPointerToFunction(F); + } + + return NULL; +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static MCJITHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + char ErrStr[256]; + sprintf(ErrStr, "Unknown variable name %s", Name.c_str()); + if (V == 0) return ErrorV(ErrStr); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = reinterpret_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '/': return Builder.CreateFDiv(L, R, "divtmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + std::string FnName = MakeLegalFunctionName(Name); + + Module* M = TheHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheHelper->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Make the helper, which holds all the code. + TheHelper = new MCJITHelper(Context); + + // Run the main "interpreter loop" now. + MainLoop(); + +#ifndef MINIMAL_STDERR_OUTPUT + // Print out all of the generated code. + TheHelper->dump(); +#endif + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/lazy/Makefile b/examples/Kaleidoscope/MCJIT/lazy/Makefile new file mode 100644 index 00000000..21cbc18d --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/Makefile @@ -0,0 +1,7 @@ +all: toy-mcjit toy-jit + +toy-mcjit : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native` -o toy-mcjit + +toy-jit : toy-jit.cpp + clang++ toy-jit.cpp -g -O3 -rdynamic `llvm-config --cppflags --ldflags --libs core jit native` -o toy-jit diff --git a/examples/Kaleidoscope/MCJIT/lazy/README.txt b/examples/Kaleidoscope/MCJIT/lazy/README.txt new file mode 100644 index 00000000..c5c271e0 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/README.txt @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory demonstrates the second version of the +program, now modified to implement a sort of 'lazy' compilation. + +The toy-jit.cpp file contains a version of the original JIT-based source code +that has been modified to disable most stderr output for timing purposes. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required. + +This directory also contains a Python script that may be used to generate random +input for the program and test scripts to capture data for rough performance +comparisons. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/lazy/genk-timing.py b/examples/Kaleidoscope/MCJIT/lazy/genk-timing.py new file mode 100644 index 00000000..96dd6db5 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/genk-timing.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python + +import sys +import random + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.timeFile = outputname + self.shfile = open(scriptname, 'w') + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls): + """Echo some comments and invoke both versions of toy""" + rootname = filename + if '.' in filename: + rootname = filename[:filename.rfind('.')] + self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-jit < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class KScriptGenerator: + """Used to generate random Kaleidoscope code""" + def __init__(self, filename): + self.kfile = open(filename, 'w') + self.nextFuncNum = 1 + self.lastFuncNum = None + self.callWeighting = 0.1 + # A mapping of calls within functions with no duplicates + self.calledFunctionTable = {} + # A list of function calls which will actually be executed + self.calledFunctions = [] + # A comprehensive mapping of calls within functions + # used for computing the total number of calls + self.comprehensiveCalledFunctionTable = {} + self.totalCallsExecuted = 0 + + def updateTotalCallCount(self, callee): + # Count this call + self.totalCallsExecuted += 1 + # Then count all the functions it calls + if callee in self.comprehensiveCalledFunctionTable: + for child in self.comprehensiveCalledFunctionTable[callee]: + self.updateTotalCallCount(child) + + def updateFunctionCallMap(self, caller, callee): + """Maintains a map of functions that are called from other functions""" + if not caller in self.calledFunctionTable: + self.calledFunctionTable[caller] = [] + if not callee in self.calledFunctionTable[caller]: + self.calledFunctionTable[caller].append(callee) + if not caller in self.comprehensiveCalledFunctionTable: + self.comprehensiveCalledFunctionTable[caller] = [] + self.comprehensiveCalledFunctionTable[caller].append(callee) + + def updateCalledFunctionList(self, callee): + """Maintains a list of functions that will actually be called""" + # Update the total call count + self.updateTotalCallCount(callee) + # If this function is already in the list, don't do anything else + if callee in self.calledFunctions: + return + # Add this function to the list of those that will be called. + self.calledFunctions.append(callee) + # If this function calls other functions, add them too + if callee in self.calledFunctionTable: + for subCallee in self.calledFunctionTable[callee]: + self.updateCalledFunctionList(subCallee) + + def setCallWeighting(self, weight): + """ Sets the probably of generating a function call""" + self.callWeighting = weight + + def writeln(self, line): + self.kfile.write(line + '\n') + + def writeComment(self, comment): + self.writeln('# ' + comment) + + def writeEmptyLine(self): + self.writeln("") + + def writePredefinedFunctions(self): + self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands") + self.writeComment("and just returns the RHS.") + self.writeln("def binary : 1 (x y) y;") + self.writeEmptyLine() + self.writeComment("Helper functions defined within toy") + self.writeln("extern putchard(x);") + self.writeln("extern printd(d);") + self.writeln("extern printlf();") + self.writeEmptyLine() + self.writeComment("Print the result of a function call") + self.writeln("def printresult(N Result)") + self.writeln(" # 'result('") + self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :") + self.writeln(" printd(N) :"); + self.writeln(" # ') = '") + self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :") + self.writeln(" printd(Result) :"); + self.writeln(" printlf();") + self.writeEmptyLine() + + def writeRandomOperation(self, LValue, LHS, RHS): + shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting) + if shouldCallFunc: + funcToCall = random.randrange(1, self.lastFuncNum - 1) + self.updateFunctionCallMap(self.lastFuncNum, funcToCall) + self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS)) + else: + possibleOperations = ["+", "-", "*", "/"] + operation = random.choice(possibleOperations) + if operation == "-": + # Don't let our intermediate value become zero + # This is complicated by the fact that '<' is our only comparison operator + self.writeln(" if %s < %s then" % (LHS, RHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else if %s < %s then" % (RHS, LHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else") + self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100))) + else: + self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS)) + + def getNextFuncNum(self): + result = self.nextFuncNum + self.nextFuncNum += 1 + self.lastFuncNum = result + return result + + def writeFunction(self, elements): + funcNum = self.getNextFuncNum() + self.writeComment("Auto-generated function number %d" % funcNum) + self.writeln("def func%d(X Y)" % funcNum) + self.writeln(" var temp1 = X,") + self.writeln(" temp2 = Y,") + self.writeln(" temp3 in") + # Initialize the variable names to be rotated + first = "temp3" + second = "temp1" + third = "temp2" + # Write some random operations + for i in range(elements): + self.writeRandomOperation(first, second, third) + # Rotate the variables + temp = first + first = second + second = third + third = temp + self.writeln(" " + third + ";") + self.writeEmptyLine() + + def writeFunctionCall(self): + self.writeComment("Call the last function") + arg1 = random.uniform(1, 100) + arg2 = random.uniform(1, 100) + self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2)) + self.writeEmptyLine() + self.updateCalledFunctionList(self.lastFuncNum) + + def writeFinalFunctionCounts(self): + self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum)) + +def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript): + """ Generate a random Kaleidoscope script based on the given parameters """ + print "Generating " + filename + print(" %d functions, %d elements per function, %d functions between execution" % + (numFuncs, elementsPerFunc, funcsBetweenExec)) + print(" Call weighting = %f" % callWeighting) + script = KScriptGenerator(filename) + script.setCallWeighting(callWeighting) + script.writeComment("===========================================================================") + script.writeComment("Auto-generated script") + script.writeComment(" %d functions, %d elements per function, %d functions between execution" + % (numFuncs, elementsPerFunc, funcsBetweenExec)) + script.writeComment(" call weighting = %f" % callWeighting) + script.writeComment("===========================================================================") + script.writeEmptyLine() + script.writePredefinedFunctions() + funcsSinceLastExec = 0 + for i in range(numFuncs): + script.writeFunction(elementsPerFunc) + funcsSinceLastExec += 1 + if funcsSinceLastExec == funcsBetweenExec: + script.writeFunctionCall() + funcsSinceLastExec = 0 + # Always end with a function call + if funcsSinceLastExec > 0: + script.writeFunctionCall() + script.writeEmptyLine() + script.writeFinalFunctionCounts() + funcsCalled = len(script.calledFunctions) + print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted) + timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted) + +# Execution begins here +random.seed() + +timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt") + +dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0), + (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0), + ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)] + +# Generate the code +for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets: + filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100)) + generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp new file mode 100644 index 00000000..c3d88c83 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp @@ -0,0 +1,1168 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static FunctionPassManager *TheFPM; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) return ErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; +#ifdef USE_MCJIT + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); +#else + Function *F = TheModule->getFunction(std::string("unary")+Opcode); +#endif + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = dynamic_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '/': return Builder.CreateFDiv(L, R, "divtmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) { + char error_str[64]; + sprintf(error_str, "Unknown function referenced %s", Callee.c_str()); + return ErrorV(error_str); + } + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + TheFPM = 0; +#ifndef MINIMAL_STDERR_OUTPUT + TheModule->dump(); +#endif + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp new file mode 100644 index 00000000..189331c0 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp @@ -0,0 +1,1423 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), OpenModule(NULL) {} + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + ExecutionEngine *compileModule(Module *M); + void closeCurrentModule(); + void dump(); + +private: + typedef std::vector ModuleVector; + + LLVMContext &Context; + Module *OpenModule; + ModuleVector Modules; + std::map EngineMap; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = SectionMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + // Walk the vector of modules. + ModuleVector::iterator it, end; + for (it = Modules.begin(), end = Modules.end(); + it != end; ++it) { + // See if we have an execution engine for this module. + std::map::iterator mapIt = EngineMap.find(*it); + // If we have an EE, the EE owns the module so just delete the EE. + if (mapIt != EngineMap.end()) { + delete mapIt->second; + } else { + // Otherwise, we still own the module. Delete it now. + delete *it; + } + } +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == OpenModule) + return F; + + assert(OpenModule != NULL); + + // This function is in a module that has already been JITed. + // We need to generate a new prototype for external linkage. + Function *PF = OpenModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + OpenModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (OpenModule) + return OpenModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + OpenModule = M; + return M; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // Look for this function in an existing module + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + std::string FnName = F->getName(); + for (it = begin; it != end; ++it) { + Function *MF = (*it)->getFunction(FnName); + if (MF == F) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::closeCurrentModule() { + OpenModule = NULL; +} + +ExecutionEngine *MCJITHelper::compileModule(Module *M) { + if (M == OpenModule) + closeCurrentModule(); + + std::string ErrStr; + ExecutionEngine *NewEngine = EngineBuilder(M) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!NewEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + // Create a function pass manager for this engine + FunctionPassManager *FPM = new FunctionPassManager(M); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*NewEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = M->end(); + for (it = M->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + // We don't need this anymore + delete FPM; + + // Store this engine + EngineMap[M] = NewEngine; + NewEngine->finalizeObject(); + + return NewEngine; +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the functions in our modules, compiling only as necessary + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(Name); + if (F && !F->empty()) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static MCJITHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + char ErrStr[256]; + sprintf(ErrStr, "Unknown variable name %s", Name.c_str()); + if (V == 0) return ErrorV(ErrStr); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = reinterpret_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '/': return Builder.CreateFDiv(L, R, "divtmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + std::string FnName = MakeLegalFunctionName(Name); + + Module* M = TheHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + TheHelper->closeCurrentModule(); + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheHelper->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Make the helper, which holds all the code. + TheHelper = new MCJITHelper(Context); + + // Run the main "interpreter loop" now. + MainLoop(); + +#ifndef MINIMAL_STDERR_OUTPUT + // Print out all of the generated code. + TheHelper->dump(); +#endif + + return 0; +} diff --git a/examples/Kaleidoscope/Makefile b/examples/Kaleidoscope/Makefile new file mode 100644 index 00000000..bd0c252c --- /dev/null +++ b/examples/Kaleidoscope/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL=../.. + +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 + +include $(LEVEL)/Makefile.common diff --git a/examples/LLVMBuild.txt b/examples/LLVMBuild.txt new file mode 100644 index 00000000..4d06ffb9 --- /dev/null +++ b/examples/LLVMBuild.txt @@ -0,0 +1,21 @@ +;===- ./examples/LLVMBuild.txt ---------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Group +name = Examples +parent = $ROOT diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 00000000..50a6db76 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,32 @@ +##===- examples/Makefile -----------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL=.. + +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS:= BrainF Fibonacci HowToUseJIT Kaleidoscope ModuleMaker + +ifeq ($(HAVE_PTHREAD),1) +PARALLEL_DIRS += ParallelJIT +endif + +ifeq ($(LLVM_ON_UNIX),1) + ifeq ($(ARCH),x86) + PARALLEL_DIRS += ExceptionDemo + endif + ifeq ($(ARCH),x86_64) + PARALLEL_DIRS += ExceptionDemo + endif +endif + +ifeq ($(filter $(BINDINGS_TO_BUILD),ocaml),ocaml) + PARALLEL_DIRS += OCaml-Kaleidoscope +endif + +include $(LEVEL)/Makefile.common diff --git a/examples/ModuleMaker/CMakeLists.txt b/examples/ModuleMaker/CMakeLists.txt new file mode 100644 index 00000000..81e91156 --- /dev/null +++ b/examples/ModuleMaker/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS bitwriter) + +add_llvm_example(ModuleMaker + ModuleMaker.cpp + ) diff --git a/examples/ModuleMaker/Makefile b/examples/ModuleMaker/Makefile new file mode 100644 index 00000000..9454cf51 --- /dev/null +++ b/examples/ModuleMaker/Makefile @@ -0,0 +1,14 @@ +##===- examples/ModuleMaker/Makefile -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL=../.. +TOOLNAME=ModuleMaker +EXAMPLE_TOOL = 1 +LINK_COMPONENTS := bitwriter + +include $(LEVEL)/Makefile.common diff --git a/examples/ModuleMaker/ModuleMaker.cpp b/examples/ModuleMaker/ModuleMaker.cpp new file mode 100644 index 00000000..c931972f --- /dev/null +++ b/examples/ModuleMaker/ModuleMaker.cpp @@ -0,0 +1,64 @@ +//===- examples/ModuleMaker/ModuleMaker.cpp - Example project ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This programs is a simple example that creates an LLVM module "from scratch", +// emitting it as a bitcode file to standard out. This is just to show how +// LLVM projects work and to demonstrate some of the LLVM APIs. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +int main() { + LLVMContext Context; + + // Create the "module" or "program" or "translation unit" to hold the + // function + Module *M = new Module("test", Context); + + // Create the main function: first create the type 'int ()' + FunctionType *FT = + FunctionType::get(Type::getInt32Ty(Context), /*not vararg*/false); + + // By passing a module as the last parameter to the Function constructor, + // it automatically gets appended to the Module. + Function *F = Function::Create(FT, Function::ExternalLinkage, "main", M); + + // Add a basic block to the function... again, it automatically inserts + // because of the last argument. + BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", F); + + // Get pointers to the constant integers... + Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2); + Value *Three = ConstantInt::get(Type::getInt32Ty(Context), 3); + + // Create the add instruction... does not insert... + Instruction *Add = BinaryOperator::Create(Instruction::Add, Two, Three, + "addresult"); + + // explicitly insert it into the basic block... + BB->getInstList().push_back(Add); + + // Create the return instruction and add it to the basic block + BB->getInstList().push_back(ReturnInst::Create(Context, Add)); + + // Output the bitcode file to stdout + WriteBitcodeToFile(M, outs()); + + // Delete the module and all of its contents. + delete M; + return 0; +} diff --git a/examples/ModuleMaker/README.txt b/examples/ModuleMaker/README.txt new file mode 100644 index 00000000..66a5d3fe --- /dev/null +++ b/examples/ModuleMaker/README.txt @@ -0,0 +1,8 @@ +//===----------------------------------------------------------------------===// +// ModuleMaker Sample project +//===----------------------------------------------------------------------===// + +This project is an extremely simple example of using some simple pieces of the +LLVM API. The actual executable generated by this project simply emits an +LLVM bitcode file to standard output. It is designed to show some basic +usage of LLVM APIs, and how to link to LLVM libraries. diff --git a/examples/OCaml-Kaleidoscope/Chapter2/Makefile b/examples/OCaml-Kaleidoscope/Chapter2/Makefile new file mode 100644 index 00000000..8fc03da0 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/Makefile @@ -0,0 +1,22 @@ +##===- examples/OCaml-Kaleidoscope/Chapter2/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 2. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch2 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm + +OCAMLCFLAGS += -pp camlp4of + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter2/_tags b/examples/OCaml-Kaleidoscope/Chapter2/_tags new file mode 100644 index 00000000..7b9b80b1 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/_tags @@ -0,0 +1 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) diff --git a/examples/OCaml-Kaleidoscope/Chapter2/ast.ml b/examples/OCaml-Kaleidoscope/Chapter2/ast.ml new file mode 100644 index 00000000..4cc2dea8 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/ast.ml @@ -0,0 +1,25 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = Prototype of string * string array + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/examples/OCaml-Kaleidoscope/Chapter2/lexer.ml b/examples/OCaml-Kaleidoscope/Chapter2/lexer.ml new file mode 100644 index 00000000..22a91555 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/lexer.ml @@ -0,0 +1,52 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/examples/OCaml-Kaleidoscope/Chapter2/parser.ml b/examples/OCaml-Kaleidoscope/Chapter2/parser.ml new file mode 100644 index 00000000..83d9874a --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/parser.ml @@ -0,0 +1,122 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/examples/OCaml-Kaleidoscope/Chapter2/token.ml b/examples/OCaml-Kaleidoscope/Chapter2/token.ml new file mode 100644 index 00000000..2ca782e1 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/token.ml @@ -0,0 +1,15 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char diff --git a/examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml b/examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml new file mode 100644 index 00000000..01c85bd7 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml @@ -0,0 +1,34 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +(* top ::= definition | external | expression | ';' *) +let rec main_loop stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop stream + + | Some token -> + begin + try match token with + | Token.Def -> + ignore(Parser.parse_definition stream); + print_endline "parsed a function definition."; + | Token.Extern -> + ignore(Parser.parse_extern stream); + print_endline "parsed an extern."; + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + ignore(Parser.parse_toplevel stream); + print_endline "parsed a top-level expr"; + with Stream.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop stream diff --git a/examples/OCaml-Kaleidoscope/Chapter2/toy.ml b/examples/OCaml-Kaleidoscope/Chapter2/toy.ml new file mode 100644 index 00000000..42b19fec --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter2/toy.ml @@ -0,0 +1,21 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop stream; +;; + +main () diff --git a/examples/OCaml-Kaleidoscope/Chapter3/Makefile b/examples/OCaml-Kaleidoscope/Chapter3/Makefile new file mode 100644 index 00000000..fdbcd519 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/Makefile @@ -0,0 +1,24 @@ +##===- examples/OCaml-Kaleidoscope/Chapter3/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 3. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch3 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm llvm_analysis + +OCAMLCFLAGS += -pp camlp4of + +ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter3/_tags b/examples/OCaml-Kaleidoscope/Chapter3/_tags new file mode 100644 index 00000000..990490a5 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/_tags @@ -0,0 +1,2 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis diff --git a/examples/OCaml-Kaleidoscope/Chapter3/ast.ml b/examples/OCaml-Kaleidoscope/Chapter3/ast.ml new file mode 100644 index 00000000..4cc2dea8 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/ast.ml @@ -0,0 +1,25 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = Prototype of string * string array + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/examples/OCaml-Kaleidoscope/Chapter3/codegen.ml b/examples/OCaml-Kaleidoscope/Chapter3/codegen.ml new file mode 100644 index 00000000..275cd0be --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/codegen.ml @@ -0,0 +1,100 @@ +(*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + +open Llvm + +exception Error of string + +let context = global_context () +let the_module = create_module context "my cool jit" +let builder = builder context +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 +let double_type = double_type context + +let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + +let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + +let codegen_func = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + the_function + with e -> + delete_function the_function; + raise e diff --git a/examples/OCaml-Kaleidoscope/Chapter3/lexer.ml b/examples/OCaml-Kaleidoscope/Chapter3/lexer.ml new file mode 100644 index 00000000..22a91555 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/lexer.ml @@ -0,0 +1,52 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml b/examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml new file mode 100644 index 00000000..b71f5d71 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml @@ -0,0 +1,6 @@ +open Ocamlbuild_plugin;; + +ocaml_lib ~extern:true "llvm";; +ocaml_lib ~extern:true "llvm_analysis";; + +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; diff --git a/examples/OCaml-Kaleidoscope/Chapter3/parser.ml b/examples/OCaml-Kaleidoscope/Chapter3/parser.ml new file mode 100644 index 00000000..83d9874a --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/parser.ml @@ -0,0 +1,122 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/examples/OCaml-Kaleidoscope/Chapter3/token.ml b/examples/OCaml-Kaleidoscope/Chapter3/token.ml new file mode 100644 index 00000000..2ca782e1 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/token.ml @@ -0,0 +1,15 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char diff --git a/examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml b/examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml new file mode 100644 index 00000000..d1bf5d4c --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml @@ -0,0 +1,39 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +open Llvm + +(* top ::= definition | external | expression | ';' *) +let rec main_loop stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + dump_value (Codegen.codegen_func e); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop stream diff --git a/examples/OCaml-Kaleidoscope/Chapter3/toy.ml b/examples/OCaml-Kaleidoscope/Chapter3/toy.ml new file mode 100644 index 00000000..73c1a1ec --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter3/toy.ml @@ -0,0 +1,26 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +open Llvm + +let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module +;; + +main () diff --git a/examples/OCaml-Kaleidoscope/Chapter4/Makefile b/examples/OCaml-Kaleidoscope/Chapter4/Makefile new file mode 100644 index 00000000..d9c3f49b --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter4/Makefile @@ -0,0 +1,25 @@ +##===- examples/OCaml-Kaleidoscope/Chapter4/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 4. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch4 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ + llvm_scalar_opts + +OCAMLCFLAGS += -pp camlp4of + +ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/examples/OCaml-Kaleidoscope/Chapter4/_tags b/examples/OCaml-Kaleidoscope/Chapter4/_tags new file mode 100644 index 00000000..7a03dba6 --- /dev/null +++ b/examples/OCaml-Kaleidoscope/Chapter4/_tags @@ -0,0 +1,4 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings diff --git a/examples/OCaml-Kaleidoscope/Chapter4/ast.ml b/examples/OCaml-Kaleidoscop