Skip to content

Commit 1b39c6f

Browse files
committed
[ORC] Add MachO universal binary support to StaticLibraryDefinitionGenerator.
Add a new overload of StaticLibraryDefinitionGenerator::Load that takes a triple argument and supports loading archives from MachO universal binaries in addition to regular archives. The LLI tool is updated to use this overload.
1 parent 322c235 commit 1b39c6f

File tree

6 files changed

+89
-18
lines changed

6 files changed

+89
-18
lines changed

llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,14 @@ class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator {
367367
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
368368
Load(ObjectLayer &L, const char *FileName);
369369

370+
/// Try to create a StaticLibraryDefinitionGenerator from the given path.
371+
///
372+
/// This call will succeed if the file at the given path is a static library
373+
/// or a MachO universal binary containing a static library that is compatible
374+
/// with the given triple. Otherwise it will return an error.
375+
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
376+
Load(ObjectLayer &L, const char *FileName, const Triple &TT);
377+
370378
/// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
371379
/// This call will succeed if the buffer contains a valid archive, otherwise
372380
/// it will return an error.

llvm/include/llvm/Object/MachOUniversal.h

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -90,25 +90,14 @@ class MachOUniversalBinary : public Binary {
9090
else // Parent->getMagic() == MachO::FAT_MAGIC_64
9191
return Header64.reserved;
9292
}
93+
Triple getTriple() const {
94+
return MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType());
95+
}
9396
std::string getArchFlagName() const {
9497
const char *McpuDefault, *ArchFlag;
95-
if (Parent->getMagic() == MachO::FAT_MAGIC) {
96-
Triple T =
97-
MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype,
98-
&McpuDefault, &ArchFlag);
99-
} else { // Parent->getMagic() == MachO::FAT_MAGIC_64
100-
Triple T =
101-
MachOObjectFile::getArchTriple(Header64.cputype,
102-
Header64.cpusubtype,
103-
&McpuDefault, &ArchFlag);
104-
}
105-
if (ArchFlag) {
106-
std::string ArchFlagName(ArchFlag);
107-
return ArchFlagName;
108-
} else {
109-
std::string ArchFlagName("");
110-
return ArchFlagName;
111-
}
98+
MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType(),
99+
&McpuDefault, &ArchFlag);
100+
return ArchFlag ? ArchFlag : std::string();
112101
}
113102

114103
Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;

llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include "llvm/IR/Function.h"
1414
#include "llvm/IR/GlobalVariable.h"
1515
#include "llvm/IR/Module.h"
16+
#include "llvm/Object/MachOUniversal.h"
17+
#include "llvm/Support/FormatVariadic.h"
1618
#include "llvm/Support/TargetRegistry.h"
1719
#include "llvm/Target/TargetMachine.h"
1820

@@ -302,6 +304,51 @@ StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) {
302304
return Create(L, std::move(*ArchiveBuffer));
303305
}
304306

307+
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
308+
StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName,
309+
const Triple &TT) {
310+
auto B = object::createBinary(FileName);
311+
if (!B)
312+
return B.takeError();
313+
314+
// If this is a regular archive then create an instance from it.
315+
if (isa<object::Archive>(B->getBinary()))
316+
return Create(L, std::move(B->takeBinary().second));
317+
318+
// If this is a universal binary then search for a slice matching the given
319+
// Triple.
320+
if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) {
321+
for (const auto &Obj : UB->objects()) {
322+
auto ObjTT = Obj.getTriple();
323+
if (ObjTT.getArch() == TT.getArch() &&
324+
ObjTT.getSubArch() == TT.getSubArch() &&
325+
ObjTT.getVendor() == TT.getVendor()) {
326+
// We found a match. Create an instance from a buffer covering this
327+
// slice.
328+
auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(),
329+
Obj.getOffset());
330+
if (!SliceBuffer)
331+
return make_error<StringError>(
332+
Twine("Could not create buffer for ") + TT.str() + " slice of " +
333+
FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) +
334+
" .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) +
335+
": " + SliceBuffer.getError().message(),
336+
SliceBuffer.getError());
337+
return Create(L, std::move(*SliceBuffer));
338+
}
339+
}
340+
341+
return make_error<StringError>(Twine("Universal binary ") + FileName +
342+
" does not contain a slice for " +
343+
TT.str(),
344+
inconvertibleErrorCode());
345+
}
346+
347+
return make_error<StringError>(Twine("Unrecognized file type for ") +
348+
FileName,
349+
inconvertibleErrorCode());
350+
}
351+
305352
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
306353
StaticLibraryDefinitionGenerator::Create(
307354
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; REQUIRES: x86_64-apple, x86-registered-target, arm-registered-target
2+
;
3+
; RUN: rm -rf %t && mkdir -p %t
4+
; RUN: llc -filetype=obj -mtriple=x86_64-apple-macosx -o %t/foo.x86_64.o \
5+
; RUN: %p/Inputs/foo-return-i32-0.ll
6+
; RUN: llvm-ar r %t/foo.x86_64.a %t/foo.x86_64.o
7+
; RUN: llc -filetype=obj -mtriple=arm-apple-ios -o %t/foo.arm.o \
8+
; RUN: %p/Inputs/foo-return-i32-0.ll
9+
; RUN: llvm-ar r %t/foo.arm.a %t/foo.arm.o
10+
; RUN: llvm-lipo -create %t/foo.x86_64.a %t/foo.arm.a -output %t/foo.a
11+
; RUN: lli -jit-kind=orc-lazy -extra-archive %t/foo.a %s
12+
;
13+
; Check that MachO universal binaries containing archives work.
14+
; This test compiles two copies of a simple int foo() function that returns
15+
; zero, one copy for x86_64 and one for arm. It then puts each of these in an
16+
; archive and combines these two archives into a macho universal binary.
17+
; Finally we execute a main function that references foo to ensure that the
18+
; x86-64 copy is correctly found and linked.
19+
20+
declare i32 @foo()
21+
22+
define i32 @main(i32 %argc, i8** nocapture readnone %argv) {
23+
entry:
24+
%0 = call i32 @foo()
25+
ret i32 %0
26+
}

llvm/tools/lli/lli.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ int runOrcLazyJIT(const char *ProgName) {
966966
auto JDItr = std::prev(IdxToDylib.lower_bound(EAIdx));
967967
auto &JD = *JDItr->second;
968968
JD.addGenerator(ExitOnErr(orc::StaticLibraryDefinitionGenerator::Load(
969-
J->getObjLinkingLayer(), EAItr->c_str())));
969+
J->getObjLinkingLayer(), EAItr->c_str(), *TT)));
970970
}
971971
}
972972

llvm/utils/lit/lit/llvm/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def __init__(self, lit_config, config):
8787

8888
if target_triple:
8989
if re.match(r'^x86_64.*-apple', target_triple):
90+
features.add('x86_64-apple')
9091
host_cxx = getattr(config, 'host_cxx', None)
9192
if 'address' in sanitizers and self.get_clang_has_lsan(host_cxx, target_triple):
9293
self.with_environment(

0 commit comments

Comments
 (0)