Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
104 changes: 73 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,78 @@ 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_definitions(hwy PUBLIC -DHWY_HEADER_ONLY=0)
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=1)
# 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=1)
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_FUNC std::atomic<WarnFunc>& AtomicWarnFunc() {
static std::atomic<WarnFunc> func;
return func;
}

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

std::string GetBaseName(std::string const& file_name) {
HWY_HEADER_ONLY_FUNC 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_FUNC HWY_DLLEXPORT WarnFunc& GetWarnFunc() {
static WarnFunc func;
func = AtomicWarnFunc().load();
func = detail::AtomicWarnFunc().load();
return func;
}

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

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

HWY_HEADER_ONLY_FUNC
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_FUNC 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_FUNC 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_FUNC
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_FUNC
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_FUNC
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_FUNC
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

#if HWY_HEADER_ONLY
#include "hwy/aligned_allocator.cc"
#endif // HWY_HEADER_ONLY
#endif // HIGHWAY_HWY_ALIGNED_ALLOCATOR_H_
2 changes: 1 addition & 1 deletion hwy/auto_tune.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

// configuration to allow auto_tune to use std::sort instead of VQSort
// (also enabled in header only mode).
#if defined(HWY_HEADER_ONLY)
#if HWY_HEADER_ONLY
#define HWY_AUTOTUNE_STDSORT
#endif

Expand Down
43 changes: 8 additions & 35 deletions hwy/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
// IWYU pragma: begin_exports
#include <stddef.h>
#include <stdint.h>
#if defined(HWY_HEADER_ONLY)
#if HWY_HEADER_ONLY
#include <stdarg.h>
#include <stdio.h>

#define HWY_HEADER_ONLY_FUNC inline
#else
#define HWY_HEADER_ONLY_FUNC
#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 HWY_HEADER_ONLY
#include "hwy/abort.cc"
#endif // HWY_HEADER_ONLY
#endif // HIGHWAY_HWY_BASE_H_
Loading
Loading