From b4279d95281f815d43ec3d28fae8d0b6b0d8f748 Mon Sep 17 00:00:00 2001 From: Francis Visoiu Mistrih Date: Tue, 18 Feb 2020 17:13:47 -0800 Subject: [PATCH] [LTO][Legacy] Add new API to query Mach-O CPU (sub)type Tools working with object files on Darwin (e.g. lipo) may need to know properties like the CPU type and subtype of a bitcode file. The logic of converting a triple to a Mach-O CPU_(SUB_)TYPE should be provided by LLVM instead of relying on tools to re-implement it. Differential Revision: https://reviews.llvm.org/D75067 --- docs/LinkTimeOptimization.rst | 6 ++++++ include/llvm-c/lto.h | 17 ++++++++++++++- include/llvm/LTO/legacy/LTOModule.h | 4 ++++ lib/LTO/LTOModule.cpp | 9 ++++++++ test/LTO/X86/print-macho-cpu.ll | 8 +++++++ test/tools/llvm-lto/error.ll | 3 +++ tools/llvm-lto/llvm-lto.cpp | 33 +++++++++++++++++++++++++++++ tools/lto/lto.cpp | 21 ++++++++++++++++++ tools/lto/lto.exports | 1 + 9 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 test/LTO/X86/print-macho-cpu.ll diff --git a/docs/LinkTimeOptimization.rst b/docs/LinkTimeOptimization.rst index 010a7881623..9e0c2cc9f62 100644 --- a/docs/LinkTimeOptimization.rst +++ b/docs/LinkTimeOptimization.rst @@ -249,6 +249,12 @@ symbols and getting the name and attributes of each symbol via: The attributes of a symbol include the alignment, visibility, and kind. +Tools working with object files on Darwin (e.g. lipo) may need to know properties like the CPU type: + +.. code-block:: c + + lto_module_get_macho_cputype(lto_module_t mod, unsigned int *out_cputype, unsigned int *out_cpusubtype) + ``lto_code_gen_t`` ------------------ diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 97a8f482332..4dbc77f294c 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -46,7 +46,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 26 +#define LTO_API_VERSION 27 /** * \since prior to LTO_API_VERSION=3 @@ -297,6 +297,21 @@ lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index); extern const char* lto_module_get_linkeropts(lto_module_t mod); +/** + * If targeting mach-o on darwin, this function gets the CPU type and subtype + * that will end up being encoded in the mach-o header. These are the values + * that can be found in mach/machine.h. + * + * \p out_cputype and \p out_cpusubtype must be non-NULL. + * + * Returns true on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=27 + */ +extern lto_bool_t lto_module_get_macho_cputype(lto_module_t mod, + unsigned int *out_cputype, + unsigned int *out_cpusubtype); + /** * Diagnostic severity. * diff --git a/include/llvm/LTO/legacy/LTOModule.h b/include/llvm/LTO/legacy/LTOModule.h index 84b9b8c0294..998a4557dd2 100644 --- a/include/llvm/LTO/legacy/LTOModule.h +++ b/include/llvm/LTO/legacy/LTOModule.h @@ -165,6 +165,10 @@ public: static const char *getDependentLibrary(lto::InputFile *input, size_t index, size_t *size); + Expected getMachOCPUType() const; + + Expected getMachOCPUSubType() const; + private: /// Parse metadata from the module // FIXME: it only parses "llvm.linker.options" metadata at the moment diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp index 587b332e706..0d37e919ff5 100644 --- a/lib/LTO/LTOModule.cpp +++ b/lib/LTO/LTOModule.cpp @@ -28,6 +28,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -676,3 +677,11 @@ const char *LTOModule::getDependentLibrary(lto::InputFile *input, size_t index, *size = S.size(); return S.data(); } + +Expected LTOModule::getMachOCPUType() const { + return MachO::getCPUType(Triple(Mod->getTargetTriple())); +} + +Expected LTOModule::getMachOCPUSubType() const { + return MachO::getCPUSubType(Triple(Mod->getTargetTriple())); +} diff --git a/test/LTO/X86/print-macho-cpu.ll b/test/LTO/X86/print-macho-cpu.ll new file mode 100644 index 00000000000..36a209d06eb --- /dev/null +++ b/test/LTO/X86/print-macho-cpu.ll @@ -0,0 +1,8 @@ +; RUN: rm -rf %t && mkdir -p %t +; RUN: llvm-as -o %t/1.bc %s +; RUN: llvm-lto -print-macho-cpu-only %t/1.bc | FileCheck %s + +target triple = "x86_64-apple-darwin" +; CHECK: 1.bc: +; CHECK-NEXT: cputype: 16777223 +; CHECK-NEXT: cpusubtype: 3 diff --git a/test/tools/llvm-lto/error.ll b/test/tools/llvm-lto/error.ll index c4c31d05aba..e1f9e8813ab 100644 --- a/test/tools/llvm-lto/error.ll +++ b/test/tools/llvm-lto/error.ll @@ -7,5 +7,8 @@ ; RUN: not llvm-lto --list-dependent-libraries-only %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-LIBS ; CHECK-LIBS: llvm-lto: {{.*}}/Inputs/empty.bc: Could not read LTO input file: The file was not recognized as a valid object file +; RUN: not llvm-lto --print-macho-cpu-only %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-MACHO +; CHECK-MACHO: llvm-lto: error: The file was not recognized as a valid object file + ; RUN: not llvm-lto --thinlto %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-THIN ; CHECK-THIN: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': file too small to contain bitcode header diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index 12851799f33..af3fa0acc39 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -223,6 +223,10 @@ static cl::opt CheckHasObjC( "check-for-objc", cl::init(false), cl::desc("Only check if the module has objective-C defined in it")); +static cl::opt PrintMachOCPUOnly( + "print-macho-cpu-only", cl::init(false), + cl::desc("Instead of running LTO, print the mach-o cpu in each IR file")); + namespace { struct ModuleInfo { @@ -404,6 +408,30 @@ static void listDependentLibraries() { } } +static void printMachOCPUOnly() { + LLVMContext Context; + Context.setDiagnosticHandler(std::make_unique(), + true); + TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); + for (auto &Filename : InputFilenames) { + ErrorOr> ModuleOrErr = + LTOModule::createFromFile(Context, Filename, Options); + if (!ModuleOrErr) + error(ModuleOrErr, "llvm-lto: "); + + Expected CPUType = (*ModuleOrErr)->getMachOCPUType(); + Expected CPUSubType = (*ModuleOrErr)->getMachOCPUSubType(); + if (!CPUType) + error("Error while printing mach-o cputype: " + + toString(CPUType.takeError())); + if (!CPUSubType) + error("Error while printing mach-o cpusubtype: " + + toString(CPUSubType.takeError())); + outs() << llvm::format("%s:\ncputype: %u\ncpusubtype: %u\n", + Filename.c_str(), *CPUType, *CPUSubType); + } +} + /// Create a combined index file from the input IR files and write it. /// /// This is meant to enable testing of ThinLTO combined index generation, @@ -905,6 +933,11 @@ int main(int argc, char **argv) { return 0; } + if (PrintMachOCPUOnly) { + printMachOCPUOnly(); + return 0; + } + if (ThinLTOMode.getNumOccurrences()) { if (ThinLTOMode.getNumOccurrences() > 1) report_fatal_error("You can't specify more than one -thinlto-action"); diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index 9933af94de1..683c2b2ae30 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -327,6 +327,27 @@ const char* lto_module_get_linkeropts(lto_module_t mod) { return unwrap(mod)->getLinkerOpts().data(); } +lto_bool_t lto_module_get_macho_cputype(lto_module_t mod, + unsigned int *out_cputype, + unsigned int *out_cpusubtype) { + LTOModule *M = unwrap(mod); + Expected CPUType = M->getMachOCPUType(); + if (!CPUType) { + sLastErrorString = toString(CPUType.takeError()); + return true; + } + *out_cputype = *CPUType; + + Expected CPUSubType = M->getMachOCPUSubType(); + if (!CPUSubType) { + sLastErrorString = toString(CPUSubType.takeError()); + return true; + } + *out_cpusubtype = *CPUSubType; + + return false; +} + void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg, lto_diagnostic_handler_t diag_handler, void *ctxt) { diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index fd2212cb5f3..1f0a6b23d3f 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -9,6 +9,7 @@ lto_module_create_from_memory_with_path lto_module_create_in_local_context lto_module_create_in_codegen_context lto_module_get_linkeropts +lto_module_get_macho_cputype lto_module_get_num_symbols lto_module_get_symbol_attribute lto_module_get_symbol_name