Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -104,6 +104,8 @@ RM_Disabled, }; + enum FileType { FT_Object, FT_Static, FT_Shared }; + private: friend class RegisterEffectiveTriple; @@ -365,11 +367,11 @@ virtual std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, - bool Shared = false) const; + FileType Type = ToolChain::FT_Static) const; - const char *getCompilerRTArgString(const llvm::opt::ArgList &Args, - StringRef Component, - bool Shared = false) const; + const char * + getCompilerRTArgString(const llvm::opt::ArgList &Args, StringRef Component, + FileType Type = ToolChain::FT_Static) const; // Returns /lib//. This is used by runtimes (such // as OpenMP) to find arch-specific libraries. Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -363,16 +363,27 @@ } std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, - bool Shared) const { + FileType Type) const { const llvm::Triple &TT = getTriple(); bool IsITANMSVCWindows = TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment(); - const char *Prefix = IsITANMSVCWindows ? "" : "lib"; - const char *Suffix = Shared ? (Triple.isOSWindows() ? ".lib" : ".so") - : (IsITANMSVCWindows ? ".lib" : ".a"); - if (Shared && Triple.isWindowsGNUEnvironment()) - Suffix = ".dll.a"; + const char *Prefix = + IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib"; + const char *Suffix; + switch (Type) { + case ToolChain::FT_Object: + Suffix = Triple.isOSWindows() ? ".obj" : ".o"; + break; + case ToolChain::FT_Static: + Suffix = IsITANMSVCWindows ? ".lib" : ".a"; + break; + case ToolChain::FT_Shared: + Suffix = Triple.isOSWindows() + ? (Triple.isWindowsGNUEnvironment() ? ".dll.a" : ".dll") + : ".so"; + break; + } for (const auto &LibPath : getLibraryPaths()) { SmallString<128> P(LibPath); @@ -391,8 +402,8 @@ const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, StringRef Component, - bool Shared) const { - return Args.MakeArgString(getCompilerRT(Args, Component, Shared)); + FileType Type) const { + return Args.MakeArgString(getCompilerRT(Args, Component, Type)); } std::string ToolChain::getArchSpecificLibPath() const { Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -530,7 +530,8 @@ // Wrap any static runtimes that must be forced into executable in // whole-archive. if (IsWhole) CmdArgs.push_back("--whole-archive"); - CmdArgs.push_back(TC.getCompilerRTArgString(Args, Sanitizer, IsShared)); + CmdArgs.push_back(TC.getCompilerRTArgString( + Args, Sanitizer, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static)); if (IsWhole) CmdArgs.push_back("--no-whole-archive"); if (IsShared) { @@ -777,9 +778,9 @@ if (TC.getXRayArgs().needsXRayRt()) { CmdArgs.push_back("-whole-archive"); - CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray", false)); + CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray")); for (const auto &Mode : TC.getXRayArgs().modeList()) - CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode, false)); + CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode)); CmdArgs.push_back("-no-whole-archive"); return true; } Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -433,19 +433,23 @@ if (IsIAMCU) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); - else { + else if (HasCRTBeginEndFiles) { const char *crtbegin; - if (Args.hasArg(options::OPT_static)) - crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; - else if (Args.hasArg(options::OPT_shared)) - crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; - else if (IsPIE) - crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; - else - crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; + if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT && !isAndroid) { + crtbegin = Args.hasArg(options::OPT_shared) || IsPIE ? "crtbegin_shared" : "crtbegin"; + CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, crtbegin, ToolChain::FT_Object)); + } else { + if (Args.hasArg(options::OPT_static)) + crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; + else if (Args.hasArg(options::OPT_shared)) + crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; + else if (IsPIE) + crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; + else + crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; - if (HasCRTBeginEndFiles) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); + } } // Add crtfastmath.o if available and fast math is enabled. @@ -539,16 +543,22 @@ } if (!Args.hasArg(options::OPT_nostartfiles) && !IsIAMCU) { - const char *crtend; - if (Args.hasArg(options::OPT_shared)) - crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; - else if (IsPIE) - crtend = isAndroid ? "crtend_android.o" : "crtendS.o"; - else - crtend = isAndroid ? "crtend_android.o" : "crtend.o"; - - if (HasCRTBeginEndFiles) - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); + if (HasCRTBeginEndFiles) { + const char *crtend; + if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT && !isAndroid) { + crtend = Args.hasArg(options::OPT_shared) || IsPIE ? "crtend_shared" : "crtend"; + CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, crtend, ToolChain::FT_Object)); + } else { + if (Args.hasArg(options::OPT_shared)) + crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; + else if (IsPIE) + crtend = isAndroid ? "crtend_android.o" : "crtendS.o"; + else + crtend = isAndroid ? "crtend_android.o" : "crtend.o"; + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); + } + } if (!isAndroid) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -378,7 +378,7 @@ if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back( Args.MakeArgString(std::string("-wholearchive:") + - TC.getCompilerRTArgString(Args, "fuzzer", false))); + TC.getCompilerRTArgString(Args, "fuzzer"))); CmdArgs.push_back(Args.MakeArgString("-debug")); // Prevent the linker from padding sections we use for instrumentation // arrays. Index: clang/lib/Driver/ToolChains/MinGW.cpp =================================================================== --- clang/lib/Driver/ToolChains/MinGW.cpp +++ clang/lib/Driver/ToolChains/MinGW.cpp @@ -249,8 +249,8 @@ if (Sanitize.needsAsanRt()) { // MinGW always links against a shared MSVCRT. - CmdArgs.push_back( - TC.getCompilerRTArgString(Args, "asan_dynamic", true)); + CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", + ToolChain::FT_Shared)); CmdArgs.push_back( TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); CmdArgs.push_back(Args.MakeArgString("--require-defined")); Index: clang/lib/Driver/ToolChains/MipsLinux.h =================================================================== --- clang/lib/Driver/ToolChains/MipsLinux.h +++ clang/lib/Driver/ToolChains/MipsLinux.h @@ -38,8 +38,9 @@ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; - std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, - bool Shared = false) const override; + std::string + getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, + FileType Type = ToolChain::FT_Static) const override; std::string computeSysRoot() const override; Index: clang/lib/Driver/ToolChains/MipsLinux.cpp =================================================================== --- clang/lib/Driver/ToolChains/MipsLinux.cpp +++ clang/lib/Driver/ToolChains/MipsLinux.cpp @@ -119,11 +119,23 @@ std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args, StringRef Component, - bool Shared) const { + FileType Type) const { SmallString<128> Path(getDriver().ResourceDir); llvm::sys::path::append(Path, SelectedMultilib.osSuffix(), "lib" + LibSuffix, getOS()); - llvm::sys::path::append(Path, Twine("libclang_rt." + Component + "-" + - "mips" + (Shared ? ".so" : ".a"))); + const char *Suffix; + switch (Type) { + case ToolChain::FT_Object: + Suffix = ".o"; + break; + case ToolChain::FT_Static: + Suffix = ".a"; + break; + case ToolChain::FT_Shared: + Suffix = ".so"; + break; + } + llvm::sys::path::append( + Path, Twine("libclang_rt." + Component + "-" + "mips" + Suffix)); return Path.str(); } Index: clang/lib/Driver/ToolChains/OpenBSD.cpp =================================================================== --- clang/lib/Driver/ToolChains/OpenBSD.cpp +++ clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -189,11 +189,11 @@ CmdArgs.push_back("-lm"); } if (NeedsSanitizerDeps) { - CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins", false)); + CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins")); linkSanitizerRuntimeDeps(ToolChain, CmdArgs); } if (NeedsXRayDeps) { - CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins", false)); + CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins")); linkXRayRuntimeDeps(ToolChain, CmdArgs); } // FIXME: For some reason GCC passes -lgcc before adding Index: clang/lib/Driver/ToolChains/Solaris.cpp =================================================================== --- clang/lib/Driver/ToolChains/Solaris.cpp +++ clang/lib/Driver/ToolChains/Solaris.cpp @@ -101,7 +101,7 @@ // __start_SECNAME labels. CmdArgs.push_back("--whole-archive"); CmdArgs.push_back( - getToolChain().getCompilerRTArgString(Args, "sancov_begin", false)); + getToolChain().getCompilerRTArgString(Args, "sancov_begin")); CmdArgs.push_back("--no-whole-archive"); getToolChain().AddFilePathLibArgs(Args, CmdArgs); @@ -135,8 +135,7 @@ // Provide __stop___sancov_guards. Solaris ld doesn't automatically create // __stop_SECNAME labels. CmdArgs.push_back("--whole-archive"); - CmdArgs.push_back( - getToolChain().getCompilerRTArgString(Args, "sancov_end", false)); + CmdArgs.push_back(getToolChain().getCompilerRTArgString(Args, "sancov_end")); CmdArgs.push_back("--no-whole-archive"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { Index: compiler-rt/CMakeLists.txt =================================================================== --- compiler-rt/CMakeLists.txt +++ compiler-rt/CMakeLists.txt @@ -29,6 +29,8 @@ option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON) mark_as_advanced(COMPILER_RT_BUILD_BUILTINS) +option(COMPILER_RT_BUILD_CRT "Build crtbegin.o/crtend.o" ON) +mark_as_advanced(COMPILER_RT_BUILD_CRT) option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON) mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS) option(COMPILER_RT_BUILD_XRAY "Build xray" ON) Index: compiler-rt/cmake/Modules/AddCompilerRT.cmake =================================================================== --- compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -132,7 +132,7 @@ # Adds static or shared runtime for a list of architectures and operating # systems and puts it in the proper directory in the build and install trees. # add_compiler_rt_runtime( -# {STATIC|SHARED} +# {OBJECT|STATIC|SHARED} # ARCHS # OS # SOURCES @@ -144,8 +144,8 @@ # PARENT_TARGET # ADDITIONAL_HEADERS
) function(add_compiler_rt_runtime name type) - if(NOT type MATCHES "^(STATIC|SHARED)$") - message(FATAL_ERROR "type argument must be STATIC or SHARED") + if(NOT type MATCHES "^(OBJECT|STATIC|SHARED)$") + message(FATAL_ERROR "type argument must be OBJECT, STATIC or SHARED") return() endif() cmake_parse_arguments(LIB @@ -204,7 +204,10 @@ message(FATAL_ERROR "Architecture ${arch} can't be targeted") return() endif() - if(type STREQUAL "STATIC") + if(type STREQUAL "OBJECT") + set(libname "${name}-${arch}") + set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX}) + elseif(type STREQUAL "STATIC") set(libname "${name}-${arch}") set_output_name(output_name_${libname} ${name} ${arch}) else() @@ -270,12 +273,34 @@ set(COMPONENT_OPTION COMPONENT ${libname}) endif() - add_library(${libname} ${type} ${sources_${libname}}) - set_target_compile_flags(${libname} ${extra_cflags_${libname}}) - set_target_link_flags(${libname} ${extra_link_flags_${libname}}) - set_property(TARGET ${libname} APPEND PROPERTY - COMPILE_DEFINITIONS ${LIB_DEFS}) - set_target_output_directories(${libname} ${output_dir_${libname}}) + if(type STREQUAL "OBJECT") + string(TOUPPER ${CMAKE_BUILD_TYPE} config) + get_property(cflags SOURCE ${sources_${libname}} PROPERTY COMPILE_FLAGS) + separate_arguments(cflags) + add_custom_command( + OUTPUT ${output_dir_${libname}}/${libname}.o + COMMAND ${CMAKE_C_COMPILER} ${sources_${libname}} ${cflags} ${extra_cflags_${libname}} -c -o ${output_dir_${libname}}/${libname}.o + DEPENDS ${sources_${libname}} + COMMENT "Building C object ${libname}.o") + add_custom_target(${libname} DEPENDS ${output_dir_${libname}}/${libname}.o) + install(FILES ${output_dir_${libname}}/${libname}.o + DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION}) + else() + add_library(${libname} ${type} ${sources_${libname}}) + set_target_compile_flags(${libname} ${extra_cflags_${libname}}) + set_target_link_flags(${libname} ${extra_link_flags_${libname}}) + set_property(TARGET ${libname} APPEND PROPERTY + COMPILE_DEFINITIONS ${LIB_DEFS}) + set_target_output_directories(${libname} ${output_dir_${libname}}) + install(TARGETS ${libname} + ARCHIVE DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION} + LIBRARY DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION} + RUNTIME DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION}) + endif() set_target_properties(${libname} PROPERTIES OUTPUT_NAME ${output_name_${libname}}) set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Runtime") @@ -299,13 +324,6 @@ ) endif() endif() - install(TARGETS ${libname} - ARCHIVE DESTINATION ${install_dir_${libname}} - ${COMPONENT_OPTION} - LIBRARY DESTINATION ${install_dir_${libname}} - ${COMPONENT_OPTION} - RUNTIME DESTINATION ${install_dir_${libname}} - ${COMPONENT_OPTION}) # We only want to generate per-library install targets if you aren't using # an IDE because the extra targets get cluttered in IDEs. Index: compiler-rt/cmake/config-ix.cmake =================================================================== --- compiler-rt/cmake/config-ix.cmake +++ compiler-rt/cmake/config-ix.cmake @@ -226,6 +226,7 @@ ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X}) set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64} ${S390X}) +set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) @@ -469,6 +470,7 @@ SANITIZER_COMMON_SUPPORTED_ARCH) else() + filter_available_targets(CRT_SUPPORTED_ARCH ${ALL_CRT_SUPPORTED_ARCH}) # Architectures supported by compiler-rt libraries. filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH ${ALL_SANITIZER_COMMON_SUPPORTED_ARCH}) @@ -557,6 +559,12 @@ # TODO: Add builtins support. +if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux") + set(COMPILER_RT_HAS_CRT TRUE) +else() + set(COMPILER_RT_HAS_CRT FALSE) +endif() + if (COMPILER_RT_HAS_SANITIZER_COMMON AND DFSAN_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux") set(COMPILER_RT_HAS_DFSAN TRUE) Index: compiler-rt/lib/CMakeLists.txt =================================================================== --- compiler-rt/lib/CMakeLists.txt +++ compiler-rt/lib/CMakeLists.txt @@ -17,6 +17,10 @@ add_subdirectory(builtins) endif() +if(COMPILER_RT_BUILD_CRT) + add_subdirectory(crt) +endif() + function(compiler_rt_build_runtime runtime) string(TOUPPER ${runtime} runtime_uppercase) if(COMPILER_RT_HAS_${runtime_uppercase}) Index: compiler-rt/lib/crt/CMakeLists.txt =================================================================== --- /dev/null +++ compiler-rt/lib/crt/CMakeLists.txt @@ -0,0 +1,101 @@ +add_compiler_rt_component(crt) + +function(check_cxx_section_exists section output) + cmake_parse_arguments(ARG "" "" "SOURCE;FLAGS" ${ARGN}) + if(NOT ARG_SOURCE) + set(ARG_SOURCE "int main() { return 0; }\n") + endif() + + string(RANDOM TARGET_NAME) + set(TARGET_NAME "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cmTC_${TARGET_NAME}.dir") + file(MAKE_DIRECTORY ${TARGET_NAME}) + + file(WRITE "${TARGET_NAME}/CheckSectionExists.c" "${ARG_SOURCE}\n") + + string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions + ${CMAKE_C_COMPILE_OBJECT}) + + set(try_compile_flags "${ARG_FLAGS}") + if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET) + list(APPEND try_compile_flags "-target ${CMAKE_C_COMPILER_TARGET}") + endif() + + string(REPLACE ";" " " extra_flags "${try_compile_flags}") + + set(test_compile_command "${CMAKE_C_COMPILE_OBJECT}") + foreach(substitution ${substitutions}) + if(substitution STREQUAL "") + string(REPLACE "" + "${CMAKE_C_COMPILER}" test_compile_command ${test_compile_command}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.o" + test_compile_command ${test_compile_command}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.c" + test_compile_command ${test_compile_command}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${CMAKE_C_FLAGS} ${extra_flags}" + test_compile_command ${test_compile_command}) + else() + string(REPLACE "${substitution}" "" test_compile_command + ${test_compile_command}) + endif() + endforeach() + + string(REPLACE " " ";" test_compile_command "${test_compile_command}") + + execute_process( + COMMAND ${test_compile_command} + RESULT_VARIABLE TEST_RESULT + OUTPUT_VARIABLE TEST_OUTPUT + ERROR_VARIABLE TEST_ERROR + ) + + execute_process( + COMMAND ${CMAKE_OBJDUMP} -h "${TARGET_NAME}/CheckSectionExists.o" + RESULT_VARIABLE CHECK_RESULT + OUTPUT_VARIABLE CHECK_OUTPUT + ERROR_VARIABLE CHECK_ERROR + ) + string(FIND ${CHECK_OUTPUT} ${section} SECTION_FOUND) + + if(NOT SECTION_FOUND EQUAL -1) + set(${output} TRUE PARENT_SCOPE) + else() + set(${output} FALSE PARENT_SCOPE) + endif() + + file(REMOVE_RECURSE ${TARGET_NAME}) +endfunction() + +check_cxx_section_exists(".init_array" COMPILER_RT_HAS_INITFINI_ARRAY + SOURCE "__attribute__((constructor)) void f() {}\nint main() { return 0; }\n") + +append_list_if(COMPILER_RT_HAS_INITFINI_ARRAY -DCRT_HAS_INITFINI_ARRAY CRT_CFLAGS) + +foreach(arch ${CRT_SUPPORTED_ARCH}) + add_compiler_rt_runtime(clang_rt.crtbegin + OBJECT + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtbegin.c + CFLAGS ${CRT_CFLAGS} + PARENT_TARGET crt) + add_compiler_rt_runtime(clang_rt.crtbegin_shared + OBJECT + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtbegin.c + CFLAGS ${CRT_CFLAGS} -DCRT_SHARED -fPIC + PARENT_TARGET crt) + add_compiler_rt_runtime(clang_rt.crtend + OBJECT + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtend.c + CFLAGS ${CRT_CFLAGS} + PARENT_TARGET crt) + add_compiler_rt_runtime(clang_rt.crtend_shared + OBJECT + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtend.c + CFLAGS ${CRT_CFLAGS} -DCRT_SHARED -fPIC + PARENT_TARGET crt) +endforeach() Index: compiler-rt/lib/crt/crtbegin.c =================================================================== --- /dev/null +++ compiler-rt/lib/crt/crtbegin.c @@ -0,0 +1,93 @@ +/* ===-- crtbegin.c - Start of constructors and destructors ----------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + */ + +__attribute__((visibility("hidden"))) +#ifdef CRT_SHARED +void *__dso_handle = &__dso_handle; +#else +void *__dso_handle = (void *)0; +#endif + +static const long __EH_FRAME_LIST__[] __attribute__(( + section(".eh_frame"), aligned(4), visibility("hidden"))) = {}; + +struct object { + void *p[8]; +}; + +extern void __register_frame_info(const void *, void *) __attribute__((weak)); + +extern void *__deregister_frame_info(const void *) __attribute__((weak)); +extern void *__deregister_frame_info_bases(const void *) __attribute__((weak)); + +#ifndef CRT_HAS_INITFINI_ARRAY +typedef void (*fp)(void); +static const fp __CTOR_LIST__[] + __attribute__((section(".ctors"), aligned(sizeof(fp)), visibility("hidden"), + used)) = {(fp)-1}; +extern const fp __CTOR_END__[] __attribute__((visibility("hidden"))); +#endif + +#ifdef CRT_SHARED +extern void __cxa_finalize(void *) __attribute__((weak)); +#endif + +static void __attribute__((used)) __do_init() { + static _Bool __initialized; + if (__builtin_expect(__initialized, 0)) + return; + __initialized = 1; + + static struct object ob; + if (__register_frame_info) + __register_frame_info(__EH_FRAME_LIST__, &ob); + +#ifndef CRT_HAS_INITFINI_ARRAY + unsigned long n = (unsigned long)__CTOR_LIST__[0]; + if (n == (unsigned long)-1) + for (n = 0; __CTOR_LIST__[n + 1] != 0; n++) + ; + for (unsigned long i = n; i >= 1; i--) + __CTOR_LIST__[i](); +#endif +} + +#ifndef CRT_HAS_INITFINI_ARRAY +static const fp __DTOR_LIST__[] + __attribute__((section(".dtors"), aligned(sizeof(fp)), visibility("hidden"), + used)) = {(fp)-1}; +extern const fp __DTOR_END__[] __attribute__((visibility("hidden"))); +#endif + +__attribute__((section(".init_array"), + used)) static void (*__init)(void) = __do_init; + +static void __attribute__((used)) __do_fini() { + static _Bool __finalized; + if (__builtin_expect(__finalized, 0)) + return; + __finalized = 1; + +#ifdef CRT_SHARED + if (__cxa_finalize) + __cxa_finalize(__dso_handle); +#endif + + if (__deregister_frame_info) + __deregister_frame_info(__EH_FRAME_LIST__); + +#ifndef CRT_HAS_INITFINI_ARRAY + for (unsigned long i = 1; __DTOR_LIST__[i]; i++) + __DTOR_LIST__[i](); +#endif +} + +__attribute__((section(".fini_array"), + used)) static void (*__fini)(void) = __do_fini; Index: compiler-rt/lib/crt/crtend.c =================================================================== --- /dev/null +++ compiler-rt/lib/crt/crtend.c @@ -0,0 +1,22 @@ +/* ===-- crtend.c - End of constructors and destructors --------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + */ + +#include + +const int32_t __EH_FRAME_END__[] + __attribute__((section(".eh_frame"), used)) = {0}; + +#ifndef CRT_HAS_INITFINI_ARRAY +typedef void (*fp)(void); +const fp __CTOR_END__[] + __attribute__((section(".ctors"), visibility("hidden"), used)) = {0}; +const fp __DTOR_END__[] + __attribute__((section(".dtors"), visibility("hidden"), used)) = {0}; +#endif Index: compiler-rt/test/CMakeLists.txt =================================================================== --- compiler-rt/test/CMakeLists.txt +++ compiler-rt/test/CMakeLists.txt @@ -79,6 +79,9 @@ if(COMPILER_RT_BUILD_XRAY) compiler_rt_test_runtime(xray) endif() + if(COMPILER_RT_HAS_CRT) + add_subdirectory(crt) + endif() # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests # include their own minimal runtime add_subdirectory(shadowcallstack) Index: compiler-rt/test/crt/CMakeLists.txt =================================================================== --- /dev/null +++ compiler-rt/test/crt/CMakeLists.txt @@ -0,0 +1,31 @@ +set(CRT_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +set(CRT_TESTSUITES) + +set(CRT_TEST_DEPS "") + +if(NOT COMPILER_RT_STANDALONE_BUILD AND COMPILER_RT_BUILD_CRT AND + COMPILER_RT_HAS_CRT) + list(APPEND CRT_TEST_DEPS crt) +endif() + +set(CRT_TEST_ARCH ${CRT_SUPPORTED_ARCH}) +if (COMPILER_RT_BUILD_CRT AND COMPILER_RT_HAS_CRT) + foreach(arch ${CRT_TEST_ARCH}) + set(CRT_TEST_TARGET_ARCH ${arch}) + string(TOLOWER "-${arch}-${OS_NAME}" CRT_TEST_CONFIG_SUFFIX) + get_test_cc_for_arch(${arch} CRT_TEST_TARGET_CC CRT_TEST_TARGET_CFLAGS) + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) + + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg) + list(APPEND CRT_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) + endforeach() +endif() + +add_lit_testsuite(check-crt "Running the CRT tests" + ${CRT_TESTSUITES} + DEPENDS ${CRT_TEST_DEPS}) +set_target_properties(check-crt PROPERTIES FOLDER "Compiler-RT Misc") Index: compiler-rt/test/crt/dso_handle.cpp =================================================================== --- /dev/null +++ compiler-rt/test/crt/dso_handle.cpp @@ -0,0 +1,33 @@ +// RUN: %clangxx -DCRT_SHARED -c %s -fPIC -o %tshared.o +// RUN: %clangxx -c %s -fPIC -o %t.o +// RUN: %clangxx -shared -o %t.so -nostartfiles -nostdlib -nodefaultlibs %crti %shared_crtbegin %tshared.o -lc -lm -lgcc_s %shared_crtend %crtn +// RUN: %clangxx -o %t -nostartfiles -nostdlib -nodefaultlibs %crt1 %crti %crtbegin %t.o -lc -lm %libgcc %t.so %crtend %crtn +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +// CHECK: 1 +// CHECK-NEXT: ~A() + +#ifdef CRT_SHARED +bool G; +void C() { + printf("%d\n", G); +} + +struct A { + A() { G = true; } + ~A() { + printf("~A()\n"); + } +}; + +A a; +#else +void C(); + +int main() { + C(); + return 0; +} +#endif Index: compiler-rt/test/crt/lit.cfg =================================================================== --- /dev/null +++ compiler-rt/test/crt/lit.cfg @@ -0,0 +1,77 @@ +# -*- Python -*- + +import os +import subprocess + +# Setup config name. +config.name = 'CRT' + config.name_suffix + +# Setup source root. +config.test_source_root = os.path.dirname(__file__) + + +def get_library_path(file): + cmd = subprocess.Popen([config.clang, + config.target_cflags, + '-print-file-name=%s' % file], + stdout=subprocess.PIPE, + env=config.environment) + if not cmd.stdout: + lit_config.fatal("Couldn't find the library path for '%s'" % file) + dir = cmd.stdout.read().strip() + if sys.platform in ['win32'] and execute_external: + # Don't pass dosish path separator to msys bash.exe. + dir = dir.replace('\\', '/') + # Ensure the result is an ascii string, across Python2.5+ - Python3. + return str(dir.decode('ascii')) + + +def get_libgcc_file_name(): + cmd = subprocess.Popen([config.clang, + config.target_cflags, + '-print-libgcc-file-name'], + stdout=subprocess.PIPE, + env=config.environment) + if not cmd.stdout: + lit_config.fatal("Couldn't find the library path for '%s'" % file) + dir = cmd.stdout.read().strip() + if sys.platform in ['win32'] and execute_external: + # Don't pass dosish path separator to msys bash.exe. + dir = dir.replace('\\', '/') + # Ensure the result is an ascii string, across Python2.5+ - Python3. + return str(dir.decode('ascii')) + + +def build_invocation(compile_flags): + return ' ' + ' '.join([config.clang] + compile_flags) + ' ' + + +# Setup substitutions. +config.substitutions.append( + ('%clang ', build_invocation([config.target_cflags]))) +config.substitutions.append( + ('%clangxx ', + build_invocation(config.cxx_mode_flags + [config.target_cflags]))) + +base_lib = os.path.join( + config.compiler_rt_libdir, "clang_rt.%%s-%s.o" % config.target_arch) +config.substitutions.append(('%crtbegin', base_lib % "crtbegin")) +config.substitutions.append(('%shared_crtbegin', base_lib % "crtbeginS")) +config.substitutions.append(('%crtend', base_lib % "crtend")) +config.substitutions.append(('%shared_crtend', base_lib % "crtendS")) + +config.substitutions.append( + ('%crt1', get_library_path('crt1.o'))) +config.substitutions.append( + ('%crti', get_library_path('crti.o'))) +config.substitutions.append( + ('%crtn', get_library_path('crtn.o'))) + +config.substitutions.append( + ('%libgcc', get_libgcc_file_name())) + +# Default test suffixes. +config.suffixes = ['.c', '.cc', '.cpp'] + +if config.host_os not in ['Linux']: + config.unsupported = True Index: compiler-rt/test/crt/lit.site.cfg.in =================================================================== --- /dev/null +++ compiler-rt/test/crt/lit.site.cfg.in @@ -0,0 +1,13 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# Tool-specific config options. +config.name_suffix = "@CRT_TEST_CONFIG_SUFFIX@" +config.crt_lit_source_dir = "@CRT_LIT_SOURCE_DIR@" +config.target_cflags = "@CRT_TEST_TARGET_CFLAGS@" +config.target_arch = "@CRT_TEST_TARGET_ARCH@" + +# Load common config for all compiler-rt lit tests +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") + +# Load tool-specific config that would do the real work. +lit_config.load_config(config, "@CRT_LIT_SOURCE_DIR@/lit.cfg")