Skip to content

[Object] Remove restriction universal archives having both IR and native #67505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 40 additions & 44 deletions llvm/lib/Object/MachOUniversalWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Slice::Slice(const IRObjectFile &IRO, uint32_t CPUType, uint32_t CPUSubType,

Slice::Slice(const MachOObjectFile &O) : Slice(O, calculateAlignment(O)) {}

using MachoCPUTy = std::pair<unsigned, unsigned>;
using MachoCPUTy = std::pair<uint32_t, uint32_t>;

static Expected<MachoCPUTy> getMachoCPUFromTriple(Triple TT) {
auto CPU = std::make_pair(MachO::getCPUType(TT), MachO::getCPUSubType(TT));
Expand All @@ -117,10 +117,15 @@ static Expected<MachoCPUTy> getMachoCPUFromTriple(StringRef TT) {
return getMachoCPUFromTriple(Triple{TT});
}

static MachoCPUTy getMachoCPUFromObjectFile(const MachOObjectFile &O) {
return std::make_pair(O.getHeader().cputype, O.getHeader().cpusubtype);
}

Expected<Slice> Slice::create(const Archive &A, LLVMContext *LLVMCtx) {
Error Err = Error::success();
std::unique_ptr<MachOObjectFile> MFO = nullptr;
std::unique_ptr<IRObjectFile> IRFO = nullptr;
std::optional<MachoCPUTy> CPU = std::nullopt;
for (const Archive::Child &Child : A.children(Err)) {
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary(LLVMCtx);
if (!ChildOrErr)
Expand All @@ -134,65 +139,56 @@ Expected<Slice> Slice::create(const Archive &A, LLVMContext *LLVMCtx) {
.c_str());
if (Bin->isMachO()) {
MachOObjectFile *O = cast<MachOObjectFile>(Bin);
if (IRFO) {
return createStringError(
std::errc::invalid_argument,
"archive member %s is a MachO, while previous archive member "
"%s was an IR LLVM object",
O->getFileName().str().c_str(), IRFO->getFileName().str().c_str());
}
if (MFO &&
std::tie(MFO->getHeader().cputype, MFO->getHeader().cpusubtype) !=
std::tie(O->getHeader().cputype, O->getHeader().cpusubtype)) {
MachoCPUTy ObjectCPU = getMachoCPUFromObjectFile(*O);

if (CPU && CPU != ObjectCPU) {
// If CPU != nullptr, one of MFO, IRFO will be != nullptr.
StringRef PreviousName = MFO ? MFO->getFileName() : IRFO->getFileName();
return createStringError(
std::errc::invalid_argument,
("archive member " + O->getFileName() + " cputype (" +
Twine(O->getHeader().cputype) + ") and cpusubtype(" +
Twine(O->getHeader().cpusubtype) +
Twine(ObjectCPU.first) + ") and cpusubtype(" +
Twine(ObjectCPU.second) +
") does not match previous archive members cputype (" +
Twine(MFO->getHeader().cputype) + ") and cpusubtype(" +
Twine(MFO->getHeader().cpusubtype) +
") (all members must match) " + MFO->getFileName())
Twine(CPU->first) + ") and cpusubtype(" + Twine(CPU->second) +
") (all members must match) " + PreviousName)
.str()
.c_str());
}
if (!MFO) {
ChildOrErr.get().release();
MFO.reset(O);
if (!CPU)
CPU.emplace(ObjectCPU);
}
} else if (Bin->isIR()) {
IRObjectFile *O = cast<IRObjectFile>(Bin);
if (MFO) {
return createStringError(std::errc::invalid_argument,
"archive member '%s' is an LLVM IR object, "
"while previous archive member "
"'%s' was a MachO",
O->getFileName().str().c_str(),
MFO->getFileName().str().c_str());
Expected<MachoCPUTy> ObjectCPU =
getMachoCPUFromTriple(O->getTargetTriple());
if (!ObjectCPU)
return ObjectCPU.takeError();

if (CPU && CPU != *ObjectCPU) {
// If CPU != nullptr, one of MFO, IRFO will be != nullptr.
StringRef PreviousName =
IRFO ? IRFO->getFileName() : MFO->getFileName();
return createStringError(
std::errc::invalid_argument,
("archive member " + O->getFileName() + " cputype (" +
Twine(ObjectCPU->first) + ") and cpusubtype(" +
Twine(ObjectCPU->second) +
") does not match previous archive members cputype (" +
Twine(CPU->first) + ") and cpusubtype(" + Twine(CPU->second) +
") (all members must match) " + PreviousName)
.str()
.c_str());
}
if (IRFO) {
Expected<MachoCPUTy> CPUO = getMachoCPUFromTriple(O->getTargetTriple());
Expected<MachoCPUTy> CPUFO =
getMachoCPUFromTriple(IRFO->getTargetTriple());
if (!CPUO)
return CPUO.takeError();
if (!CPUFO)
return CPUFO.takeError();
if (*CPUO != *CPUFO) {
return createStringError(
std::errc::invalid_argument,
("archive member " + O->getFileName() + " cputype (" +
Twine(CPUO->first) + ") and cpusubtype(" + Twine(CPUO->second) +
") does not match previous archive members cputype (" +
Twine(CPUFO->first) + ") and cpusubtype(" +
Twine(CPUFO->second) + ") (all members must match) " +
IRFO->getFileName())
.str()
.c_str());
}
} else {

if (!IRFO) {
ChildOrErr.get().release();
IRFO.reset(O);
if (!CPU)
CPU.emplace(*ObjectCPU);
}
} else
return createStringError(std::errc::invalid_argument,
Expand Down
22 changes: 16 additions & 6 deletions llvm/test/tools/llvm-lipo/create-archive-input.test
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,27 @@
# RUN: llvm-lipo %t-ir-armv7-x86_64-universal.o -thin x86_64 -output %t-ir-extracted-x86_64.o
# RUN: cmp %t-ir-extracted-x86_64.o %t-ir-x86_64.o

# RUN: llvm-ar cr %t.different_types0.a %t-i386.o %t-ir-x86_64.o
# RUN: not llvm-lipo -create %t.different_types0.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-MACHO-AND-IR %s
# RUN: llvm-ar cr %t.different_types1.a %t-ir-x86_64.o %t-i386.o
# RUN: not llvm-lipo -create %t.different_types1.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-IR-AND-MACHO %s
# RUN: llvm-ar cr %t.different_types0-i386.a %t-i386.o
# RUN: llvm-ar cr %t.different_types0-x86_64.a %t-x86_64.o %t-ir-x86_64.o
# RUN: llvm-lipo -create %t.different_types0-i386.a %t.different_types0-x86_64.a -output %t.different_types0-universal.a
# RUN: llvm-lipo %t.different_types0-universal.a -thin i386 -output %t.different_types0-extracted-i386.a
# RUN: llvm-lipo %t.different_types0-universal.a -thin x86_64 -output %t.different_types0-extracted-x86_64.a
# RUN: cmp %t.different_types0-extracted-i386.a %t.different_types0-i386.a
# RUN: cmp %t.different_types0-extracted-x86_64.a %t.different_types0-x86_64.a

# RUN: llvm-ar cr %t.different_types1-i386.a %t-i386.o
# RUN: llvm-ar cr %t.different_types1-x86_64.a %t-ir-x86_64.o %t-x86_64.o
# RUN: llvm-lipo -create %t.different_types1-x86_64.a %t.different_types1-i386.a -output %t.different_types1-universal.a
# RUN: llvm-lipo %t.different_types1-universal.a -thin i386 -output %t.different_types1-extracted-i386.a
# RUN: llvm-lipo %t.different_types1-universal.a -thin x86_64 -output %t.different_types1-extracted-x86_64.a
# RUN: cmp %t.different_types1-extracted-i386.a %t.different_types1-i386.a
# RUN: cmp %t.different_types1-extracted-x86_64.a %t.different_types1-x86_64.a

# RUN: llvm-ar cr %t.different_architectures_ir.a %t-ir-x86_64.o %t-ir-armv7.o
# RUN: not llvm-lipo -create %t.different_architectures_ir.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-DIFFERENT-ARCHS %s

# EMPTY-ARCHIVE: empty archive
# ARCHIVE-WITH-DIFFERENT-ARCHS: all members must match
# ARCHIVE-WITH-MACHO-AND-IR: is an LLVM IR object, while previous archive member {{.*}} was a MachO
# ARCHIVE-WITH-IR-AND-MACHO: is a MachO, while previous archive member {{.*}} was an IR LLVM object
# ARCHIVE-WITH-FAT-BINARY: fat file (not allowed in an archive)
#
# INFO-i386-x86_64: i386 x86_64