Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,14 @@ jobs:
cxx_flags: -ftrapv
cxx_standard: 23

- name: Header only (GCC-14 C++23)
extra_deps: g++-14
c_compiler: gcc-14
cxx_compiler: g++-14
cxx_flags: -ftrapv
cxx_standard: 23
extra_cmake_flags: -DHWY_CMAKE_HEADER_ONLY=ON

steps:
- name: Harden Runner
uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
Expand Down
2 changes: 1 addition & 1 deletion BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ CLANG_GCC_COPTS = [
"-Wextra-semi",
"-Wunreachable-code",
"-Wshadow",
"-Wmissing-declarations",
# "-Wmissing-declarations",
]

# Warnings supported by Clang and Clang-cl
Expand Down
103 changes: 72 additions & 31 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ set(HWY_SOURCES
hwy/x86_cpuid.h
)


if (NOT HWY_CMAKE_HEADER_ONLY)
list(APPEND HWY_SOURCES
hwy/abort.cc
Expand Down Expand Up @@ -500,10 +501,6 @@ if (HWY_DISABLE_FUTEX)
list(APPEND HWY_FLAGS -DHWY_DISABLE_FUTEX)
endif()

if (HWY_CMAKE_HEADER_ONLY)
list(APPEND HWY_FLAGS -DHWY_HEADER_ONLY)
endif()

include(CheckIncludeFile)
check_include_file(sys/auxv.h HAVE_SYS_AUXV_H)
check_include_file(asm/hwcap.h HAVE_ASM_HWCAP_H)
Expand Down Expand Up @@ -531,33 +528,77 @@ else()
set(DLLEXPORT_TO_DEFINE "HWY_STATIC_DEFINE")
endif()

add_library(hwy ${HWY_LIBRARY_TYPE} ${HWY_SOURCES})
if(NOT HAVE_SYS_AUXV_H)
target_compile_definitions(hwy PUBLIC TOOLCHAIN_MISS_SYS_AUXV_H)
endif()
if(NOT HAVE_ASM_HWCAP_H)
target_compile_definitions(hwy PUBLIC TOOLCHAIN_MISS_ASM_HWCAP_H)
endif()
target_compile_definitions(hwy PUBLIC "${DLLEXPORT_TO_DEFINE}")
target_compile_options(hwy PRIVATE ${HWY_FLAGS})
set_property(TARGET hwy PROPERTY POSITION_INDEPENDENT_CODE ON)
set_target_properties(hwy PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION})
target_include_directories(hwy PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_features(hwy PUBLIC cxx_std_11)
if (NOT HWY_CXX_STD_TGT_COMPILE_FEATURE STREQUAL "cxx_std_11")
target_compile_features(hwy PRIVATE ${HWY_CXX_STD_TGT_COMPILE_FEATURE})
endif()
set_target_properties(hwy PROPERTIES
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/hwy/hwy.version)
# For GCC __atomic_store_8, see #887
target_link_libraries(hwy PRIVATE ${ATOMICS_LIBRARIES})
# not supported by MSVC/Clang, safe to skip (we use DLLEXPORT annotations)
if(UNIX AND NOT APPLE)
set_property(TARGET hwy APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/hwy/hwy.version")
endif()
if (NOT HWY_CMAKE_HEADER_ONLY)
add_library(hwy ${HWY_LIBRARY_TYPE} ${HWY_SOURCES})
if (NOT HAVE_SYS_AUXV_H)
target_compile_definitions(hwy PUBLIC TOOLCHAIN_MISS_SYS_AUXV_H)
endif ()
if (NOT HAVE_ASM_HWCAP_H)
target_compile_definitions(hwy PUBLIC TOOLCHAIN_MISS_ASM_HWCAP_H)
endif ()
target_compile_definitions(hwy PUBLIC "${DLLEXPORT_TO_DEFINE}")
target_compile_options(hwy PRIVATE ${HWY_FLAGS})
set_property(TARGET hwy PROPERTY POSITION_INDEPENDENT_CODE ON)
set_target_properties(hwy PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION})
target_include_directories(hwy PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_features(hwy PUBLIC cxx_std_11)
if (NOT HWY_CXX_STD_TGT_COMPILE_FEATURE STREQUAL "cxx_std_11")
target_compile_features(hwy PRIVATE ${HWY_CXX_STD_TGT_COMPILE_FEATURE})
endif ()
set_target_properties(hwy PROPERTIES
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/hwy/hwy.version)
# For GCC __atomic_store_8, see #887
target_link_libraries(hwy PRIVATE ${ATOMICS_LIBRARIES})
# not supported by MSVC/Clang, safe to skip (we use DLLEXPORT annotations)
if (UNIX AND NOT APPLE)
set_property(TARGET hwy APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/hwy/hwy.version")
endif ()
else()
# to uncomment this, finally
# add_library(hwy INTERFACE)
# target_compile_definitions(hwy INTERFACE -DHWY_HEADER_ONLY)
# if (HWY_WARNINGS_ARE_ERRORS)
# target_include_directories(hwy INTERFACE
# $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
# $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
# else()
# target_include_directories(hwy SYSTEM INTERFACE
# $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
# $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
# endif ()
# target_link_libraries(hwy INTERFACE ${ATOMICS_LIBRARIES})

add_library(hwy STATIC)
target_compile_features(hwy PUBLIC cxx_std_11)
if (NOT HWY_CXX_STD_TGT_COMPILE_FEATURE STREQUAL "cxx_std_11")
target_compile_features(hwy PRIVATE ${HWY_CXX_STD_TGT_COMPILE_FEATURE})
endif ()
target_compile_definitions(hwy PUBLIC -DHWY_HEADER_ONLY)
if (HWY_WARNINGS_ARE_ERRORS)
target_include_directories(hwy PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
else ()
target_include_directories(hwy SYSTEM PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
endif ()
target_link_libraries(hwy PRIVATE ${ATOMICS_LIBRARIES})
target_sources(hwy PRIVATE
# hwy/abort.cc
# hwy/aligned_allocator.cc
# hwy/nanobenchmark.cc
hwy/per_target.cc
# hwy/perf_counters.cc
# hwy/print.cc
# hwy/profiler.cc
# hwy/targets.cc
# hwy/timer.cc
)
endif ()

if (HWY_ENABLE_CONTRIB)
add_library(hwy_contrib ${HWY_LIBRARY_TYPE} ${HWY_CONTRIB_SOURCES})
Expand Down
34 changes: 18 additions & 16 deletions hwy/abort.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@

namespace hwy {

namespace {
namespace detail {

std::atomic<WarnFunc>& AtomicWarnFunc() {
HWY_HEADER_ONLY_FUN std::atomic<WarnFunc>& AtomicWarnFunc() {
static std::atomic<WarnFunc> func;
return func;
}

std::atomic<AbortFunc>& AtomicAbortFunc() {
HWY_HEADER_ONLY_FUN std::atomic<AbortFunc>& AtomicAbortFunc() {
static std::atomic<AbortFunc> func;
return func;
}

std::string GetBaseName(std::string const& file_name) {
HWY_HEADER_ONLY_FUN std::string GetBaseName(std::string const& file_name) {
auto last_slash = file_name.find_last_of("/\\");
return file_name.substr(last_slash + 1);
}
Expand All @@ -43,55 +43,57 @@ std::string GetBaseName(std::string const& file_name) {
// is required to safely implement `SetWarnFunc`. As a workaround, we store a
// copy here, update it when called, and return a reference to the copy. This
// has the added benefit of protecting the actual pointer from modification.
HWY_DLLEXPORT WarnFunc& GetWarnFunc() {
HWY_HEADER_ONLY_FUN HWY_DLLEXPORT WarnFunc& GetWarnFunc() {
static WarnFunc func;
func = AtomicWarnFunc().load();
func = detail::AtomicWarnFunc().load();
return func;
}

HWY_DLLEXPORT AbortFunc& GetAbortFunc() {
HWY_HEADER_ONLY_FUN HWY_DLLEXPORT AbortFunc& GetAbortFunc() {
static AbortFunc func;
func = AtomicAbortFunc().load();
func = detail::AtomicAbortFunc().load();
return func;
}

HWY_HEADER_ONLY_FUN
HWY_DLLEXPORT WarnFunc SetWarnFunc(WarnFunc func) {
return AtomicWarnFunc().exchange(func);
return detail::AtomicWarnFunc().exchange(func);
}

HWY_HEADER_ONLY_FUN
HWY_DLLEXPORT AbortFunc SetAbortFunc(AbortFunc func) {
return AtomicAbortFunc().exchange(func);
return detail::AtomicAbortFunc().exchange(func);
}

HWY_DLLEXPORT void HWY_FORMAT(3, 4)
HWY_HEADER_ONLY_FUN HWY_DLLEXPORT void HWY_FORMAT(3, 4)
Warn(const char* file, int line, const char* format, ...) {
char buf[800];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);

WarnFunc handler = AtomicWarnFunc().load();
WarnFunc handler = detail::AtomicWarnFunc().load();
if (handler != nullptr) {
handler(file, line, buf);
} else {
fprintf(stderr, "Warn at %s:%d: %s\n", GetBaseName(file).data(), line, buf);
fprintf(stderr, "Warn at %s:%d: %s\n", detail::GetBaseName(file).data(), line, buf);
}
}

HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4)
HWY_HEADER_ONLY_FUN HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4)
Abort(const char* file, int line, const char* format, ...) {
char buf[800];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);

AbortFunc handler = AtomicAbortFunc().load();
AbortFunc handler = detail::AtomicAbortFunc().load();
if (handler != nullptr) {
handler(file, line, buf);
} else {
fprintf(stderr, "Abort at %s:%d: %s\n", GetBaseName(file).data(), line,
fprintf(stderr, "Abort at %s:%d: %s\n", detail::GetBaseName(file).data(), line,
buf);
}

Expand Down
9 changes: 8 additions & 1 deletion hwy/aligned_allocator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "hwy/base.h"

namespace hwy {
namespace {
namespace detail {

#if HWY_ARCH_RISCV && defined(__riscv_v_intrinsic) && \
__riscv_v_intrinsic >= 11000
Expand Down Expand Up @@ -54,6 +54,7 @@ struct AllocationHeader {
#pragma pack(pop)

// Returns a 'random' (cyclical) offset for AllocateAlignedBytes.
HWY_HEADER_ONLY_FUN
size_t NextAlignedOffset() {
static std::atomic<size_t> next{0};
static_assert(kAlias % kAlignment == 0, "kAlias must be a multiple");
Expand All @@ -66,8 +67,10 @@ size_t NextAlignedOffset() {

} // namespace

HWY_HEADER_ONLY_FUN
HWY_DLLEXPORT void* AllocateAlignedBytes(const size_t payload_size,
AllocPtr alloc_ptr, void* opaque_ptr) {
using namespace hwy::detail;
HWY_ASSERT(payload_size != 0); // likely a bug in caller
if (payload_size >= std::numeric_limits<size_t>::max() / 2) {
HWY_DASSERT(false && "payload_size too large");
Expand Down Expand Up @@ -114,8 +117,10 @@ HWY_DLLEXPORT void* AllocateAlignedBytes(const size_t payload_size,
return HWY_ASSUME_ALIGNED(reinterpret_cast<void*>(payload), kAlignment);
}

HWY_HEADER_ONLY_FUN
HWY_DLLEXPORT void FreeAlignedBytes(const void* aligned_pointer,
FreePtr free_ptr, void* opaque_ptr) {
using namespace hwy::detail;
if (aligned_pointer == nullptr) return;

const uintptr_t payload = reinterpret_cast<uintptr_t>(aligned_pointer);
Expand All @@ -131,10 +136,12 @@ HWY_DLLEXPORT void FreeAlignedBytes(const void* aligned_pointer,
}

// static
HWY_HEADER_ONLY_FUN
HWY_DLLEXPORT void AlignedDeleter::DeleteAlignedArray(void* aligned_pointer,
FreePtr free_ptr,
void* opaque_ptr,
ArrayDeleter deleter) {
using namespace hwy::detail;
if (aligned_pointer == nullptr) return;

const uintptr_t payload = reinterpret_cast<uintptr_t>(aligned_pointer);
Expand Down
4 changes: 4 additions & 0 deletions hwy/aligned_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,4 +424,8 @@ class AlignedNDArray {
};

} // namespace hwy

#ifdef HWY_HEADER_ONLY
#include "hwy/aligned_allocator.cc"
#endif // HWY_HEADER_ONLY
#endif // HIGHWAY_HWY_ALIGNED_ALLOCATOR_H_
41 changes: 7 additions & 34 deletions hwy/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#if defined(HWY_HEADER_ONLY)
#include <stdarg.h>
#include <stdio.h>

#define HWY_HEADER_ONLY_FUN inline
#else
#define HWY_HEADER_ONLY_FUN
#endif

#if !defined(HWY_NO_LIBCXX)
Expand Down Expand Up @@ -284,38 +288,6 @@ namespace hwy {
//------------------------------------------------------------------------------
// Abort / Warn

#if defined(HWY_HEADER_ONLY)
HWY_DLLEXPORT inline void HWY_FORMAT(3, 4)
Warn(const char* file, int line, const char* format, ...) {
char buf[800];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);

fprintf(stderr, "Warn at %s:%d: %s\n", file, line, buf);
}

HWY_DLLEXPORT HWY_NORETURN inline void HWY_FORMAT(3, 4)
Abort(const char* file, int line, const char* format, ...) {
char buf[800];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);

fprintf(stderr, "Abort at %s:%d: %s\n", file, line, buf);

fflush(stderr);

// Now terminate the program:
#if HWY_ARCH_RISCV
exit(1); // trap/abort just freeze Spike.
#else
abort(); // Compile error without this due to HWY_NORETURN.
#endif
}
#else // !HWY_HEADER_ONLY
// Interfaces for custom Warn/Abort handlers.
typedef void (*WarnFunc)(const char* file, int line, const char* message);

Expand Down Expand Up @@ -350,8 +322,6 @@ HWY_DLLEXPORT void HWY_FORMAT(3, 4)
HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4)
Abort(const char* file, int line, const char* format, ...);

#endif // HWY_HEADER_ONLY

#define HWY_WARN(format, ...) \
::hwy::Warn(__FILE__, __LINE__, format, ##__VA_ARGS__)

Expand Down Expand Up @@ -3290,4 +3260,7 @@ HWY_API void PreventElision(T&& output) {

} // namespace hwy

#if defined(HWY_HEADER_ONLY)
#include "hwy/abort.cc"
#endif // HWY_HEADER_ONLY
#endif // HIGHWAY_HWY_BASE_H_
Loading
Loading