Commit 684dac65 authored by steinbac's avatar steinbac

refactored the structure of the package to be more consistent

parent 4c720046
......@@ -27,12 +27,14 @@ Here is a minimal code example that tries to detect SSE4 at runtime:
#include <iostream>
#include "compass.hpp"
using namespace compass;
int main(int argc, char** argv){
if(compass::runtime::has(compass::feature::sse4()))
if(runtime::has(feature::sse4()))
std::cout << "SSE4 found!!\n";
else
std::cout << "this is an old machine!!\n";
std::cout << "This is an old machine. I hope I don't break anything.\n";
return 0;
......@@ -40,15 +42,18 @@ int main(int argc, char** argv){
```
## Help needed
This project is quite small, so here is your chance to boost open-source to the benefit of the entire C++ community.
- [ ] code review the model to extend compass to new compilers/platforms
- [ ] code review the model to extend compass to new features
- [ ] is thread-safety an issue of the current implementation
- [ ] contribute/check Intel compiler
- [ ] contribute for GPUs and nvcc
- [ ] contribute for OpenPower
- [ ] contribute for ARM
- [ ] code review the model to extend compass for new compilers/platforms/OSes
- [ ] code review the model to extend compass for new features
- [ ] is thread-safety an issue of the current implementation ?
- [ ] contribute for adding Intel compiler on x86
- [ ] contribute for GPUs (nvcc)
- [ ] contribute for OpenPower (gcc/at)
- [ ] contribute for ARM (gcc/clang)
## License
This project is licensed under the BSD 3-clause open source license. See (LICENSE)[LICENSE] for details.
#ifndef _COMPASS_HPP_
#define _COMPASS_HPP_
#include "detail/dispatch.hpp"
#include "detail/api.hpp"
#include <type_traits>
#include <cstdint>
#include <string>
#include <thread>
namespace compass {
namespace compiletime {
static const bool is_gnu(){
using current_toolchain_t = toolchain::type;
bool value = std::is_same<current_toolchain_t,gnu_tag>::value;
return value;
}
static const bool is_llvm(){
using current_toolchain_t = toolchain::type;
bool value = std::is_same<current_toolchain_t,llvm_tag>::value;
return value;
}
static const bool is_msvc(){
using current_toolchain_t = toolchain::type;
bool value = std::is_same<current_toolchain_t,msvc_tag>::value;
return value;
}
};
namespace runtime {
static bool works() {
using current_platform_t = ct::platform::type;
return detail::works(current_platform_t());
}
static std::string vendor() {
using current_platform_t = ct::platform::type;
return detail::vendor(current_platform_t());
}
static int ncores() {
return std::thread::hardware_concurrency();
}
template <typename feature_t>
static bool has(feature_t) {
using current_platform_t = ct::platform::type;
return detail::has(feature_t(),current_platform_t());
}
};//namespace runtime
};//namespace compass
#endif /* _COMPASS_H_ */
#ifndef COMPASS_API_H
#define COMPASS_API_H
#include "detail/dispatch.hpp"
#include "detail/definitions.hpp"
#include <type_traits>
#include <cstdint>
#include <string>
#include <thread>
namespace compass {
namespace runtime {
static bool works() {
using current_arch_t = ct::arch::type;
return detail::works(current_arch_t());
}
static std::string vendor() {
using current_arch_t = ct::arch::type;
return detail::vendor(current_arch_t());
}
static int ncores() {
return std::thread::hardware_concurrency();
}
template <typename feature_t>
static bool has(feature_t) {
using current_arch_t = ct::arch::type;
return detail::has(feature_t(),current_arch_t());
}
};//namespace runtime
} // compass
#endif /* API_H */
#ifndef DETAIL_DETECT_ARCHITECTURE_H
#define DETAIL_DETECT_ARCHITECTURE_H
//for reference see: https://sourceforge.net/p/predef/wiki/Architectures/
#define COMPASS_CT_ARCH_UNSUPPORTED
#if (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64))
#define COMPASS_CT_ARCH_X86
#define COMPASS_CT_ARCH_64BITS
#undef COMPASS_CT_ARCH_UNSUPPORTED
#endif
#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__M_I86) || defined(_M_IX86))
#define COMPASS_CT_ARCH_X86
#undef COMPASS_CT_ARCH_UNSUPPORTED
#endif
#if (defined(__powerpc64__) || defined(_ARCH_PPC64) || defined(__ppc64__))
#define COMPASS_CT_ARCH_POWER
#define COMPASS_CT_ARCH_64BITS
#undef COMPASS_CT_ARCH_UNSUPPORTED
#endif
#if (defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__PPC__) || defined(__ppc__))
#define COMPASS_CT_ARCH_POWER
#undef COMPASS_CT_ARCH_UNSUPPORTED
#endif
#include <climits> //for CHAR_BIT
namespace compass {
namespace compiletime {
//architectures
struct unsupported_tag {};
struct x86_tag {};
struct power_tag {};
struct arch {
#ifdef COMPASS_CT_ARCH_X86
typedef x86_tag type;
#endif
#ifdef COMPASS_CT_ARCH_POWER
typedef power_tag type;
#endif
#ifdef COMPASS_CT_ARCH_UNSUPPORTED
typedef unsupported_tag type;
#endif
//32 or 64bit?
const static int bitness = sizeof(void*)*CHAR_BIT;
};
} // compiletime
} // compass
#endif /* DETAIL_DETECT_ARCHITECTURE_H */
#ifndef DETAIL_DETECT_COMPILER_H
#define DETAIL_DETECT_COMPILER_H
//for reference see: https://sourceforge.net/p/predef/wiki/Compilers/
#ifdef __GNUC__
#define COMPASS_CT_COMP_GCC
#endif
#ifdef __clang__
#define COMPASS_CT_COMP_CLANG
#endif
#if (defined(_MSC_VER) || defined(_MSC_FULL_VER) || defined(_MSC_BUILD))
#define COMPASS_CT_COMP_MSVC
#endif
#ifdef __INTEL_COMPILER
#define COMPASS_CT_COMP_INTEL
#endif
//TODO: if needed, this is the header where the compiler version could be inferred
namespace compass {
namespace compiletime {
struct gnu_tag {};
struct llvm_tag {};
struct msvc_tag {};
struct intel_tag {};
struct toolchain {
#ifdef COMPASS_CT_COMP_CLANG
typedef llvm_tag type;
#endif
#ifdef COMPASS_CT_COMP_GCC
typedef gnu_tag type;
#endif
#ifdef COMPASS_CT_COMP_MSVC
typedef msvc_tag type;
#endif
#ifdef COMPASS_CT_COMP_INTEL
typedef intel_tag type;
#endif
};
static const bool is_gnu(){
using current_toolchain_t = toolchain::type;
bool value = std::is_same<current_toolchain_t,gnu_tag>::value;
return value;
}
static const bool is_llvm(){
using current_toolchain_t = toolchain::type;
bool value = std::is_same<current_toolchain_t,llvm_tag>::value;
return value;
}
static const bool is_msvc(){
using current_toolchain_t = toolchain::type;
bool value = std::is_same<current_toolchain_t,msvc_tag>::value;
return value;
}
static const bool is_intel(){
using current_toolchain_t = toolchain::type;
bool value = std::is_same<current_toolchain_t,intel_tag>::value;
return value;
}
} // compiletime
} // compass
#endif /* DETAIL_DETECT_COMPILER_H */
#ifndef DETAIL_DETECT_OS_H
#define DETAIL_DETECT_OS_H
//for reference see: https://sourceforge.net/p/predef/wiki/OperatingSystems/
#if (defined(__linux__) || defined(__gnu_linux__))
#define COMPASS_CT_OS_LINUX
#endif
#if (defined(__APPLE__) && defined(__MACH__))
#define COMPASS_CT_OS_MACOS
#endif
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__))
#define COMPASS_CT_OS_WINDOWS
#endif
namespace compass {
namespace compiletime {
struct linux_tag {};
struct macos_tag {};
struct windows_tag {};
struct platform {
#ifdef COMPASS_CT_OS_LINUX
typedef linux_tag type;
#endif
#ifdef COMPASS_CT_OS_MACOS
typedef macos_tag type;
#endif
#ifdef COMPASS_CT_OS_WINDOWS
typedef windows_tag type;
#endif
};
} // compiletime
} // compass
#endif /* DETAIL_DETECT_OS_H */
......@@ -2,27 +2,27 @@
#define COMPASS_CT_PREPROCESSOR_IMPL_H_
#ifndef WIN32
#if defined __SSE2__ && defined __SSE2_MATH__
#define COMPASS_HAS_SSE2
#endif
#if defined __SSE2__ && defined __SSE2_MATH__
#define COMPASS_HAS_SSE2
#endif
#else
#if _M_IX86_FP >= 2
#define COMPASS_HAS_SSE2
#endif
#if _M_IX86_FP >= 2
#define COMPASS_HAS_SSE2
#endif
#endif
#ifndef WIN32
#if defined __SSE3__ && defined __SSSE3__
#define COMPASS_HAS_SSE3
#endif
#if defined __SSE3__ && defined __SSSE3__
#define COMPASS_HAS_SSE3
#endif
#if defined __SSE4_2__ && defined __SSE4_1__
#define COMPASS_HAS_SSE4
#endif
#if defined __SSE4_2__ && defined __SSE4_1__
#define COMPASS_HAS_SSE4
#endif
#else
//TODO: try to warn users on Windows that we are enabling SSE3 + SSE4 upon assumption here
#define COMPASS_HAS_SSE3
#define COMPASS_HAS_SSE4
//TODO: try to warn users on Windows that we are enabling SSE3 + SSE4 upon assumption here
#define COMPASS_HAS_SSE3
#define COMPASS_HAS_SSE4
#endif
#include "../tags.hpp"
......@@ -39,38 +39,38 @@ namespace compass {
template<>
struct has<feature::sse2>{
static const bool enabled=
static const bool enabled=
#ifdef COMPASS_CT_HAS_SSE2
true;
true;
#else
false;
false;
#endif
};
template<>
struct has<feature::sse3>{
static const bool enabled=
static const bool enabled=
#ifdef COMPASS_CT_HAS_SSE3
true;
true;
#else
false;
false;
#endif
};
template<>
struct has<feature::sse4>{
static const bool enabled=
static const bool enabled=
#ifdef COMPASS_CT_HAS_SSE4
true;
true;
#else
false;
false;
#endif
};
};
};
#endif /* COMPASS_CT_PREPROCESSOR_IMPL_H_ */
#ifndef COMPASS_DEFINITIONS_H
#define COMPASS_DEFINITIONS_H
namespace compass {
namespace compiletime {
//cpuid register locations
static const int eax = 0;
static const int ebx = 1;
static const int ecx = 2;
static const int edx = 3;
};
namespace runtime {
//empty for now
};
namespace rt = runtime;
namespace ct = compiletime;
};
#endif /* DEFINITIONS_H */
#ifndef COMPASS_DETAIL_H_
#define COMPASS_DETAIL_H_
#ifndef COMPASS_DISPATCH_H_
#define COMPASS_DISPATCH_H_
#include "detail/ct/detect_os.hpp"
#include "detail/ct/detect_compiler.hpp"
#include "detail/ct/detect_arch.hpp"
#include "tags.hpp"
#include "rt/unsupported_impl.hpp"
//compiletime code
#if defined(__linux__)
#if (defined(__powerpc64__) || defined(__powerpc__))
#include "ct/power_impl.hpp"
#else
#if defined(__clang__)
#include "ct/llvm_impl.hpp"
#else if defined(__GNUC__)
#include "ct/gnu_impl.hpp"
#endif
#endif
#endif
#else //not linux
#ifdef __APPLE__
#include "ct/llvm_impl.hpp"
#else //not __APPLE__
#ifdef _MSC_BUILD
#include "ct/msvc_impl.hpp"
#endif
#endif
#endif
#include "ct/preprocessor_impl.hpp"
//runtime code
#if defined(__x86_64) || defined(__x86_64__) || defined(__x86)
#ifdef COMPASS_CT_ARCH_X86
#include "rt/x86_impl.hpp"
#endif
#if (defined(__powerpc64__) || defined(__powerpc__))
#ifdef COMPASS_CT_ARCH_POWER
#include "rt/power_impl.hpp"
#else
#endif
#endif /* COMPASS_DETAIL_H_ */
#endif /* COMPASS_DISPATCH_H_ */
#ifndef COMPASS_RT_UNSUPPORTED_IMPL_H_
#define COMPASS_RT_UNSUPPORTED_IMPL_H_
#include "detail/ct/detect_os.hpp"
#include "detail/ct/detect_compiler.hpp"
#include "detail/ct/detect_arch.hpp"
#include "detail/definitions.hpp"
#include "detail/tags.hpp"
#include <iostream>
#include <string>
#include <bitset>
namespace compass {
namespace runtime {
namespace detail {
static bool works(ct::unsupported_tag) {
return false;
}
static std::string vendor(ct::unsupported_tag) {
std::string vendor_name = "";
return vendor_name;
}
static bool has(feature::sse , ct::unsupported_tag){
return false;
}
static bool has(feature::sse2 , ct::unsupported_tag){
return false;
}
static bool has(feature::sse3 , ct::unsupported_tag){
return false;
}
static bool has(feature::sse4 , ct::unsupported_tag){
return false;
}
static bool has(feature::avx , ct::unsupported_tag){
return false;
}
static bool has(feature::avx2 , ct::unsupported_tag){
return false;
}
};
};
};
#endif /* COMPASS_RT_UNSUPPORTED_IMPL_H_ */
#ifndef COMPASS_CT_GNU_IMPL_H_
#define COMPASS_CT_GNU_IMPL_H_
#ifndef COMPASS_RT_X86_GNU_CPUID_H_
#include "../tags.hpp"
#include "detail/ct/detect_compiler.hpp"
#ifdef COMPASS_CT_COMP_GCC
#define COMPASS_RT_X86_GNU_CPUID_H_
#include "cpuid.h"
#include <array>
#include <bitset>
#include <cstdint>
#include "cpuid.h"
#include "detail/tags.hpp"
#include "detail/definitions.hpp"
namespace compass {
namespace compiletime {
namespace runtime {
static std::array<std::bitset<32>,4> cpuid(std::uint32_t level,
......@@ -23,10 +30,10 @@ namespace compass {
std::uint32_t regs[4] = {in_eax,in_ebx,in_ecx,in_edx};
int cpuid_rvalue = __get_cpuid(level,
&regs[eax],
&regs[ebx],
&regs[ecx],
&regs[edx]
&regs[ct::eax],
&regs[ct::ebx],
&regs[ct::ecx],
&regs[ct::edx]
);
static std::array<std::bitset<32>,4> value;
......@@ -36,10 +43,10 @@ namespace compass {
}
value[eax] = regs[eax];
value[ebx] = regs[ebx];
value[ecx] = regs[ecx];
value[edx] = regs[edx];
value[ct::eax] = regs[ct::eax];
value[ct::ebx] = regs[ct::ebx];
value[ct::ecx] = regs[ct::ecx];
value[ct::edx] = regs[ct::edx];
return value;
......@@ -79,4 +86,5 @@ namespace compass {
};
};
#endif /* COMPASS_CT_COMP_GCC */
#endif /* COMPASS_CT_GNU_IMPL_H_ */
#ifndef COMPASS_CT_LLVM_IMPL_H_
#define COMPASS_CT_LLVM_IMPL_H_
#ifndef COMPASS_RT_X86_LLVM_CPUID_H_
#define COMPASS_RT_X86_LLVM_CPUID_H_
#include "detail/ct/detect_compiler.hpp"
#ifdef COMPASS_CT_COMP_CLANG
#include "cpuid.h"
......@@ -7,32 +11,34 @@
#include <bitset>
#include <cstdint>
#include "../compass_tags.hpp"
#include "detail/tags.hpp"
namespace compass {
namespace compiletime {
namespace runtime {
static std::array<std::bitset<32>,4> cpuid(std::uint32_t level,
std::uint32_t in_eax = 0,
std::uint32_t in_ebx = 0,
std::uint32_t in_ecx = 0,
std::uint32_t in_edx = 0){
std::uint32_t in_eax = 0,
std::uint32_t in_ebx = 0,
std::uint32_t in_ecx = 0,
std::uint32_t in_edx = 0){
std::uint32_t regs[4] = {in_eax,in_ebx,in_ecx,in_edx};
int cpuid_rvalue = __get_cpuid(level,
&regs[eax],
&regs[ebx],
&regs[ecx],
&regs[edx]
);
&regs[eax],
&regs[ebx],
&regs[ecx],
&regs[edx]
);
static std::array<std::bitset<32>,4> value;
if(cpuid_rvalue < 1){