Skip to content

Commit

Permalink
[LTO][Legacy] Add new API to query Mach-O CPU (sub)type
Browse files Browse the repository at this point in the history
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
  • Loading branch information
francisvm committed Feb 28, 2020
1 parent 67c1615 commit e551b73
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 1 deletion.
6 changes: 6 additions & 0 deletions llvm/docs/LinkTimeOptimization.rst
Expand Up @@ -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``
------------------

Expand Down
17 changes: 16 additions & 1 deletion llvm/include/llvm-c/lto.h
Expand Up @@ -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
Expand Down Expand Up @@ -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.
*
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/LTO/legacy/LTOModule.h
Expand Up @@ -165,6 +165,10 @@ struct LTOModule {

static const char *getDependentLibrary(lto::InputFile *input, size_t index, size_t *size);

Expected<uint32_t> getMachOCPUType() const;

Expected<uint32_t> getMachOCPUSubType() const;

private:
/// Parse metadata from the module
// FIXME: it only parses "llvm.linker.options" metadata at the moment
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/LTO/LTOModule.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -676,3 +677,11 @@ const char *LTOModule::getDependentLibrary(lto::InputFile *input, size_t index,
*size = S.size();
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()));
}
8 changes: 8 additions & 0 deletions llvm/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
3 changes: 3 additions & 0 deletions llvm/test/tools/llvm-lto/error.ll
Expand Up @@ -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
33 changes: 33 additions & 0 deletions llvm/tools/llvm-lto/llvm-lto.cpp
Expand Up @@ -223,6 +223,10 @@ static cl::opt<bool> CheckHasObjC(
"check-for-objc", cl::init(false),
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 {

struct ModuleInfo {
Expand Down Expand Up @@ -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.
///
/// This is meant to enable testing of ThinLTO combined index generation,
Expand Down Expand Up @@ -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");
Expand Down
21 changes: 21 additions & 0 deletions llvm/tools/lto/lto.cpp
Expand Up @@ -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<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,
lto_diagnostic_handler_t diag_handler,
void *ctxt) {
Expand Down
1 change: 1 addition & 0 deletions llvm/tools/lto/lto.exports
Expand Up @@ -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
Expand Down

0 comments on commit e551b73

Please sign in to comment.