[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
This commit is contained in:
Francis Visoiu Mistrih 2020-02-18 17:13:47 -08:00
parent 67c1615440
commit e551b737c3
9 changed files with 101 additions and 1 deletions

View File

@ -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. 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`` ``lto_code_gen_t``
------------------ ------------------

View File

@ -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 * \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* extern const char*
lto_module_get_linkeropts(lto_module_t mod); 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. * Diagnostic severity.
* *

View File

@ -165,6 +165,10 @@ public:
static const char *getDependentLibrary(lto::InputFile *input, size_t index, size_t *size); static const char *getDependentLibrary(lto::InputFile *input, size_t index, size_t *size);
Expected<uint32_t> getMachOCPUType() const;
Expected<uint32_t> getMachOCPUSubType() const;
private: private:
/// Parse metadata from the module /// Parse metadata from the module
// FIXME: it only parses "llvm.linker.options" metadata at the moment // FIXME: it only parses "llvm.linker.options" metadata at the moment

View File

@ -28,6 +28,7 @@
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbol.h"
#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h" #include "llvm/Support/Host.h"
@ -676,3 +677,11 @@ const char *LTOModule::getDependentLibrary(lto::InputFile *input, size_t index,
*size = S.size(); *size = S.size();
return S.data(); return S.data();
} }
Expected<uint32_t> LTOModule::getMachOCPUType() const {
return MachO::getCPUType(Triple(Mod->getTargetTriple()));
}
Expected<uint32_t> LTOModule::getMachOCPUSubType() const {
return MachO::getCPUSubType(Triple(Mod->getTargetTriple()));
}

View File

@ -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

View File

@ -7,5 +7,8 @@
; RUN: not llvm-lto --list-dependent-libraries-only %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-LIBS ; 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 ; 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 ; 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 ; CHECK-THIN: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': file too small to contain bitcode header

View File

@ -223,6 +223,10 @@ static cl::opt<bool> CheckHasObjC(
"check-for-objc", cl::init(false), "check-for-objc", cl::init(false),
cl::desc("Only check if the module has objective-C defined in it")); cl::desc("Only check if the module has objective-C defined in it"));
static cl::opt<bool> PrintMachOCPUOnly(
"print-macho-cpu-only", cl::init(false),
cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"));
namespace { namespace {
struct ModuleInfo { struct ModuleInfo {
@ -404,6 +408,30 @@ static void listDependentLibraries() {
} }
} }
static void printMachOCPUOnly() {
LLVMContext Context;
Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
true);
TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
for (auto &Filename : InputFilenames) {
ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
LTOModule::createFromFile(Context, Filename, Options);
if (!ModuleOrErr)
error(ModuleOrErr, "llvm-lto: ");
Expected<uint32_t> CPUType = (*ModuleOrErr)->getMachOCPUType();
Expected<uint32_t> 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. /// Create a combined index file from the input IR files and write it.
/// ///
/// This is meant to enable testing of ThinLTO combined index generation, /// This is meant to enable testing of ThinLTO combined index generation,
@ -905,6 +933,11 @@ int main(int argc, char **argv) {
return 0; return 0;
} }
if (PrintMachOCPUOnly) {
printMachOCPUOnly();
return 0;
}
if (ThinLTOMode.getNumOccurrences()) { if (ThinLTOMode.getNumOccurrences()) {
if (ThinLTOMode.getNumOccurrences() > 1) if (ThinLTOMode.getNumOccurrences() > 1)
report_fatal_error("You can't specify more than one -thinlto-action"); report_fatal_error("You can't specify more than one -thinlto-action");

View File

@ -327,6 +327,27 @@ const char* lto_module_get_linkeropts(lto_module_t mod) {
return unwrap(mod)->getLinkerOpts().data(); 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<uint32_t> CPUType = M->getMachOCPUType();
if (!CPUType) {
sLastErrorString = toString(CPUType.takeError());
return true;
}
*out_cputype = *CPUType;
Expected<uint32_t> 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, void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
lto_diagnostic_handler_t diag_handler, lto_diagnostic_handler_t diag_handler,
void *ctxt) { void *ctxt) {

View File

@ -9,6 +9,7 @@ lto_module_create_from_memory_with_path
lto_module_create_in_local_context lto_module_create_in_local_context
lto_module_create_in_codegen_context lto_module_create_in_codegen_context
lto_module_get_linkeropts lto_module_get_linkeropts
lto_module_get_macho_cputype
lto_module_get_num_symbols lto_module_get_num_symbols
lto_module_get_symbol_attribute lto_module_get_symbol_attribute
lto_module_get_symbol_name lto_module_get_symbol_name