mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[llvm-lipo] Add support for -arch
Add support for -arch. Differential revision: https://reviews.llvm.org/D68116 Test plan: make check-all llvm-svn: 373132
This commit is contained in:
parent
59afa86678
commit
5d5e87b41e
17
test/tools/llvm-lipo/create-arch.test
Normal file
17
test/tools/llvm-lipo/create-arch.test
Normal file
@ -0,0 +1,17 @@
|
||||
# RUN: yaml2obj %p/Inputs/i386-slice.yaml > %t-i386.o
|
||||
# RUN: yaml2obj %p/Inputs/x86_64-slice.yaml > %t-x86_64.o
|
||||
|
||||
# RUN: llvm-lipo %t-i386.o %t-x86_64.o -create -output %t-universal.o
|
||||
# RUN: llvm-lipo %t-i386.o -arch x86_64 %t-x86_64.o -create -output %t-universal-1.o
|
||||
# RUN: cmp %t-universal.o %t-universal-1.o
|
||||
# RUN: llvm-lipo -arch i386 %t-i386.o -arch x86_64 %t-x86_64.o -create -output %t-universal-2.o
|
||||
# RUN: cmp %t-universal.o %t-universal-2.o
|
||||
#
|
||||
# RUN: not llvm-lipo -arch armv7 %t-i386.o -arch x86_64 %t-x86_64.o -create -output /dev/null 2>&1 | FileCheck --check-prefix=ARCH_NOT_MATCHED %s
|
||||
# ARCH_NOT_MATCHED: error: specified architecture: armv7 for file: {{.*}} does not match the file's architecture (i386)
|
||||
#
|
||||
# # RUN: not llvm-lipo -arch i3866 %t-32.o -create -o /dev/null 2>&1 | FileCheck --check-prefix=INVALID_ARCH %s
|
||||
# INVALID_ARCH: error: Invalid architecture: i3866
|
||||
#
|
||||
# RUN: not llvm-lipo -arch i386 %t-33.o -create -o /dev/null 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
|
||||
# INVALID_FILE: {{[nN]}}o such file or directory
|
@ -5,20 +5,20 @@
|
||||
# RUN: not llvm-lipo %t-universal.o -replace %t-32.o 2>&1 | FileCheck --check-prefix=MISSING_ARG %s
|
||||
# MISSING_ARG: error: replace is missing an argument: expects -replace arch_type file_name
|
||||
|
||||
# RUN: not llvm-lipo %t-universal.o -replace %t-32.o i386 2>&1 | FileCheck --check-prefix=OUTPUT_FILE %s
|
||||
# RUN: not llvm-lipo %t-universal.o -replace i386 %t-32.o 2>&1 | FileCheck --check-prefix=OUTPUT_FILE %s
|
||||
# OUTPUT_FILE: error: replace expects a single output file to be specified
|
||||
|
||||
# RUN: not llvm-lipo %t-universal.o %t-universal.o -replace %t-32.o i386 -o %t.o 2>&1 | FileCheck --check-prefix=INPUT_ARGS %s
|
||||
# RUN: not llvm-lipo %t-universal.o %t-universal.o -replace i386 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=INPUT_ARGS %s
|
||||
# INPUT_ARGS: error: replace expects a single input file
|
||||
|
||||
# RUN: not llvm-lipo %t-universal.o -replace %t-32.o i386 -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
|
||||
# INVALID_FILE: error: 'i386': {{[nN]}}o such file or directory
|
||||
# RUN: not llvm-lipo %t-universal.o -replace i386 %t-33.o -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
|
||||
# INVALID_FILE: {{[nN]}}o such file or directory
|
||||
|
||||
# RUN: not llvm-lipo %t-universal.o -replace i3866 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_ARCH %s
|
||||
# INVALID_ARCH: error: Invalid architecture: i3866
|
||||
|
||||
# RUN: not llvm-lipo %t-universal.o -replace arm64 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=ARCH_NOT_MATCHED %s
|
||||
# ARCH_NOT_MATCHED: error: specified architecture: arm64 for replacement file: {{.*}} does not match the file's architecture
|
||||
# ARCH_NOT_MATCHED: error: specified architecture: arm64 for file: {{.*}} does not match the file's architecture (i386)
|
||||
|
||||
# RUN: not llvm-lipo %t-universal.o -replace arm64 %t-arm64.o -o %t.o 2>&1 | FileCheck --check-prefix=ARCH_NOT_IN_INPUT %s
|
||||
# ARCH_NOT_IN_INPUT: error: -replace arm64 <file_name> specified but fat file: {{.*}} does not contain that architecture
|
||||
|
@ -12,6 +12,10 @@ def segalign
|
||||
"architecture when creating a universal binary file. The "
|
||||
"alignment is a hexadecimal number that is a power of 2.">;
|
||||
|
||||
def arch
|
||||
: MultiArg<["-", "--"], "arch", 2>,
|
||||
HelpText<"Specifies the architecture and the corresponding input file">;
|
||||
|
||||
def action_group : OptionGroup<"action group">;
|
||||
|
||||
def verify_arch
|
||||
|
@ -86,15 +86,15 @@ enum class LipoAction {
|
||||
ReplaceArch,
|
||||
};
|
||||
|
||||
struct Replacement {
|
||||
StringRef ArchType;
|
||||
struct InputFile {
|
||||
Optional<StringRef> ArchType;
|
||||
StringRef FileName;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
SmallVector<std::string, 1> InputFiles;
|
||||
SmallVector<InputFile, 1> InputFiles;
|
||||
SmallVector<std::string, 1> VerifyArchList;
|
||||
SmallVector<Replacement, 1> Replacements;
|
||||
SmallVector<InputFile, 1> ReplacementFiles;
|
||||
StringMap<const uint32_t> SegmentAlignments;
|
||||
std::string ThinArchType;
|
||||
std::string OutputFile;
|
||||
@ -301,7 +301,15 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
|
||||
reportError("unknown argument '" + Arg->getAsString(InputArgs) + "'");
|
||||
|
||||
for (auto Arg : InputArgs.filtered(LIPO_INPUT))
|
||||
C.InputFiles.push_back(Arg->getValue());
|
||||
C.InputFiles.push_back({None, Arg->getValue()});
|
||||
for (auto Arg : InputArgs.filtered(LIPO_arch)) {
|
||||
validateArchitectureName(Arg->getValue(0));
|
||||
if (!Arg->getValue(1))
|
||||
reportError(
|
||||
"arch is missing an argument: expects -arch arch_type file_name");
|
||||
C.InputFiles.push_back({StringRef(Arg->getValue(0)), Arg->getValue(1)});
|
||||
}
|
||||
|
||||
if (C.InputFiles.empty())
|
||||
reportError("at least one input file should be specified");
|
||||
|
||||
@ -402,8 +410,9 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
|
||||
reportError(
|
||||
"replace is missing an argument: expects -replace arch_type "
|
||||
"file_name");
|
||||
C.Replacements.push_back(
|
||||
Replacement{Action->getValue(0), Action->getValue(1)});
|
||||
validateArchitectureName(Action->getValue(0));
|
||||
C.ReplacementFiles.push_back(
|
||||
{StringRef(Action->getValue(0)), Action->getValue(1)});
|
||||
}
|
||||
|
||||
if (C.OutputFile.empty())
|
||||
@ -419,16 +428,25 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
|
||||
}
|
||||
|
||||
static SmallVector<OwningBinary<Binary>, 1>
|
||||
readInputBinaries(ArrayRef<std::string> InputFiles) {
|
||||
readInputBinaries(ArrayRef<InputFile> InputFiles) {
|
||||
SmallVector<OwningBinary<Binary>, 1> InputBinaries;
|
||||
for (StringRef InputFile : InputFiles) {
|
||||
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFile);
|
||||
for (const InputFile &IF : InputFiles) {
|
||||
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(IF.FileName);
|
||||
if (!BinaryOrErr)
|
||||
reportError(InputFile, BinaryOrErr.takeError());
|
||||
if (!BinaryOrErr->getBinary()->isArchive() &&
|
||||
!BinaryOrErr->getBinary()->isMachO() &&
|
||||
!BinaryOrErr->getBinary()->isMachOUniversalBinary())
|
||||
reportError("File " + InputFile + " has unsupported binary format");
|
||||
reportError(IF.FileName, BinaryOrErr.takeError());
|
||||
const Binary *B = BinaryOrErr->getBinary();
|
||||
if (!B->isArchive() && !B->isMachO() && !B->isMachOUniversalBinary())
|
||||
reportError("File " + IF.FileName + " has unsupported binary format");
|
||||
if (IF.ArchType && (B->isMachO() || B->isArchive())) {
|
||||
const auto ArchType =
|
||||
B->isMachO() ? Slice(cast<MachOObjectFile>(B)).getArchString()
|
||||
: Slice(cast<Archive>(B)).getArchString();
|
||||
if (Triple(*IF.ArchType).getArch() != Triple(ArchType).getArch())
|
||||
reportError("specified architecture: " + *IF.ArchType +
|
||||
" for file: " + B->getFileName() +
|
||||
" does not match the file's architecture (" + ArchType +
|
||||
")");
|
||||
}
|
||||
InputBinaries.push_back(std::move(*BinaryOrErr));
|
||||
}
|
||||
return InputBinaries;
|
||||
@ -716,32 +734,20 @@ static void createUniversalBinary(ArrayRef<OwningBinary<Binary>> InputBinaries,
|
||||
|
||||
static StringMap<Slice>
|
||||
buildReplacementSlices(ArrayRef<OwningBinary<Binary>> ReplacementBinaries,
|
||||
const StringMap<const uint32_t> &Alignments,
|
||||
ArrayRef<Replacement> Replacements) {
|
||||
assert(ReplacementBinaries.size() == Replacements.size() &&
|
||||
"Number of replacment binaries does not match the number of "
|
||||
"replacements");
|
||||
const StringMap<const uint32_t> &Alignments) {
|
||||
StringMap<Slice> Slices;
|
||||
// populates StringMap of slices to replace with; error checks for mismatched
|
||||
// replace flag args, fat files, and duplicate arch_types
|
||||
for (size_t Index = 0, Size = Replacements.size(); Index < Size; ++Index) {
|
||||
StringRef ReplacementArch = Replacements[Index].ArchType;
|
||||
const Binary *ReplacementBinary = ReplacementBinaries[Index].getBinary();
|
||||
validateArchitectureName(ReplacementArch);
|
||||
|
||||
for (const auto &OB : ReplacementBinaries) {
|
||||
const Binary *ReplacementBinary = OB.getBinary();
|
||||
auto O = dyn_cast<MachOObjectFile>(ReplacementBinary);
|
||||
if (!O)
|
||||
reportError("replacement file: " + ReplacementBinary->getFileName() +
|
||||
" is a fat file (must be a thin file)");
|
||||
|
||||
if (O->getArch() != Triple(ReplacementArch).getArch())
|
||||
reportError("specified architecture: " + ReplacementArch +
|
||||
" for replacement file: " + ReplacementBinary->getFileName() +
|
||||
" does not match the file's architecture");
|
||||
|
||||
auto Entry = Slices.try_emplace(ReplacementArch, Slice(O));
|
||||
Slice S(O);
|
||||
auto Entry = Slices.try_emplace(S.getArchString(), S);
|
||||
if (!Entry.second)
|
||||
reportError("-replace " + ReplacementArch +
|
||||
reportError("-replace " + S.getArchString() +
|
||||
" <file_name> specified multiple times: " +
|
||||
Entry.first->second.getBinary()->getFileName() + ", " +
|
||||
O->getFileName());
|
||||
@ -756,7 +762,7 @@ LLVM_ATTRIBUTE_NORETURN
|
||||
static void replaceSlices(ArrayRef<OwningBinary<Binary>> InputBinaries,
|
||||
const StringMap<const uint32_t> &Alignments,
|
||||
StringRef OutputFileName,
|
||||
ArrayRef<Replacement> Replacements) {
|
||||
ArrayRef<InputFile> ReplacementFiles) {
|
||||
assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
|
||||
assert(!OutputFileName.empty() && "Replace expects a single output file");
|
||||
|
||||
@ -765,14 +771,11 @@ static void replaceSlices(ArrayRef<OwningBinary<Binary>> InputBinaries,
|
||||
InputBinaries.front().getBinary()->getFileName() +
|
||||
" must be a fat file when the -replace option is specified");
|
||||
|
||||
SmallVector<std::string, 1> ReplacementFiles;
|
||||
for (const auto &R : Replacements)
|
||||
ReplacementFiles.push_back(R.FileName);
|
||||
SmallVector<OwningBinary<Binary>, 1> ReplacementBinaries =
|
||||
readInputBinaries(ReplacementFiles);
|
||||
|
||||
StringMap<Slice> ReplacementSlices =
|
||||
buildReplacementSlices(ReplacementBinaries, Alignments, Replacements);
|
||||
buildReplacementSlices(ReplacementBinaries, Alignments);
|
||||
SmallVector<std::unique_ptr<MachOObjectFile>, 2> ExtractedObjects;
|
||||
SmallVector<Slice, 2> Slices =
|
||||
buildSlices(InputBinaries, Alignments, ExtractedObjects);
|
||||
@ -820,7 +823,7 @@ int main(int argc, char **argv) {
|
||||
break;
|
||||
case LipoAction::ReplaceArch:
|
||||
replaceSlices(InputBinaries, C.SegmentAlignments, C.OutputFile,
|
||||
C.Replacements);
|
||||
C.ReplacementFiles);
|
||||
break;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
Loading…
Reference in New Issue
Block a user