authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-28 11:53:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-28 11:53:25-07:00
logadb4a953021aadcfd539589eeccc2fe4e6ab827a
tree0c3fd514812e38fdaec5927825861858e8bfd8f4
parente863292fe2f280945d914e7e98fbc704b68f1004

update to LLVM 15

release/15.x 37007475ca1b345b4c5d340e228bcd7a62732d81

8 files changed, 354 insertions(+), 137 deletions(-)

CMakeLists.txt+3-3
......@@ -108,9 +108,9 @@ else()
108108 set(ZIG_USE_LLVM_CONFIG OFF CACHE BOOL "use llvm-config to find LLVM libraries")
109109endif()
110110
111find_package(llvm 14)
112find_package(clang 14)
113find_package(lld 14)
111find_package(llvm 15)
112find_package(clang 15)
113find_package(lld 15)
114114
115115if(ZIG_STATIC_ZLIB)
116116 list(REMOVE_ITEM LLVM_LIBRARIES "-lz")
cmake/Findclang.cmake+3-3
......@@ -17,9 +17,9 @@ find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h
1717if(${LLVM_LINK_MODE} STREQUAL "shared")
1818 find_library(CLANG_LIBRARIES
1919 NAMES
20 libclang-cpp.so.14
21 clang-cpp-14.0
22 clang-cpp140
20 libclang-cpp.so.15
21 clang-cpp-15.0
22 clang-cpp150
2323 clang-cpp
2424 NAMES_PER_DIR
2525 HINTS "${LLVM_LIBDIRS}"
cmake/Findlld.cmake+16-16
......@@ -9,21 +9,21 @@
99find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h
1010 HINTS ${LLVM_INCLUDE_DIRS}
1111 PATHS
12 /usr/lib/llvm-14/include
13 /usr/local/llvm140/include
14 /usr/local/llvm14/include
15 /usr/local/opt/llvm@14/include
16 /opt/homebrew/opt/llvm@14/include
12 /usr/lib/llvm-15/include
13 /usr/local/llvm150/include
14 /usr/local/llvm15/include
15 /usr/local/opt/llvm@15/include
16 /opt/homebrew/opt/llvm@15/include
1717 /mingw64/include)
1818
19find_library(LLD_LIBRARY NAMES lld-14.0 lld140 lld NAMES_PER_DIR
19find_library(LLD_LIBRARY NAMES lld-15.0 lld150 lld NAMES_PER_DIR
2020 HINTS ${LLVM_LIBDIRS}
2121 PATHS
22 /usr/lib/llvm-14/lib
23 /usr/local/llvm140/lib
24 /usr/local/llvm14/lib
25 /usr/local/opt/llvm@14/lib
26 /opt/homebrew/opt/llvm@14/lib
22 /usr/lib/llvm-15/lib
23 /usr/local/llvm150/lib
24 /usr/local/llvm15/lib
25 /usr/local/opt/llvm@15/lib
26 /opt/homebrew/opt/llvm@15/lib
2727)
2828if(EXISTS ${LLD_LIBRARY})
2929 set(LLD_LIBRARIES ${LLD_LIBRARY})
......@@ -34,11 +34,11 @@ else()
3434 HINTS ${LLVM_LIBDIRS}
3535 PATHS
3636 ${LLD_LIBDIRS}
37 /usr/lib/llvm-14/lib
38 /usr/local/llvm140/lib
39 /usr/local/llvm14/lib
40 /usr/local/opt/llvm@14/lib
41 /opt/homebrew/opt/llvm@14/lib
37 /usr/lib/llvm-15/lib
38 /usr/local/llvm150/lib
39 /usr/local/llvm15/lib
40 /usr/local/opt/llvm@15/lib
41 /opt/homebrew/opt/llvm@15/lib
4242 /mingw64/lib
4343 /c/msys64/mingw64/lib
4444 c:/msys64/mingw64/lib)
cmake/Findllvm.cmake+6-6
......@@ -13,12 +13,12 @@ if(ZIG_USE_LLVM_CONFIG)
1313 while(1)
1414 unset(LLVM_CONFIG_EXE CACHE)
1515 find_program(LLVM_CONFIG_EXE
16 NAMES llvm-config-14 llvm-config-14.0 llvm-config140 llvm-config14 llvm-config NAMES_PER_DIR
16 NAMES llvm-config-15 llvm-config-15.0 llvm-config150 llvm-config15 llvm-config NAMES_PER_DIR
1717 PATHS
1818 "/mingw64/bin"
1919 "/c/msys64/mingw64/bin"
2020 "c:/msys64/mingw64/bin"
21 "C:/Libraries/llvm-14.0.0/bin")
21 "C:/Libraries/llvm-15.0.0/bin")
2222
2323 if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND")
2424 if (DEFINED LLVM_CONFIG_ERROR_MESSAGE)
......@@ -35,9 +35,9 @@ if(ZIG_USE_LLVM_CONFIG)
3535 OUTPUT_STRIP_TRAILING_WHITESPACE)
3636
3737 get_filename_component(LLVM_CONFIG_DIR "${LLVM_CONFIG_EXE}" DIRECTORY)
38 if("${LLVM_CONFIG_VERSION}" VERSION_LESS 14 OR "${LLVM_CONFIG_VERSION}" VERSION_EQUAL 15 OR "${LLVM_CONFIG_VERSION}" VERSION_GREATER 15)
38 if("${LLVM_CONFIG_VERSION}" VERSION_LESS 15 OR "${LLVM_CONFIG_VERSION}" VERSION_EQUAL 16 OR "${LLVM_CONFIG_VERSION}" VERSION_GREATER 16)
3939 # Save the error message, in case this is the last llvm-config we find
40 set(LLVM_CONFIG_ERROR_MESSAGE "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
40 set(LLVM_CONFIG_ERROR_MESSAGE "expected LLVM 15.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
4141
4242 # Ignore this directory and try the search again
4343 list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}")
......@@ -61,9 +61,9 @@ if(ZIG_USE_LLVM_CONFIG)
6161 if (LLVM_CONFIG_ERROR)
6262 # Save the error message, in case this is the last llvm-config we find
6363 if (ZIG_SHARED_LLVM)
64 set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 14.x found at ${LLVM_CONFIG_EXE} does not support linking as a shared library")
64 set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 15.x found at ${LLVM_CONFIG_EXE} does not support linking as a shared library")
6565 else()
66 set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 14.x found at ${LLVM_CONFIG_EXE} does not support linking as a static library")
66 set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 15.x found at ${LLVM_CONFIG_EXE} does not support linking as a static library")
6767 endif()
6868
6969 # Ignore this directory and try the search again
src/zig_clang_cc1_main.cpp+11-3
......@@ -212,7 +212,9 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
212212 bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),
213213 Argv, Diags, Argv0);
214214
215 if (Clang->getFrontendOpts().TimeTrace) {
215 if (Clang->getFrontendOpts().TimeTrace ||
216 !Clang->getFrontendOpts().TimeTracePath.empty()) {
217 Clang->getFrontendOpts().TimeTrace = 1;
216218 llvm::timeTraceProfilerInitialize(
217219 Clang->getFrontendOpts().TimeTraceGranularity, Argv0);
218220 }
......@@ -256,12 +258,18 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
256258 if (llvm::timeTraceProfilerEnabled()) {
257259 SmallString<128> Path(Clang->getFrontendOpts().OutputFile);
258260 llvm::sys::path::replace_extension(Path, "json");
261 if (!Clang->getFrontendOpts().TimeTracePath.empty()) {
262 // replace the suffix to '.json' directly
263 SmallString<128> TracePath(Clang->getFrontendOpts().TimeTracePath);
264 if (llvm::sys::fs::is_directory(TracePath))
265 llvm::sys::path::append(TracePath, llvm::sys::path::filename(Path));
266 Path.assign(TracePath);
267 }
259268 if (auto profilerOutput = Clang->createOutputFile(
260269 Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false,
261270 /*useTemporary=*/false)) {
262271 llvm::timeTraceProfilerWrite(*profilerOutput);
263 // FIXME(ibiryukov): make profilerOutput flush in destructor instead.
264 profilerOutput->flush();
272 profilerOutput.reset();
265273 llvm::timeTraceProfilerCleanup();
266274 Clang->clearOutputFiles(false);
267275 }
src/zig_clang_cc1as_main.cpp+25-3
......@@ -137,6 +137,9 @@ struct AssemblerInvocation {
137137 unsigned IncrementalLinkerCompatible : 1;
138138 unsigned EmbedBitcode : 1;
139139
140 /// Whether to emit DWARF unwind info.
141 EmitDwarfUnwindType EmitDwarfUnwind;
142
140143 /// The name of the relocation model to use.
141144 std::string RelocationModel;
142145
......@@ -144,6 +147,9 @@ struct AssemblerInvocation {
144147 /// otherwise.
145148 std::string TargetABI;
146149
150 /// Darwin target variant triple, the variant of the deployment target
151 /// for which the code is being compiled.
152 llvm::Optional<llvm::Triple> DarwinTargetVariantTriple;
147153 /// @}
148154
149155public:
......@@ -164,6 +170,7 @@ public:
164170 Dwarf64 = 0;
165171 DwarfVersion = 0;
166172 EmbedBitcode = 0;
173 EmitDwarfUnwind = EmitDwarfUnwindType::Default;
167174 }
168175
169176 static bool CreateFromArgs(AssemblerInvocation &Res,
......@@ -209,6 +216,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
209216
210217 // Target Options
211218 Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
219 if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))
220 Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());
221
212222 Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
213223 Opts.Features = Args.getAllArgValues(OPT_target_feature);
214224
......@@ -311,6 +321,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
311321 .Default(0);
312322 }
313323
324 if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {
325 Opts.EmitDwarfUnwind =
326 llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())
327 .Case("always", EmitDwarfUnwindType::Always)
328 .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)
329 .Case("default", EmitDwarfUnwindType::Default);
330 }
331
314332 return Success;
315333}
316334
......@@ -361,6 +379,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
361379 assert(MRI && "Unable to create target register info!");
362380
363381 MCTargetOptions MCOptions;
382 MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
383
364384 std::unique_ptr<MCAsmInfo> MAI(
365385 TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
366386 assert(MAI && "Unable to create target asm info!");
......@@ -407,6 +427,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
407427 // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
408428 std::unique_ptr<MCObjectFileInfo> MOFI(
409429 TheTarget->createMCObjectFileInfo(Ctx, PIC));
430 if (Opts.DarwinTargetVariantTriple)
431 MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
410432 Ctx.setObjectFileInfo(MOFI.get());
411433
412434 if (Opts.SaveTemporaryLabels)
......@@ -455,7 +477,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
455477
456478 std::unique_ptr<MCCodeEmitter> CE;
457479 if (Opts.ShowEncoding)
458 CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
480 CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
459481 std::unique_ptr<MCAsmBackend> MAB(
460482 TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
461483
......@@ -475,7 +497,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
475497 }
476498
477499 std::unique_ptr<MCCodeEmitter> CE(
478 TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
500 TheTarget->createMCCodeEmitter(*MCII, Ctx));
479501 std::unique_ptr<MCAsmBackend> MAB(
480502 TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
481503 assert(MAB && "Unable to create asm backend!");
......@@ -497,7 +519,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
497519 if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {
498520 MCSection *AsmLabel = Ctx.getMachOSection(
499521 "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
500 Str.get()->SwitchSection(AsmLabel);
522 Str.get()->switchSection(AsmLabel);
501523 Str.get()->emitZeros(1);
502524 }
503525
src/zig_clang_driver.cpp+41-25
......@@ -410,18 +410,18 @@ int ZigClang_main(int Argc, const char **Argv) {
410410 if (ClangCLMode) {
411411 // Arguments in "CL" are prepended.
412412 llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");
413 if (OptCL.hasValue()) {
413 if (OptCL) {
414414 SmallVector<const char *, 8> PrependedOpts;
415 getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts);
415 getCLEnvVarOptions(OptCL.value(), Saver, PrependedOpts);
416416
417417 // Insert right after the program name to prepend to the argument list.
418418 Args.insert(Args.begin() + 1, PrependedOpts.begin(), PrependedOpts.end());
419419 }
420420 // Arguments in "_CL_" are appended.
421421 llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_");
422 if (Opt_CL_.hasValue()) {
422 if (Opt_CL_) {
423423 SmallVector<const char *, 8> AppendedOpts;
424 getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts);
424 getCLEnvVarOptions(Opt_CL_.value(), Saver, AppendedOpts);
425425
426426 // Insert at the end of the argument list to append.
427427 Args.append(AppendedOpts.begin(), AppendedOpts.end());
......@@ -488,32 +488,39 @@ int ZigClang_main(int Argc, const char **Argv) {
488488 }
489489
490490 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args));
491
492 Driver::ReproLevel ReproLevel = Driver::ReproLevel::OnCrash;
493 if (Arg *A = C->getArgs().getLastArg(options::OPT_gen_reproducer_eq)) {
494 auto Level = llvm::StringSwitch<Optional<Driver::ReproLevel>>(A->getValue())
495 .Case("off", Driver::ReproLevel::Off)
496 .Case("crash", Driver::ReproLevel::OnCrash)
497 .Case("error", Driver::ReproLevel::OnError)
498 .Case("always", Driver::ReproLevel::Always)
499 .Default(None);
500 if (!Level) {
501 llvm::errs() << "Unknown value for " << A->getSpelling() << ": '"
502 << A->getValue() << "'\n";
503 return 1;
504 }
505 ReproLevel = *Level;
506 }
507 if (!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"))
508 ReproLevel = Driver::ReproLevel::Always;
509
491510 int Res = 1;
492511 bool IsCrash = false;
512 Driver::CommandStatus CommandStatus = Driver::CommandStatus::Ok;
513 // Pretend the first command failed if ReproStatus is Always.
514 const Command *FailingCommand = nullptr;
515 if (!C->getJobs().empty())
516 FailingCommand = &*C->getJobs().begin();
493517 if (C && !C->containsError()) {
494518 SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
495519 Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
496520
497 // Force a crash to test the diagnostics.
498 if (TheDriver.GenReproducer) {
499 Diags.Report(diag::err_drv_force_crash)
500 << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH");
501
502 // Pretend that every command failed.
503 FailingCommands.clear();
504 for (const auto &J : C->getJobs())
505 if (const Command *C = dyn_cast<Command>(&J))
506 FailingCommands.push_back(std::make_pair(-1, C));
507
508 // Print the bug report message that would be printed if we did actually
509 // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH.
510 if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"))
511 llvm::dbgs() << llvm::getBugReportMsg();
512 }
513
514521 for (const auto &P : FailingCommands) {
515522 int CommandRes = P.first;
516 const Command *FailingCommand = P.second;
523 FailingCommand = P.second;
517524 if (!Res)
518525 Res = CommandRes;
519526
......@@ -532,13 +539,22 @@ int ZigClang_main(int Argc, const char **Argv) {
532539 // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
533540 IsCrash |= CommandRes > 128;
534541#endif
535 if (IsCrash) {
536 TheDriver.generateCompilationDiagnostics(*C, *FailingCommand);
542 CommandStatus =
543 IsCrash ? Driver::CommandStatus::Crash : Driver::CommandStatus::Error;
544 if (IsCrash)
537545 break;
538 }
539546 }
540547 }
541548
549 // Print the bug report message that would be printed if we did actually
550 // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH.
551 if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"))
552 llvm::dbgs() << llvm::getBugReportMsg();
553 if (FailingCommand != nullptr &&
554 TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel,
555 *C, *FailingCommand))
556 Res = 1;
557
542558 Diags.getClient()->finish();
543559
544560 if (!UseNewCC1Process && IsCrash) {
src/zig_llvm-ar.cpp+249-78
......@@ -18,10 +18,15 @@
1818#include "llvm/IR/LLVMContext.h"
1919#include "llvm/Object/Archive.h"
2020#include "llvm/Object/ArchiveWriter.h"
21#include "llvm/Object/COFFImportFile.h"
22#include "llvm/Object/ELFObjectFile.h"
2123#include "llvm/Object/IRObjectFile.h"
2224#include "llvm/Object/MachO.h"
2325#include "llvm/Object/ObjectFile.h"
2426#include "llvm/Object/SymbolicFile.h"
27#include "llvm/Object/TapiFile.h"
28#include "llvm/Object/Wasm.h"
29#include "llvm/Object/XCOFFObjectFile.h"
2530#include "llvm/Support/Chrono.h"
2631#include "llvm/Support/CommandLine.h"
2732#include "llvm/Support/ConvertUTF.h"
......@@ -54,6 +59,7 @@
5459#endif
5560
5661using namespace llvm;
62using namespace llvm::object;
5763
5864// The name this program was invoked as.
5965static StringRef ToolName;
......@@ -61,37 +67,36 @@ static StringRef ToolName;
6167// The basename of this program.
6268static StringRef Stem;
6369
64const char RanlibHelp[] = R"(OVERVIEW: LLVM Ranlib (llvm-ranlib)
65
66 This program generates an index to speed access to archives
67
68USAGE: llvm-ranlib <archive-file>
69
70OPTIONS:
71 -h --help - Display available options
72 -v --version - Display the version of this program
73 -D - Use zero for timestamps and uids/gids (default)
74 -U - Use actual timestamps and uids/gids
75)";
76
77const char ArHelp[] = R"(OVERVIEW: LLVM Archiver
78
79USAGE: llvm-ar [options] [-]<operation>[modifiers] [relpos] [count] <archive> [files]
80 llvm-ar -M [<mri-script]
70static void printRanLibHelp(StringRef ToolName) {
71 outs() << "OVERVIEW: LLVM Ranlib\n\n"
72 << "This program generates an index to speed access to archives\n\n"
73 << "USAGE: " + ToolName + " <archive-file>\n\n"
74 << "OPTIONS:\n"
75 << " -h --help - Display available options\n"
76 << " -v --version - Display the version of this program\n"
77 << " -D - Use zero for timestamps and uids/gids "
78 "(default)\n"
79 << " -U - Use actual timestamps and uids/gids\n";
80}
8181
82OPTIONS:
82static void printArHelp(StringRef ToolName) {
83 const char ArOptions[] =
84 R"(OPTIONS:
8385 --format - archive format to create
8486 =default - default
8587 =gnu - gnu
8688 =darwin - darwin
8789 =bsd - bsd
90 =bigarchive - big archive (AIX OS)
8891 --plugin=<string> - ignored for compatibility
8992 -h --help - display this help and exit
93 --output - the directory to extract archive members to
9094 --rsp-quoting - quoting style for response files
9195 =posix - posix
9296 =windows - windows
9397 --thin - create a thin archive
9498 --version - print the version and exit
99 -X{32|64|32_64|any} - object mode (only for AIX OS)
95100 @<file> - read options from <file>
96101
97102OPERATIONS:
......@@ -126,11 +131,20 @@ MODIFIERS:
126131 [V] - display the version and exit
127132)";
128133
134 outs() << "OVERVIEW: LLVM Archiver\n\n"
135 << "USAGE: " + ToolName +
136 " [options] [-]<operation>[modifiers] [relpos] "
137 "[count] <archive> [files]\n"
138 << " " + ToolName + " -M [<mri-script]\n\n";
139
140 outs() << ArOptions;
141}
142
129143static void printHelpMessage() {
130144 if (Stem.contains_insensitive("ranlib"))
131 outs() << RanlibHelp;
145 printRanLibHelp(Stem);
132146 else if (Stem.contains_insensitive("ar"))
133 outs() << ArHelp;
147 printArHelp(Stem);
134148}
135149
136150static unsigned MRILineNumber;
......@@ -176,12 +190,16 @@ static void failIfError(Error E, Twine Context = "") {
176190 });
177191}
178192
193static void warn(Twine Message) {
194 WithColor::warning(errs(), ToolName) << Message << "\n";
195}
196
179197static SmallVector<const char *, 256> PositionalArgs;
180198
181199static bool MRI;
182200
183201namespace {
184enum Format { Default, GNU, BSD, DARWIN, Unknown };
202enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown };
185203}
186204
187205static Format FormatType = Default;
......@@ -201,6 +219,10 @@ enum ArchiveOperation {
201219 CreateSymTab ///< Create a symbol table in an existing archive
202220};
203221
222enum class BitModeTy { Bit32, Bit64, Bit32_64, Any, Unknown };
223
224static BitModeTy BitMode = BitModeTy::Bit32;
225
204226// Modifiers to follow operation to vary behavior
205227static bool AddAfter = false; ///< 'a' modifier
206228static bool AddBefore = false; ///< 'b' modifier
......@@ -230,6 +252,9 @@ static int CountParam = 0;
230252// command line.
231253static std::string ArchiveName;
232254
255// Output directory specified by --output.
256static std::string OutputDir;
257
233258static std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
234259static std::vector<std::unique_ptr<object::Archive>> Archives;
235260
......@@ -447,6 +472,19 @@ static ArchiveOperation parseCommandLine() {
447472 if (AddLibrary && Operation != QuickAppend)
448473 badUsage("the 'L' modifier is only applicable to the 'q' operation");
449474
475 if (!OutputDir.empty()) {
476 if (Operation != Extract)
477 badUsage("--output is only applicable to the 'x' operation");
478 bool IsDir = false;
479 // If OutputDir is not a directory, create_directories may still succeed if
480 // all components of the path prefix are directories. Test is_directory as
481 // well.
482 if (!sys::fs::create_directories(OutputDir))
483 sys::fs::is_directory(OutputDir, IsDir);
484 if (!IsDir)
485 fail("'" + OutputDir + "' is not a directory");
486 }
487
450488 // Return the parsed operation to the caller
451489 return Operation;
452490}
......@@ -547,7 +585,15 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {
547585 failIfError(ModeOrErr.takeError());
548586 sys::fs::perms Mode = ModeOrErr.get();
549587
550 llvm::StringRef outputFilePath = sys::path::filename(Name);
588 StringRef outputFilePath;
589 SmallString<128> path;
590 if (OutputDir.empty()) {
591 outputFilePath = sys::path::filename(Name);
592 } else {
593 sys::path::append(path, OutputDir, sys::path::filename(Name));
594 outputFilePath = path.str();
595 }
596
551597 if (Verbose)
552598 outs() << "x - " << outputFilePath << '\n';
553599
......@@ -600,6 +646,71 @@ static bool shouldCreateArchive(ArchiveOperation Op) {
600646 llvm_unreachable("Missing entry in covered switch.");
601647}
602648
649static bool is64BitSymbolicFile(SymbolicFile &Obj) {
650 if (auto *IRObj = dyn_cast<IRObjectFile>(&Obj))
651 return Triple(IRObj->getTargetTriple()).isArch64Bit();
652 if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj))
653 return false;
654 if (XCOFFObjectFile *XCOFFObj = dyn_cast<XCOFFObjectFile>(&Obj))
655 return XCOFFObj->is64Bit();
656 if (isa<WasmObjectFile>(Obj))
657 return false;
658 if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
659 return Tapi->is64Bit();
660 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
661 return MachO->is64Bit();
662 if (ELFObjectFileBase *ElfO = dyn_cast<ELFObjectFileBase>(&Obj))
663 return ElfO->getBytesInAddress() == 8;
664
665 fail("unsupported file format");
666}
667
668static bool isValidInBitMode(Binary &Bin) {
669 if (BitMode == BitModeTy::Bit32_64 || BitMode == BitModeTy::Any)
670 return true;
671
672 if (SymbolicFile *SymFile = dyn_cast<SymbolicFile>(&Bin)) {
673 bool Is64Bit = is64BitSymbolicFile(*SymFile);
674 if ((Is64Bit && (BitMode == BitModeTy::Bit32)) ||
675 (!Is64Bit && (BitMode == BitModeTy::Bit64)))
676 return false;
677 }
678 // In AIX "ar", non-object files are always considered to have a valid bit
679 // mode.
680 return true;
681}
682
683Expected<std::unique_ptr<Binary>> getAsBinary(const NewArchiveMember &NM,
684 LLVMContext *Context) {
685 auto BinaryOrErr = createBinary(NM.Buf->getMemBufferRef(), Context);
686 if (BinaryOrErr)
687 return std::move(*BinaryOrErr);
688 return BinaryOrErr.takeError();
689}
690
691Expected<std::unique_ptr<Binary>> getAsBinary(const Archive::Child &C,
692 LLVMContext *Context) {
693 return C.getAsBinary(Context);
694}
695
696template <class A> static bool isValidInBitMode(const A &Member) {
697 if (object::Archive::getDefaultKindForHost() != object::Archive::K_AIXBIG)
698 return true;
699 LLVMContext Context;
700 Expected<std::unique_ptr<Binary>> BinOrErr = getAsBinary(Member, &Context);
701 // In AIX "ar", if there is a non-object file member, it is never ignored due
702 // to the bit mode setting.
703 if (!BinOrErr) {
704 consumeError(BinOrErr.takeError());
705 return true;
706 }
707 return isValidInBitMode(*BinOrErr.get());
708}
709
710static void warnInvalidObjectForFileMode(Twine Name) {
711 warn("'" + Name + "' is not valid with the current object file mode");
712}
713
603714static void performReadOperation(ArchiveOperation Operation,
604715 object::Archive *OldArchive) {
605716 if (Operation == Extract && OldArchive->isThin())
......@@ -614,6 +725,10 @@ static void performReadOperation(ArchiveOperation Operation,
614725 failIfError(NameOrErr.takeError());
615726 StringRef Name = NameOrErr.get();
616727
728 // Check whether to ignore this object due to its bitness.
729 if (!isValidInBitMode(C))
730 continue;
731
617732 if (Filter) {
618733 auto I = find_if(Members, [Name](StringRef Path) {
619734 return comparePaths(Name, Path);
......@@ -652,8 +767,6 @@ static void performReadOperation(ArchiveOperation Operation,
652767static void addChildMember(std::vector<NewArchiveMember> &Members,
653768 const object::Archive::Child &M,
654769 bool FlattenArchive = false) {
655 if (Thin && !M.getParent()->isThin())
656 fail("cannot convert a regular archive to a thin one");
657770 Expected<NewArchiveMember> NMOrErr =
658771 NewArchiveMember::getOldMember(M, Deterministic);
659772 failIfError(NMOrErr.takeError());
......@@ -692,8 +805,7 @@ static void addChildMember(std::vector<NewArchiveMember> &Members,
692805 Members.push_back(std::move(*NMOrErr));
693806}
694807
695static void addMember(std::vector<NewArchiveMember> &Members,
696 StringRef FileName, bool FlattenArchive = false) {
808static NewArchiveMember getArchiveMember(StringRef FileName) {
697809 Expected<NewArchiveMember> NMOrErr =
698810 NewArchiveMember::getFile(FileName, Deterministic);
699811 failIfError(NMOrErr.takeError(), FileName);
......@@ -713,9 +825,24 @@ static void addMember(std::vector<NewArchiveMember> &Members,
713825 PathOrErr ? *PathOrErr : sys::path::convert_to_slash(FileName));
714826 }
715827 }
828 return std::move(*NMOrErr);
829}
830
831static void addMember(std::vector<NewArchiveMember> &Members,
832 NewArchiveMember &NM) {
833 Members.push_back(std::move(NM));
834}
835
836static void addMember(std::vector<NewArchiveMember> &Members,
837 StringRef FileName, bool FlattenArchive = false) {
838 NewArchiveMember NM = getArchiveMember(FileName);
839 if (!isValidInBitMode(NM)) {
840 warnInvalidObjectForFileMode(FileName);
841 return;
842 }
716843
717844 if (FlattenArchive &&
718 identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
845 identify_magic(NM.Buf->getBuffer()) == file_magic::archive) {
719846 object::Archive &Lib = readLibrary(FileName);
720847 // When creating thin archives, only flatten if the member is also thin.
721848 if (!Thin || Lib.isThin()) {
......@@ -727,7 +854,7 @@ static void addMember(std::vector<NewArchiveMember> &Members,
727854 return;
728855 }
729856 }
730 Members.push_back(std::move(*NMOrErr));
857 Members.push_back(std::move(NM));
731858}
732859
733860enum InsertAction {
......@@ -743,6 +870,9 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
743870 StringRef Name,
744871 std::vector<StringRef>::iterator &Pos,
745872 StringMap<int> &MemberCount) {
873 if (!isValidInBitMode(Member))
874 return IA_AddOldMember;
875
746876 if (Operation == QuickAppend || Members.empty())
747877 return IA_AddOldMember;
748878 auto MI = find_if(
......@@ -804,7 +934,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,
804934 Expected<StringRef> NameOrErr = Child.getName();
805935 failIfError(NameOrErr.takeError());
806936 std::string Name = std::string(NameOrErr.get());
807 if (comparePaths(Name, RelPos)) {
937 if (comparePaths(Name, RelPos) && isValidInBitMode(Child)) {
808938 assert(AddAfter || AddBefore);
809939 if (AddBefore)
810940 InsertPos = Pos;
......@@ -815,12 +945,25 @@ computeNewArchiveMembers(ArchiveOperation Operation,
815945 std::vector<StringRef>::iterator MemberI = Members.end();
816946 InsertAction Action =
817947 computeInsertAction(Operation, Child, Name, MemberI, MemberCount);
948
949 auto HandleNewMember = [](auto Member, auto &Members, auto &Child) {
950 NewArchiveMember NM = getArchiveMember(*Member);
951 if (isValidInBitMode(NM))
952 addMember(Members, NM);
953 else {
954 // If a new member is not a valid object for the bit mode, add
955 // the old member back.
956 warnInvalidObjectForFileMode(*Member);
957 addChildMember(Members, Child, /*FlattenArchive=*/Thin);
958 }
959 };
960
818961 switch (Action) {
819962 case IA_AddOldMember:
820963 addChildMember(Ret, Child, /*FlattenArchive=*/Thin);
821964 break;
822965 case IA_AddNewMember:
823 addMember(Ret, *MemberI);
966 HandleNewMember(MemberI, Ret, Child);
824967 break;
825968 case IA_Delete:
826969 break;
......@@ -828,7 +971,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,
828971 addChildMember(Moved, Child, /*FlattenArchive=*/Thin);
829972 break;
830973 case IA_MoveNewMember:
831 addMember(Moved, *MemberI);
974 HandleNewMember(MemberI, Moved, Child);
832975 break;
833976 }
834977 // When processing elements with the count param, we need to preserve the
......@@ -875,48 +1018,18 @@ computeNewArchiveMembers(ArchiveOperation Operation,
8751018 return Ret;
8761019}
8771020
878static object::Archive::Kind getDefaultForHost() {
879 return Triple(sys::getProcessTriple()).isOSDarwin()
880 ? object::Archive::K_DARWIN
881 : object::Archive::K_GNU;
882}
883
884static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) {
885 auto MemBufferRef = Member.Buf->getMemBufferRef();
886 Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
887 object::ObjectFile::createObjectFile(MemBufferRef);
888
889 if (OptionalObject)
890 return isa<object::MachOObjectFile>(**OptionalObject)
891 ? object::Archive::K_DARWIN
892 : object::Archive::K_GNU;
893
894 // squelch the error in case we had a non-object file
895 consumeError(OptionalObject.takeError());
896
897 // If we're adding a bitcode file to the archive, detect the Archive kind
898 // based on the target triple.
899 LLVMContext Context;
900 if (identify_magic(MemBufferRef.getBuffer()) == file_magic::bitcode) {
901 if (auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
902 MemBufferRef, file_magic::bitcode, &Context)) {
903 auto &IRObject = cast<object::IRObjectFile>(**ObjOrErr);
904 return Triple(IRObject.getTargetTriple()).isOSDarwin()
905 ? object::Archive::K_DARWIN
906 : object::Archive::K_GNU;
907 } else {
908 // Squelch the error in case this was not a SymbolicFile.
909 consumeError(ObjOrErr.takeError());
910 }
911 }
912
913 return getDefaultForHost();
914}
915
9161021static void performWriteOperation(ArchiveOperation Operation,
9171022 object::Archive *OldArchive,
9181023 std::unique_ptr<MemoryBuffer> OldArchiveBuf,
9191024 std::vector<NewArchiveMember> *NewMembersP) {
1025 if (OldArchive) {
1026 if (Thin && !OldArchive->isThin())
1027 fail("cannot convert a regular archive to a thin one");
1028
1029 if (OldArchive->isThin())
1030 Thin = true;
1031 }
1032
9201033 std::vector<NewArchiveMember> NewMembers;
9211034 if (!NewMembersP)
9221035 NewMembers = computeNewArchiveMembers(Operation, OldArchive);
......@@ -926,14 +1039,23 @@ static void performWriteOperation(ArchiveOperation Operation,
9261039 case Default:
9271040 if (Thin)
9281041 Kind = object::Archive::K_GNU;
929 else if (OldArchive)
1042 else if (OldArchive) {
9301043 Kind = OldArchive->kind();
931 else if (NewMembersP)
932 Kind = !NewMembersP->empty() ? getKindFromMember(NewMembersP->front())
933 : getDefaultForHost();
1044 if (Kind == object::Archive::K_BSD) {
1045 auto InferredKind = object::Archive::K_BSD;
1046 if (NewMembersP && !NewMembersP->empty())
1047 InferredKind = NewMembersP->front().detectKindFromObject();
1048 else if (!NewMembers.empty())
1049 InferredKind = NewMembers.front().detectKindFromObject();
1050 if (InferredKind == object::Archive::K_DARWIN)
1051 Kind = object::Archive::K_DARWIN;
1052 }
1053 } else if (NewMembersP)
1054 Kind = !NewMembersP->empty() ? NewMembersP->front().detectKindFromObject()
1055 : object::Archive::getDefaultKindForHost();
9341056 else
935 Kind = !NewMembers.empty() ? getKindFromMember(NewMembers.front())
936 : getDefaultForHost();
1057 Kind = !NewMembers.empty() ? NewMembers.front().detectKindFromObject()
1058 : object::Archive::getDefaultKindForHost();
9371059 break;
9381060 case GNU:
9391061 Kind = object::Archive::K_GNU;
......@@ -948,6 +1070,11 @@ static void performWriteOperation(ArchiveOperation Operation,
9481070 fail("only the gnu format has a thin mode");
9491071 Kind = object::Archive::K_DARWIN;
9501072 break;
1073 case BIGARCHIVE:
1074 if (Thin)
1075 fail("only the gnu format has a thin mode");
1076 Kind = object::Archive::K_AIXBIG;
1077 break;
9511078 case Unknown:
9521079 llvm_unreachable("");
9531080 }
......@@ -1029,8 +1156,7 @@ static int performOperation(ArchiveOperation Operation,
10291156 } else {
10301157 if (!Create) {
10311158 // Produce a warning if we should and we're creating the archive
1032 WithColor::warning(errs(), ToolName)
1033 << "creating " << ArchiveName << "\n";
1159 warn("creating " + ArchiveName);
10341160 }
10351161 }
10361162
......@@ -1073,8 +1199,12 @@ static void runMRIScript() {
10731199
10741200 switch (Command) {
10751201 case MRICommand::AddLib: {
1202 if (!Create)
1203 fail("no output archive has been opened");
10761204 object::Archive &Lib = readLibrary(Rest);
10771205 {
1206 if (Thin && !Lib.isThin())
1207 fail("cannot add a regular archive's contents to a thin archive");
10781208 Error Err = Error::success();
10791209 for (auto &Member : Lib.children(Err))
10801210 addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin);
......@@ -1083,6 +1213,8 @@ static void runMRIScript() {
10831213 break;
10841214 }
10851215 case MRICommand::AddMod:
1216 if (!Create)
1217 fail("no output archive has been opened");
10861218 addMember(NewMembers, Rest);
10871219 break;
10881220 case MRICommand::CreateThin:
......@@ -1095,6 +1227,8 @@ static void runMRIScript() {
10951227 if (Saved)
10961228 fail("file already saved");
10971229 ArchiveName = std::string(Rest);
1230 if (ArchiveName.empty())
1231 fail("missing archive name");
10981232 break;
10991233 case MRICommand::Delete: {
11001234 llvm::erase_if(NewMembers, [=](NewArchiveMember &M) {
......@@ -1116,7 +1250,8 @@ static void runMRIScript() {
11161250
11171251 // Nothing to do if not saved.
11181252 if (Saved)
1119 performOperation(ReplaceOrInsert, &NewMembers);
1253 performOperation(ReplaceOrInsert, /*OldArchive=*/nullptr,
1254 /*OldArchiveBuf=*/nullptr, &NewMembers);
11201255 exit(0);
11211256}
11221257
......@@ -1132,6 +1267,15 @@ static bool handleGenericOption(StringRef arg) {
11321267 return false;
11331268}
11341269
1270static BitModeTy getBitMode(const char *RawBitMode) {
1271 return StringSwitch<BitModeTy>(RawBitMode)
1272 .Case("32", BitModeTy::Bit32)
1273 .Case("64", BitModeTy::Bit64)
1274 .Case("32_64", BitModeTy::Bit32_64)
1275 .Case("any", BitModeTy::Any)
1276 .Default(BitModeTy::Unknown);
1277}
1278
11351279static const char *matchFlagWithArg(StringRef Expected,
11361280 ArrayRef<const char *>::iterator &ArgIt,
11371281 ArrayRef<const char *> Args) {
......@@ -1181,6 +1325,14 @@ static int ar_main(int argc, char **argv) {
11811325
11821326 cl::ExpandResponseFiles(Saver, getRspQuoting(makeArrayRef(argv, argc)), Argv);
11831327
1328 // Get BitMode from enviorment variable "OBJECT_MODE" for AIX OS, if
1329 // specified.
1330 if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) {
1331 BitMode = getBitMode(getenv("OBJECT_MODE"));
1332 if (BitMode == BitModeTy::Unknown)
1333 BitMode = BitModeTy::Bit32;
1334 }
1335
11841336 for (ArrayRef<const char *>::iterator ArgIt = Argv.begin();
11851337 ArgIt != Argv.end(); ++ArgIt) {
11861338 const char *Match = nullptr;
......@@ -1219,16 +1371,35 @@ static int ar_main(int argc, char **argv) {
12191371 .Case("gnu", GNU)
12201372 .Case("darwin", DARWIN)
12211373 .Case("bsd", BSD)
1374 .Case("bigarchive", BIGARCHIVE)
12221375 .Default(Unknown);
12231376 if (FormatType == Unknown)
12241377 fail(std::string("Invalid format ") + Match);
12251378 continue;
12261379 }
12271380
1381 if ((Match = matchFlagWithArg("output", ArgIt, Argv))) {
1382 OutputDir = Match;
1383 continue;
1384 }
1385
12281386 if (matchFlagWithArg("plugin", ArgIt, Argv) ||
12291387 matchFlagWithArg("rsp-quoting", ArgIt, Argv))
12301388 continue;
12311389
1390 if (strncmp(*ArgIt, "-X", 2) == 0) {
1391 if (object::Archive::getDefaultKindForHost() ==
1392 object::Archive::K_AIXBIG) {
1393 Match = *(*ArgIt + 2) != '\0' ? *ArgIt + 2 : *(++ArgIt);
1394 BitMode = getBitMode(Match);
1395 if (BitMode == BitModeTy::Unknown)
1396 fail(Twine("invalid bit mode: ") + Match);
1397 continue;
1398 } else {
1399 fail(Twine(*ArgIt) + " option not supported on non AIX OS");
1400 }
1401 }
1402
12321403 Options += *ArgIt + 1;
12331404 }
12341405