[llvm] 1b39c6f - [ORC] Add MachO universal binary support to StaticLibraryDefinitionGenerator.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 5 20:25:48 PDT 2020
Author: Lang Hames
Date: 2020-04-05T20:21:05-07:00
New Revision: 1b39c6f62c7c0345f2260f1cca26f93c0fb2f75a
URL: https://github.com/llvm/llvm-project/commit/1b39c6f62c7c0345f2260f1cca26f93c0fb2f75a
DIFF: https://github.com/llvm/llvm-project/commit/1b39c6f62c7c0345f2260f1cca26f93c0fb2f75a.diff
LOG: [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.
Added:
llvm/test/ExecutionEngine/OrcLazy/macho-universal-static-library-support.ll
Modified:
llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
llvm/include/llvm/Object/MachOUniversal.h
llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
llvm/tools/lli/lli.cpp
llvm/utils/lit/lit/llvm/config.py
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index 49ab0d628b0b..3b824b83b052 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -367,6 +367,14 @@ class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator {
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Load(ObjectLayer &L, const char *FileName);
+ /// Try to create a StaticLibraryDefinitionGenerator from the given path.
+ ///
+ /// This call will succeed if the file at the given path is a static library
+ /// or a MachO universal binary containing a static library that is compatible
+ /// with the given triple. Otherwise it will return an error.
+ static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+ Load(ObjectLayer &L, const char *FileName, const Triple &TT);
+
/// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
/// This call will succeed if the buffer contains a valid archive, otherwise
/// it will return an error.
diff --git a/llvm/include/llvm/Object/MachOUniversal.h b/llvm/include/llvm/Object/MachOUniversal.h
index eb45aff4480b..5e006fd87318 100644
--- a/llvm/include/llvm/Object/MachOUniversal.h
+++ b/llvm/include/llvm/Object/MachOUniversal.h
@@ -90,25 +90,14 @@ class MachOUniversalBinary : public Binary {
else // Parent->getMagic() == MachO::FAT_MAGIC_64
return Header64.reserved;
}
+ Triple getTriple() const {
+ return MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType());
+ }
std::string getArchFlagName() const {
const char *McpuDefault, *ArchFlag;
- if (Parent->getMagic() == MachO::FAT_MAGIC) {
- Triple T =
- MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype,
- &McpuDefault, &ArchFlag);
- } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
- Triple T =
- MachOObjectFile::getArchTriple(Header64.cputype,
- Header64.cpusubtype,
- &McpuDefault, &ArchFlag);
- }
- if (ArchFlag) {
- std::string ArchFlagName(ArchFlag);
- return ArchFlagName;
- } else {
- std::string ArchFlagName("");
- return ArchFlagName;
- }
+ MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType(),
+ &McpuDefault, &ArchFlag);
+ return ArchFlag ? ArchFlag : std::string();
}
Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 50f1ca3fe3df..4d255cd66c1b 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -13,6 +13,8 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
+#include "llvm/Object/MachOUniversal.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
@@ -302,6 +304,51 @@ StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) {
return Create(L, std::move(*ArchiveBuffer));
}
+Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName,
+ const Triple &TT) {
+ auto B = object::createBinary(FileName);
+ if (!B)
+ return B.takeError();
+
+ // If this is a regular archive then create an instance from it.
+ if (isa<object::Archive>(B->getBinary()))
+ return Create(L, std::move(B->takeBinary().second));
+
+ // If this is a universal binary then search for a slice matching the given
+ // Triple.
+ if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) {
+ for (const auto &Obj : UB->objects()) {
+ auto ObjTT = Obj.getTriple();
+ if (ObjTT.getArch() == TT.getArch() &&
+ ObjTT.getSubArch() == TT.getSubArch() &&
+ ObjTT.getVendor() == TT.getVendor()) {
+ // We found a match. Create an instance from a buffer covering this
+ // slice.
+ auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(),
+ Obj.getOffset());
+ if (!SliceBuffer)
+ return make_error<StringError>(
+ Twine("Could not create buffer for ") + TT.str() + " slice of " +
+ FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) +
+ " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) +
+ ": " + SliceBuffer.getError().message(),
+ SliceBuffer.getError());
+ return Create(L, std::move(*SliceBuffer));
+ }
+ }
+
+ return make_error<StringError>(Twine("Universal binary ") + FileName +
+ " does not contain a slice for " +
+ TT.str(),
+ inconvertibleErrorCode());
+ }
+
+ return make_error<StringError>(Twine("Unrecognized file type for ") +
+ FileName,
+ inconvertibleErrorCode());
+}
+
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
StaticLibraryDefinitionGenerator::Create(
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
diff --git a/llvm/test/ExecutionEngine/OrcLazy/macho-universal-static-library-support.ll b/llvm/test/ExecutionEngine/OrcLazy/macho-universal-static-library-support.ll
new file mode 100644
index 000000000000..4e6a42682cdc
--- /dev/null
+++ b/llvm/test/ExecutionEngine/OrcLazy/macho-universal-static-library-support.ll
@@ -0,0 +1,26 @@
+; REQUIRES: x86_64-apple, x86-registered-target, arm-registered-target
+;
+; RUN: rm -rf %t && mkdir -p %t
+; RUN: llc -filetype=obj -mtriple=x86_64-apple-macosx -o %t/foo.x86_64.o \
+; RUN: %p/Inputs/foo-return-i32-0.ll
+; RUN: llvm-ar r %t/foo.x86_64.a %t/foo.x86_64.o
+; RUN: llc -filetype=obj -mtriple=arm-apple-ios -o %t/foo.arm.o \
+; RUN: %p/Inputs/foo-return-i32-0.ll
+; RUN: llvm-ar r %t/foo.arm.a %t/foo.arm.o
+; RUN: llvm-lipo -create %t/foo.x86_64.a %t/foo.arm.a -output %t/foo.a
+; RUN: lli -jit-kind=orc-lazy -extra-archive %t/foo.a %s
+;
+; Check that MachO universal binaries containing archives work.
+; This test compiles two copies of a simple int foo() function that returns
+; zero, one copy for x86_64 and one for arm. It then puts each of these in an
+; archive and combines these two archives into a macho universal binary.
+; Finally we execute a main function that references foo to ensure that the
+; x86-64 copy is correctly found and linked.
+
+declare i32 @foo()
+
+define i32 @main(i32 %argc, i8** nocapture readnone %argv) {
+entry:
+ %0 = call i32 @foo()
+ ret i32 %0
+}
diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp
index 45ce92743359..4cb808baba45 100644
--- a/llvm/tools/lli/lli.cpp
+++ b/llvm/tools/lli/lli.cpp
@@ -966,7 +966,7 @@ int runOrcLazyJIT(const char *ProgName) {
auto JDItr = std::prev(IdxToDylib.lower_bound(EAIdx));
auto &JD = *JDItr->second;
JD.addGenerator(ExitOnErr(orc::StaticLibraryDefinitionGenerator::Load(
- J->getObjLinkingLayer(), EAItr->c_str())));
+ J->getObjLinkingLayer(), EAItr->c_str(), *TT)));
}
}
diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py
index 32a2c9e16a87..fe0f1f4441ac 100644
--- a/llvm/utils/lit/lit/llvm/config.py
+++ b/llvm/utils/lit/lit/llvm/config.py
@@ -87,6 +87,7 @@ def __init__(self, lit_config, config):
if target_triple:
if re.match(r'^x86_64.*-apple', target_triple):
+ features.add('x86_64-apple')
host_cxx = getattr(config, 'host_cxx', None)
if 'address' in sanitizers and self.get_clang_has_lsan(host_cxx, target_triple):
self.with_environment(
More information about the llvm-commits
mailing list