「x86_64h」是什么?

| macOS, clang

老版的macOS可以看到系统自带的libBLAS支持三种CPU架构:

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.13.6
BuildVersion:   17G14042

$ file /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib: Mach-O universal binary with 3 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [x86_64h]
/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib (for architecture x86_64):      Mach-O 64-bit dynamically linked shared library x86_64
/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib (for architecture i386):        Mach-O dynamically linked shared library i386
/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib (for architecture x86_64h):     Mach-O 64-bit dynamically linked shared library x86_64h

「x86_64h」是什么玩意儿?经过一番查找,果然是苹果自己发明的一个代号:x86_64h=x86_64 Haswell。这个「架构」在clang中自动开启相应编译选项的配套设定,即-march=core-avx2。clang的实现如下:

if (StringRef(A->getValue()) != "native") {
if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
    return "core-avx2";
return A->getValue();
}

if (Triple.getArchName() == "x86_64h") {
    // x86_64h implies quite a few of the more modern subtarget features
    // for Haswell class CPUs, but not all of them. Opt-out of a few.
    Features.push_back("-rdrnd");
    Features.push_back("-aes");
    Features.push_back("-pclmul");
    Features.push_back("-rtm");
    Features.push_back("-hle");
    Features.push_back("-fsgsbase");
}

Apple Silicon的Rosetta 2不支持AVX,也不支持x86_64h,如果通过arch命令强制执行,结果报错:

$ arch -x86_64h ./test
arch: posix_spawnp: ./test: Bad CPU type in executable

这样x86_64h就处于一个尴尬境地,老机器、新机器都不支持,兼容性很差,目前正在销售的Mac只有Mac Pro能运行。苹果这种自己创造CPU指令集代号的行为我们似曾相识,那就是所谓的「armv7s」、「armv7k」、「arm64e」等。这样的做法在其他操作系统应该很少出现。例如Linux不会在ELF文件上打个记号,表明支持x86_64的哪一代,并在运行前检测本机CPU的型号是否比可执行文件中标记的版本更新。使用高级指令集的程序一般是通过运行时检测CPUID的机制保证选择正确、高效的程序实现。


参考链接

Support Building for Mac Catalyst (x86_64h-apple-ios13.x-macabi)

RemObjects Elements - Cocoa - CPU Architectures