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()...@@ -108,9 +108,9 @@ else()
108 set(ZIG_USE_LLVM_CONFIG OFF CACHE BOOL "use llvm-config to find LLVM libraries")108 set(ZIG_USE_LLVM_CONFIG OFF CACHE BOOL "use llvm-config to find LLVM libraries")
109endif()109endif()
110110
111find_package(llvm 14)111find_package(llvm 15)
112find_package(clang 14)112find_package(clang 15)
113find_package(lld 14)113find_package(lld 15)
114114
115if(ZIG_STATIC_ZLIB)115if(ZIG_STATIC_ZLIB)
116 list(REMOVE_ITEM LLVM_LIBRARIES "-lz")116 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...@@ -17,9 +17,9 @@ find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h
17if(${LLVM_LINK_MODE} STREQUAL "shared")17if(${LLVM_LINK_MODE} STREQUAL "shared")
18 find_library(CLANG_LIBRARIES18 find_library(CLANG_LIBRARIES
19 NAMES19 NAMES
20 libclang-cpp.so.1420 libclang-cpp.so.15
21 clang-cpp-14.021 clang-cpp-15.0
22 clang-cpp14022 clang-cpp150
23 clang-cpp23 clang-cpp
24 NAMES_PER_DIR24 NAMES_PER_DIR
25 HINTS "${LLVM_LIBDIRS}"25 HINTS "${LLVM_LIBDIRS}"
cmake/Findlld.cmake+16-16
...@@ -9,21 +9,21 @@...@@ -9,21 +9,21 @@
9find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h9find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h
10 HINTS ${LLVM_INCLUDE_DIRS}10 HINTS ${LLVM_INCLUDE_DIRS}
11 PATHS11 PATHS
12 /usr/lib/llvm-14/include12 /usr/lib/llvm-15/include
13 /usr/local/llvm140/include13 /usr/local/llvm150/include
14 /usr/local/llvm14/include14 /usr/local/llvm15/include
15 /usr/local/opt/llvm@14/include15 /usr/local/opt/llvm@15/include
16 /opt/homebrew/opt/llvm@14/include16 /opt/homebrew/opt/llvm@15/include
17 /mingw64/include)17 /mingw64/include)
1818
19find_library(LLD_LIBRARY NAMES lld-14.0 lld140 lld NAMES_PER_DIR19find_library(LLD_LIBRARY NAMES lld-15.0 lld150 lld NAMES_PER_DIR
20 HINTS ${LLVM_LIBDIRS}20 HINTS ${LLVM_LIBDIRS}
21 PATHS21 PATHS
22 /usr/lib/llvm-14/lib22 /usr/lib/llvm-15/lib
23 /usr/local/llvm140/lib23 /usr/local/llvm150/lib
24 /usr/local/llvm14/lib24 /usr/local/llvm15/lib
25 /usr/local/opt/llvm@14/lib25 /usr/local/opt/llvm@15/lib
26 /opt/homebrew/opt/llvm@14/lib26 /opt/homebrew/opt/llvm@15/lib
27)27)
28if(EXISTS ${LLD_LIBRARY})28if(EXISTS ${LLD_LIBRARY})
29 set(LLD_LIBRARIES ${LLD_LIBRARY})29 set(LLD_LIBRARIES ${LLD_LIBRARY})
...@@ -34,11 +34,11 @@ else()...@@ -34,11 +34,11 @@ else()
34 HINTS ${LLVM_LIBDIRS}34 HINTS ${LLVM_LIBDIRS}
35 PATHS35 PATHS
36 ${LLD_LIBDIRS}36 ${LLD_LIBDIRS}
37 /usr/lib/llvm-14/lib37 /usr/lib/llvm-15/lib
38 /usr/local/llvm140/lib38 /usr/local/llvm150/lib
39 /usr/local/llvm14/lib39 /usr/local/llvm15/lib
40 /usr/local/opt/llvm@14/lib40 /usr/local/opt/llvm@15/lib
41 /opt/homebrew/opt/llvm@14/lib41 /opt/homebrew/opt/llvm@15/lib
42 /mingw64/lib42 /mingw64/lib
43 /c/msys64/mingw64/lib43 /c/msys64/mingw64/lib
44 c:/msys64/mingw64/lib)44 c:/msys64/mingw64/lib)
cmake/Findllvm.cmake+6-6
...@@ -13,12 +13,12 @@ if(ZIG_USE_LLVM_CONFIG)...@@ -13,12 +13,12 @@ if(ZIG_USE_LLVM_CONFIG)
13 while(1)13 while(1)
14 unset(LLVM_CONFIG_EXE CACHE)14 unset(LLVM_CONFIG_EXE CACHE)
15 find_program(LLVM_CONFIG_EXE15 find_program(LLVM_CONFIG_EXE
16 NAMES llvm-config-14 llvm-config-14.0 llvm-config140 llvm-config14 llvm-config NAMES_PER_DIR16 NAMES llvm-config-15 llvm-config-15.0 llvm-config150 llvm-config15 llvm-config NAMES_PER_DIR
17 PATHS17 PATHS
18 "/mingw64/bin"18 "/mingw64/bin"
19 "/c/msys64/mingw64/bin"19 "/c/msys64/mingw64/bin"
20 "c:/msys64/mingw64/bin"20 "c:/msys64/mingw64/bin"
21 "C:/Libraries/llvm-14.0.0/bin")21 "C:/Libraries/llvm-15.0.0/bin")
2222
23 if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND")23 if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND")
24 if (DEFINED LLVM_CONFIG_ERROR_MESSAGE)24 if (DEFINED LLVM_CONFIG_ERROR_MESSAGE)
...@@ -35,9 +35,9 @@ if(ZIG_USE_LLVM_CONFIG)...@@ -35,9 +35,9 @@ if(ZIG_USE_LLVM_CONFIG)
35 OUTPUT_STRIP_TRAILING_WHITESPACE)35 OUTPUT_STRIP_TRAILING_WHITESPACE)
3636
37 get_filename_component(LLVM_CONFIG_DIR "${LLVM_CONFIG_EXE}" DIRECTORY)37 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)
39 # Save the error message, in case this is the last llvm-config we find39 # 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
42 # Ignore this directory and try the search again42 # Ignore this directory and try the search again
43 list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}")43 list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}")
...@@ -61,9 +61,9 @@ if(ZIG_USE_LLVM_CONFIG)...@@ -61,9 +61,9 @@ if(ZIG_USE_LLVM_CONFIG)
61 if (LLVM_CONFIG_ERROR) 61 if (LLVM_CONFIG_ERROR)
62 # Save the error message, in case this is the last llvm-config we find62 # Save the error message, in case this is the last llvm-config we find
63 if (ZIG_SHARED_LLVM)63 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")
65 else()65 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")
67 endif()67 endif()
6868
69 # Ignore this directory and try the search again69 # 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) {...@@ -212,7 +212,9 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
212 bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),212 bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),
213 Argv, Diags, Argv0);213 Argv, Diags, Argv0);
214214
215 if (Clang->getFrontendOpts().TimeTrace) {215 if (Clang->getFrontendOpts().TimeTrace ||
216 !Clang->getFrontendOpts().TimeTracePath.empty()) {
217 Clang->getFrontendOpts().TimeTrace = 1;
216 llvm::timeTraceProfilerInitialize(218 llvm::timeTraceProfilerInitialize(
217 Clang->getFrontendOpts().TimeTraceGranularity, Argv0);219 Clang->getFrontendOpts().TimeTraceGranularity, Argv0);
218 }220 }
...@@ -256,12 +258,18 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {...@@ -256,12 +258,18 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
256 if (llvm::timeTraceProfilerEnabled()) {258 if (llvm::timeTraceProfilerEnabled()) {
257 SmallString<128> Path(Clang->getFrontendOpts().OutputFile);259 SmallString<128> Path(Clang->getFrontendOpts().OutputFile);
258 llvm::sys::path::replace_extension(Path, "json");260 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 }
259 if (auto profilerOutput = Clang->createOutputFile(268 if (auto profilerOutput = Clang->createOutputFile(
260 Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false,269 Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false,
261 /*useTemporary=*/false)) {270 /*useTemporary=*/false)) {
262 llvm::timeTraceProfilerWrite(*profilerOutput);271 llvm::timeTraceProfilerWrite(*profilerOutput);
263 // FIXME(ibiryukov): make profilerOutput flush in destructor instead.272 profilerOutput.reset();
264 profilerOutput->flush();
265 llvm::timeTraceProfilerCleanup();273 llvm::timeTraceProfilerCleanup();
266 Clang->clearOutputFiles(false);274 Clang->clearOutputFiles(false);
267 }275 }
src/zig_clang_cc1as_main.cpp+25-3
...@@ -137,6 +137,9 @@ struct AssemblerInvocation {...@@ -137,6 +137,9 @@ struct AssemblerInvocation {
137 unsigned IncrementalLinkerCompatible : 1;137 unsigned IncrementalLinkerCompatible : 1;
138 unsigned EmbedBitcode : 1;138 unsigned EmbedBitcode : 1;
139139
140 /// Whether to emit DWARF unwind info.
141 EmitDwarfUnwindType EmitDwarfUnwind;
142
140 /// The name of the relocation model to use.143 /// The name of the relocation model to use.
141 std::string RelocationModel;144 std::string RelocationModel;
142145
...@@ -144,6 +147,9 @@ struct AssemblerInvocation {...@@ -144,6 +147,9 @@ struct AssemblerInvocation {
144 /// otherwise.147 /// otherwise.
145 std::string TargetABI;148 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;
147 /// @}153 /// @}
148154
149public:155public:
...@@ -164,6 +170,7 @@ public:...@@ -164,6 +170,7 @@ public:
164 Dwarf64 = 0;170 Dwarf64 = 0;
165 DwarfVersion = 0;171 DwarfVersion = 0;
166 EmbedBitcode = 0;172 EmbedBitcode = 0;
173 EmitDwarfUnwind = EmitDwarfUnwindType::Default;
167 }174 }
168175
169 static bool CreateFromArgs(AssemblerInvocation &Res,176 static bool CreateFromArgs(AssemblerInvocation &Res,
...@@ -209,6 +216,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,...@@ -209,6 +216,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
209216
210 // Target Options217 // Target Options
211 Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));218 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
212 Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));222 Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
213 Opts.Features = Args.getAllArgValues(OPT_target_feature);223 Opts.Features = Args.getAllArgValues(OPT_target_feature);
214224
...@@ -311,6 +321,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,...@@ -311,6 +321,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
311 .Default(0);321 .Default(0);
312 }322 }
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
314 return Success;332 return Success;
315}333}
316334
...@@ -361,6 +379,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,...@@ -361,6 +379,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
361 assert(MRI && "Unable to create target register info!");379 assert(MRI && "Unable to create target register info!");
362380
363 MCTargetOptions MCOptions;381 MCTargetOptions MCOptions;
382 MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
383
364 std::unique_ptr<MCAsmInfo> MAI(384 std::unique_ptr<MCAsmInfo> MAI(
365 TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));385 TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
366 assert(MAI && "Unable to create target asm info!");386 assert(MAI && "Unable to create target asm info!");
...@@ -407,6 +427,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,...@@ -407,6 +427,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
407 // MCObjectFileInfo needs a MCContext reference in order to initialize itself.427 // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
408 std::unique_ptr<MCObjectFileInfo> MOFI(428 std::unique_ptr<MCObjectFileInfo> MOFI(
409 TheTarget->createMCObjectFileInfo(Ctx, PIC));429 TheTarget->createMCObjectFileInfo(Ctx, PIC));
430 if (Opts.DarwinTargetVariantTriple)
431 MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
410 Ctx.setObjectFileInfo(MOFI.get());432 Ctx.setObjectFileInfo(MOFI.get());
411433
412 if (Opts.SaveTemporaryLabels)434 if (Opts.SaveTemporaryLabels)
...@@ -455,7 +477,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,...@@ -455,7 +477,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
455477
456 std::unique_ptr<MCCodeEmitter> CE;478 std::unique_ptr<MCCodeEmitter> CE;
457 if (Opts.ShowEncoding)479 if (Opts.ShowEncoding)
458 CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));480 CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
459 std::unique_ptr<MCAsmBackend> MAB(481 std::unique_ptr<MCAsmBackend> MAB(
460 TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));482 TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
461483
...@@ -475,7 +497,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,...@@ -475,7 +497,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
475 }497 }
476498
477 std::unique_ptr<MCCodeEmitter> CE(499 std::unique_ptr<MCCodeEmitter> CE(
478 TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));500 TheTarget->createMCCodeEmitter(*MCII, Ctx));
479 std::unique_ptr<MCAsmBackend> MAB(501 std::unique_ptr<MCAsmBackend> MAB(
480 TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));502 TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
481 assert(MAB && "Unable to create asm backend!");503 assert(MAB && "Unable to create asm backend!");
...@@ -497,7 +519,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,...@@ -497,7 +519,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
497 if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {519 if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {
498 MCSection *AsmLabel = Ctx.getMachOSection(520 MCSection *AsmLabel = Ctx.getMachOSection(
499 "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());521 "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
500 Str.get()->SwitchSection(AsmLabel);522 Str.get()->switchSection(AsmLabel);
501 Str.get()->emitZeros(1);523 Str.get()->emitZeros(1);
502 }524 }
503525
src/zig_clang_driver.cpp+41-25
...@@ -410,18 +410,18 @@ int ZigClang_main(int Argc, const char **Argv) {...@@ -410,18 +410,18 @@ int ZigClang_main(int Argc, const char **Argv) {
410 if (ClangCLMode) {410 if (ClangCLMode) {
411 // Arguments in "CL" are prepended.411 // Arguments in "CL" are prepended.
412 llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");412 llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");
413 if (OptCL.hasValue()) {413 if (OptCL) {
414 SmallVector<const char *, 8> PrependedOpts;414 SmallVector<const char *, 8> PrependedOpts;
415 getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts);415 getCLEnvVarOptions(OptCL.value(), Saver, PrependedOpts);
416416
417 // Insert right after the program name to prepend to the argument list.417 // Insert right after the program name to prepend to the argument list.
418 Args.insert(Args.begin() + 1, PrependedOpts.begin(), PrependedOpts.end());418 Args.insert(Args.begin() + 1, PrependedOpts.begin(), PrependedOpts.end());
419 }419 }
420 // Arguments in "_CL_" are appended.420 // Arguments in "_CL_" are appended.
421 llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_");421 llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_");
422 if (Opt_CL_.hasValue()) {422 if (Opt_CL_) {
423 SmallVector<const char *, 8> AppendedOpts;423 SmallVector<const char *, 8> AppendedOpts;
424 getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts);424 getCLEnvVarOptions(Opt_CL_.value(), Saver, AppendedOpts);
425425
426 // Insert at the end of the argument list to append.426 // Insert at the end of the argument list to append.
427 Args.append(AppendedOpts.begin(), AppendedOpts.end());427 Args.append(AppendedOpts.begin(), AppendedOpts.end());
...@@ -488,32 +488,39 @@ int ZigClang_main(int Argc, const char **Argv) {...@@ -488,32 +488,39 @@ int ZigClang_main(int Argc, const char **Argv) {
488 }488 }
489489
490 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args));490 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
491 int Res = 1;510 int Res = 1;
492 bool IsCrash = false;511 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();
493 if (C && !C->containsError()) {517 if (C && !C->containsError()) {
494 SmallVector<std::pair<int, const Command *>, 4> FailingCommands;518 SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
495 Res = TheDriver.ExecuteCompilation(*C, FailingCommands);519 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
514 for (const auto &P : FailingCommands) {521 for (const auto &P : FailingCommands) {
515 int CommandRes = P.first;522 int CommandRes = P.first;
516 const Command *FailingCommand = P.second;523 FailingCommand = P.second;
517 if (!Res)524 if (!Res)
518 Res = CommandRes;525 Res = CommandRes;
519526
...@@ -532,13 +539,22 @@ int ZigClang_main(int Argc, const char **Argv) {...@@ -532,13 +539,22 @@ int ZigClang_main(int Argc, const char **Argv) {
532 // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html539 // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
533 IsCrash |= CommandRes > 128;540 IsCrash |= CommandRes > 128;
534#endif541#endif
535 if (IsCrash) {542 CommandStatus =
536 TheDriver.generateCompilationDiagnostics(*C, *FailingCommand);543 IsCrash ? Driver::CommandStatus::Crash : Driver::CommandStatus::Error;
544 if (IsCrash)
537 break;545 break;
538 }
539 }546 }
540 }547 }
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
542 Diags.getClient()->finish();558 Diags.getClient()->finish();
543559
544 if (!UseNewCC1Process && IsCrash) {560 if (!UseNewCC1Process && IsCrash) {
src/zig_llvm-ar.cpp+249-78
...@@ -18,10 +18,15 @@...@@ -18,10 +18,15 @@
18#include "llvm/IR/LLVMContext.h"18#include "llvm/IR/LLVMContext.h"
19#include "llvm/Object/Archive.h"19#include "llvm/Object/Archive.h"
20#include "llvm/Object/ArchiveWriter.h"20#include "llvm/Object/ArchiveWriter.h"
21#include "llvm/Object/COFFImportFile.h"
22#include "llvm/Object/ELFObjectFile.h"
21#include "llvm/Object/IRObjectFile.h"23#include "llvm/Object/IRObjectFile.h"
22#include "llvm/Object/MachO.h"24#include "llvm/Object/MachO.h"
23#include "llvm/Object/ObjectFile.h"25#include "llvm/Object/ObjectFile.h"
24#include "llvm/Object/SymbolicFile.h"26#include "llvm/Object/SymbolicFile.h"
27#include "llvm/Object/TapiFile.h"
28#include "llvm/Object/Wasm.h"
29#include "llvm/Object/XCOFFObjectFile.h"
25#include "llvm/Support/Chrono.h"30#include "llvm/Support/Chrono.h"
26#include "llvm/Support/CommandLine.h"31#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/ConvertUTF.h"32#include "llvm/Support/ConvertUTF.h"
...@@ -54,6 +59,7 @@...@@ -54,6 +59,7 @@
54#endif59#endif
5560
56using namespace llvm;61using namespace llvm;
62using namespace llvm::object;
5763
58// The name this program was invoked as.64// The name this program was invoked as.
59static StringRef ToolName;65static StringRef ToolName;
...@@ -61,37 +67,36 @@ static StringRef ToolName;...@@ -61,37 +67,36 @@ static StringRef ToolName;
61// The basename of this program.67// The basename of this program.
62static StringRef Stem;68static StringRef Stem;
6369
64const char RanlibHelp[] = R"(OVERVIEW: LLVM Ranlib (llvm-ranlib)70static void printRanLibHelp(StringRef ToolName) {
6571 outs() << "OVERVIEW: LLVM Ranlib\n\n"
66 This program generates an index to speed access to archives72 << "This program generates an index to speed access to archives\n\n"
6773 << "USAGE: " + ToolName + " <archive-file>\n\n"
68USAGE: llvm-ranlib <archive-file>74 << "OPTIONS:\n"
6975 << " -h --help - Display available options\n"
70OPTIONS:76 << " -v --version - Display the version of this program\n"
71 -h --help - Display available options77 << " -D - Use zero for timestamps and uids/gids "
72 -v --version - Display the version of this program78 "(default)\n"
73 -D - Use zero for timestamps and uids/gids (default)79 << " -U - Use actual timestamps and uids/gids\n";
74 -U - Use actual timestamps and uids/gids80}
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]
8181
82OPTIONS:82static void printArHelp(StringRef ToolName) {
83 const char ArOptions[] =
84 R"(OPTIONS:
83 --format - archive format to create85 --format - archive format to create
84 =default - default86 =default - default
85 =gnu - gnu87 =gnu - gnu
86 =darwin - darwin88 =darwin - darwin
87 =bsd - bsd89 =bsd - bsd
90 =bigarchive - big archive (AIX OS)
88 --plugin=<string> - ignored for compatibility91 --plugin=<string> - ignored for compatibility
89 -h --help - display this help and exit92 -h --help - display this help and exit
93 --output - the directory to extract archive members to
90 --rsp-quoting - quoting style for response files94 --rsp-quoting - quoting style for response files
91 =posix - posix95 =posix - posix
92 =windows - windows96 =windows - windows
93 --thin - create a thin archive97 --thin - create a thin archive
94 --version - print the version and exit98 --version - print the version and exit
99 -X{32|64|32_64|any} - object mode (only for AIX OS)
95 @<file> - read options from <file>100 @<file> - read options from <file>
96101
97OPERATIONS:102OPERATIONS:
...@@ -126,11 +131,20 @@ MODIFIERS:...@@ -126,11 +131,20 @@ MODIFIERS:
126 [V] - display the version and exit131 [V] - display the version and exit
127)";132)";
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
129static void printHelpMessage() {143static void printHelpMessage() {
130 if (Stem.contains_insensitive("ranlib"))144 if (Stem.contains_insensitive("ranlib"))
131 outs() << RanlibHelp;145 printRanLibHelp(Stem);
132 else if (Stem.contains_insensitive("ar"))146 else if (Stem.contains_insensitive("ar"))
133 outs() << ArHelp;147 printArHelp(Stem);
134}148}
135149
136static unsigned MRILineNumber;150static unsigned MRILineNumber;
...@@ -176,12 +190,16 @@ static void failIfError(Error E, Twine Context = "") {...@@ -176,12 +190,16 @@ static void failIfError(Error E, Twine Context = "") {
176 });190 });
177}191}
178192
193static void warn(Twine Message) {
194 WithColor::warning(errs(), ToolName) << Message << "\n";
195}
196
179static SmallVector<const char *, 256> PositionalArgs;197static SmallVector<const char *, 256> PositionalArgs;
180198
181static bool MRI;199static bool MRI;
182200
183namespace {201namespace {
184enum Format { Default, GNU, BSD, DARWIN, Unknown };202enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown };
185}203}
186204
187static Format FormatType = Default;205static Format FormatType = Default;
...@@ -201,6 +219,10 @@ enum ArchiveOperation {...@@ -201,6 +219,10 @@ enum ArchiveOperation {
201 CreateSymTab ///< Create a symbol table in an existing archive219 CreateSymTab ///< Create a symbol table in an existing archive
202};220};
203221
222enum class BitModeTy { Bit32, Bit64, Bit32_64, Any, Unknown };
223
224static BitModeTy BitMode = BitModeTy::Bit32;
225
204// Modifiers to follow operation to vary behavior226// Modifiers to follow operation to vary behavior
205static bool AddAfter = false; ///< 'a' modifier227static bool AddAfter = false; ///< 'a' modifier
206static bool AddBefore = false; ///< 'b' modifier228static bool AddBefore = false; ///< 'b' modifier
...@@ -230,6 +252,9 @@ static int CountParam = 0;...@@ -230,6 +252,9 @@ static int CountParam = 0;
230// command line.252// command line.
231static std::string ArchiveName;253static std::string ArchiveName;
232254
255// Output directory specified by --output.
256static std::string OutputDir;
257
233static std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;258static std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
234static std::vector<std::unique_ptr<object::Archive>> Archives;259static std::vector<std::unique_ptr<object::Archive>> Archives;
235260
...@@ -447,6 +472,19 @@ static ArchiveOperation parseCommandLine() {...@@ -447,6 +472,19 @@ static ArchiveOperation parseCommandLine() {
447 if (AddLibrary && Operation != QuickAppend)472 if (AddLibrary && Operation != QuickAppend)
448 badUsage("the 'L' modifier is only applicable to the 'q' operation");473 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
450 // Return the parsed operation to the caller488 // Return the parsed operation to the caller
451 return Operation;489 return Operation;
452}490}
...@@ -547,7 +585,15 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {...@@ -547,7 +585,15 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {
547 failIfError(ModeOrErr.takeError());585 failIfError(ModeOrErr.takeError());
548 sys::fs::perms Mode = ModeOrErr.get();586 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
551 if (Verbose)597 if (Verbose)
552 outs() << "x - " << outputFilePath << '\n';598 outs() << "x - " << outputFilePath << '\n';
553599
...@@ -600,6 +646,71 @@ static bool shouldCreateArchive(ArchiveOperation Op) {...@@ -600,6 +646,71 @@ static bool shouldCreateArchive(ArchiveOperation Op) {
600 llvm_unreachable("Missing entry in covered switch.");646 llvm_unreachable("Missing entry in covered switch.");
601}647}
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
603static void performReadOperation(ArchiveOperation Operation,714static void performReadOperation(ArchiveOperation Operation,
604 object::Archive *OldArchive) {715 object::Archive *OldArchive) {
605 if (Operation == Extract && OldArchive->isThin())716 if (Operation == Extract && OldArchive->isThin())
...@@ -614,6 +725,10 @@ static void performReadOperation(ArchiveOperation Operation,...@@ -614,6 +725,10 @@ static void performReadOperation(ArchiveOperation Operation,
614 failIfError(NameOrErr.takeError());725 failIfError(NameOrErr.takeError());
615 StringRef Name = NameOrErr.get();726 StringRef Name = NameOrErr.get();
616727
728 // Check whether to ignore this object due to its bitness.
729 if (!isValidInBitMode(C))
730 continue;
731
617 if (Filter) {732 if (Filter) {
618 auto I = find_if(Members, [Name](StringRef Path) {733 auto I = find_if(Members, [Name](StringRef Path) {
619 return comparePaths(Name, Path);734 return comparePaths(Name, Path);
...@@ -652,8 +767,6 @@ static void performReadOperation(ArchiveOperation Operation,...@@ -652,8 +767,6 @@ static void performReadOperation(ArchiveOperation Operation,
652static void addChildMember(std::vector<NewArchiveMember> &Members,767static void addChildMember(std::vector<NewArchiveMember> &Members,
653 const object::Archive::Child &M,768 const object::Archive::Child &M,
654 bool FlattenArchive = false) {769 bool FlattenArchive = false) {
655 if (Thin && !M.getParent()->isThin())
656 fail("cannot convert a regular archive to a thin one");
657 Expected<NewArchiveMember> NMOrErr =770 Expected<NewArchiveMember> NMOrErr =
658 NewArchiveMember::getOldMember(M, Deterministic);771 NewArchiveMember::getOldMember(M, Deterministic);
659 failIfError(NMOrErr.takeError());772 failIfError(NMOrErr.takeError());
...@@ -692,8 +805,7 @@ static void addChildMember(std::vector<NewArchiveMember> &Members,...@@ -692,8 +805,7 @@ static void addChildMember(std::vector<NewArchiveMember> &Members,
692 Members.push_back(std::move(*NMOrErr));805 Members.push_back(std::move(*NMOrErr));
693}806}
694807
695static void addMember(std::vector<NewArchiveMember> &Members,808static NewArchiveMember getArchiveMember(StringRef FileName) {
696 StringRef FileName, bool FlattenArchive = false) {
697 Expected<NewArchiveMember> NMOrErr =809 Expected<NewArchiveMember> NMOrErr =
698 NewArchiveMember::getFile(FileName, Deterministic);810 NewArchiveMember::getFile(FileName, Deterministic);
699 failIfError(NMOrErr.takeError(), FileName);811 failIfError(NMOrErr.takeError(), FileName);
...@@ -713,9 +825,24 @@ static void addMember(std::vector<NewArchiveMember> &Members,...@@ -713,9 +825,24 @@ static void addMember(std::vector<NewArchiveMember> &Members,
713 PathOrErr ? *PathOrErr : sys::path::convert_to_slash(FileName));825 PathOrErr ? *PathOrErr : sys::path::convert_to_slash(FileName));
714 }826 }
715 }827 }
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
717 if (FlattenArchive &&844 if (FlattenArchive &&
718 identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {845 identify_magic(NM.Buf->getBuffer()) == file_magic::archive) {
719 object::Archive &Lib = readLibrary(FileName);846 object::Archive &Lib = readLibrary(FileName);
720 // When creating thin archives, only flatten if the member is also thin.847 // When creating thin archives, only flatten if the member is also thin.
721 if (!Thin || Lib.isThin()) {848 if (!Thin || Lib.isThin()) {
...@@ -727,7 +854,7 @@ static void addMember(std::vector<NewArchiveMember> &Members,...@@ -727,7 +854,7 @@ static void addMember(std::vector<NewArchiveMember> &Members,
727 return;854 return;
728 }855 }
729 }856 }
730 Members.push_back(std::move(*NMOrErr));857 Members.push_back(std::move(NM));
731}858}
732859
733enum InsertAction {860enum InsertAction {
...@@ -743,6 +870,9 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,...@@ -743,6 +870,9 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
743 StringRef Name,870 StringRef Name,
744 std::vector<StringRef>::iterator &Pos,871 std::vector<StringRef>::iterator &Pos,
745 StringMap<int> &MemberCount) {872 StringMap<int> &MemberCount) {
873 if (!isValidInBitMode(Member))
874 return IA_AddOldMember;
875
746 if (Operation == QuickAppend || Members.empty())876 if (Operation == QuickAppend || Members.empty())
747 return IA_AddOldMember;877 return IA_AddOldMember;
748 auto MI = find_if(878 auto MI = find_if(
...@@ -804,7 +934,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,...@@ -804,7 +934,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,
804 Expected<StringRef> NameOrErr = Child.getName();934 Expected<StringRef> NameOrErr = Child.getName();
805 failIfError(NameOrErr.takeError());935 failIfError(NameOrErr.takeError());
806 std::string Name = std::string(NameOrErr.get());936 std::string Name = std::string(NameOrErr.get());
807 if (comparePaths(Name, RelPos)) {937 if (comparePaths(Name, RelPos) && isValidInBitMode(Child)) {
808 assert(AddAfter || AddBefore);938 assert(AddAfter || AddBefore);
809 if (AddBefore)939 if (AddBefore)
810 InsertPos = Pos;940 InsertPos = Pos;
...@@ -815,12 +945,25 @@ computeNewArchiveMembers(ArchiveOperation Operation,...@@ -815,12 +945,25 @@ computeNewArchiveMembers(ArchiveOperation Operation,
815 std::vector<StringRef>::iterator MemberI = Members.end();945 std::vector<StringRef>::iterator MemberI = Members.end();
816 InsertAction Action =946 InsertAction Action =
817 computeInsertAction(Operation, Child, Name, MemberI, MemberCount);947 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
818 switch (Action) {961 switch (Action) {
819 case IA_AddOldMember:962 case IA_AddOldMember:
820 addChildMember(Ret, Child, /*FlattenArchive=*/Thin);963 addChildMember(Ret, Child, /*FlattenArchive=*/Thin);
821 break;964 break;
822 case IA_AddNewMember:965 case IA_AddNewMember:
823 addMember(Ret, *MemberI);966 HandleNewMember(MemberI, Ret, Child);
824 break;967 break;
825 case IA_Delete:968 case IA_Delete:
826 break;969 break;
...@@ -828,7 +971,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,...@@ -828,7 +971,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,
828 addChildMember(Moved, Child, /*FlattenArchive=*/Thin);971 addChildMember(Moved, Child, /*FlattenArchive=*/Thin);
829 break;972 break;
830 case IA_MoveNewMember:973 case IA_MoveNewMember:
831 addMember(Moved, *MemberI);974 HandleNewMember(MemberI, Moved, Child);
832 break;975 break;
833 }976 }
834 // When processing elements with the count param, we need to preserve the977 // When processing elements with the count param, we need to preserve the
...@@ -875,48 +1018,18 @@ computeNewArchiveMembers(ArchiveOperation Operation,...@@ -875,48 +1018,18 @@ computeNewArchiveMembers(ArchiveOperation Operation,
875 return Ret;1018 return Ret;
876}1019}
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
916static void performWriteOperation(ArchiveOperation Operation,1021static void performWriteOperation(ArchiveOperation Operation,
917 object::Archive *OldArchive,1022 object::Archive *OldArchive,
918 std::unique_ptr<MemoryBuffer> OldArchiveBuf,1023 std::unique_ptr<MemoryBuffer> OldArchiveBuf,
919 std::vector<NewArchiveMember> *NewMembersP) {1024 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
920 std::vector<NewArchiveMember> NewMembers;1033 std::vector<NewArchiveMember> NewMembers;
921 if (!NewMembersP)1034 if (!NewMembersP)
922 NewMembers = computeNewArchiveMembers(Operation, OldArchive);1035 NewMembers = computeNewArchiveMembers(Operation, OldArchive);
...@@ -926,14 +1039,23 @@ static void performWriteOperation(ArchiveOperation Operation,...@@ -926,14 +1039,23 @@ static void performWriteOperation(ArchiveOperation Operation,
926 case Default:1039 case Default:
927 if (Thin)1040 if (Thin)
928 Kind = object::Archive::K_GNU;1041 Kind = object::Archive::K_GNU;
929 else if (OldArchive)1042 else if (OldArchive) {
930 Kind = OldArchive->kind();1043 Kind = OldArchive->kind();
931 else if (NewMembersP)1044 if (Kind == object::Archive::K_BSD) {
932 Kind = !NewMembersP->empty() ? getKindFromMember(NewMembersP->front())1045 auto InferredKind = object::Archive::K_BSD;
933 : getDefaultForHost();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();
934 else1056 else
935 Kind = !NewMembers.empty() ? getKindFromMember(NewMembers.front())1057 Kind = !NewMembers.empty() ? NewMembers.front().detectKindFromObject()
936 : getDefaultForHost();1058 : object::Archive::getDefaultKindForHost();
937 break;1059 break;
938 case GNU:1060 case GNU:
939 Kind = object::Archive::K_GNU;1061 Kind = object::Archive::K_GNU;
...@@ -948,6 +1070,11 @@ static void performWriteOperation(ArchiveOperation Operation,...@@ -948,6 +1070,11 @@ static void performWriteOperation(ArchiveOperation Operation,
948 fail("only the gnu format has a thin mode");1070 fail("only the gnu format has a thin mode");
949 Kind = object::Archive::K_DARWIN;1071 Kind = object::Archive::K_DARWIN;
950 break;1072 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;
951 case Unknown:1078 case Unknown:
952 llvm_unreachable("");1079 llvm_unreachable("");
953 }1080 }
...@@ -1029,8 +1156,7 @@ static int performOperation(ArchiveOperation Operation,...@@ -1029,8 +1156,7 @@ static int performOperation(ArchiveOperation Operation,
1029 } else {1156 } else {
1030 if (!Create) {1157 if (!Create) {
1031 // Produce a warning if we should and we're creating the archive1158 // Produce a warning if we should and we're creating the archive
1032 WithColor::warning(errs(), ToolName)1159 warn("creating " + ArchiveName);
1033 << "creating " << ArchiveName << "\n";
1034 }1160 }
1035 }1161 }
10361162
...@@ -1073,8 +1199,12 @@ static void runMRIScript() {...@@ -1073,8 +1199,12 @@ static void runMRIScript() {
10731199
1074 switch (Command) {1200 switch (Command) {
1075 case MRICommand::AddLib: {1201 case MRICommand::AddLib: {
1202 if (!Create)
1203 fail("no output archive has been opened");
1076 object::Archive &Lib = readLibrary(Rest);1204 object::Archive &Lib = readLibrary(Rest);
1077 {1205 {
1206 if (Thin && !Lib.isThin())
1207 fail("cannot add a regular archive's contents to a thin archive");
1078 Error Err = Error::success();1208 Error Err = Error::success();
1079 for (auto &Member : Lib.children(Err))1209 for (auto &Member : Lib.children(Err))
1080 addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin);1210 addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin);
...@@ -1083,6 +1213,8 @@ static void runMRIScript() {...@@ -1083,6 +1213,8 @@ static void runMRIScript() {
1083 break;1213 break;
1084 }1214 }
1085 case MRICommand::AddMod:1215 case MRICommand::AddMod:
1216 if (!Create)
1217 fail("no output archive has been opened");
1086 addMember(NewMembers, Rest);1218 addMember(NewMembers, Rest);
1087 break;1219 break;
1088 case MRICommand::CreateThin:1220 case MRICommand::CreateThin:
...@@ -1095,6 +1227,8 @@ static void runMRIScript() {...@@ -1095,6 +1227,8 @@ static void runMRIScript() {
1095 if (Saved)1227 if (Saved)
1096 fail("file already saved");1228 fail("file already saved");
1097 ArchiveName = std::string(Rest);1229 ArchiveName = std::string(Rest);
1230 if (ArchiveName.empty())
1231 fail("missing archive name");
1098 break;1232 break;
1099 case MRICommand::Delete: {1233 case MRICommand::Delete: {
1100 llvm::erase_if(NewMembers, [=](NewArchiveMember &M) {1234 llvm::erase_if(NewMembers, [=](NewArchiveMember &M) {
...@@ -1116,7 +1250,8 @@ static void runMRIScript() {...@@ -1116,7 +1250,8 @@ static void runMRIScript() {
11161250
1117 // Nothing to do if not saved.1251 // Nothing to do if not saved.
1118 if (Saved)1252 if (Saved)
1119 performOperation(ReplaceOrInsert, &NewMembers);1253 performOperation(ReplaceOrInsert, /*OldArchive=*/nullptr,
1254 /*OldArchiveBuf=*/nullptr, &NewMembers);
1120 exit(0);1255 exit(0);
1121}1256}
11221257
...@@ -1132,6 +1267,15 @@ static bool handleGenericOption(StringRef arg) {...@@ -1132,6 +1267,15 @@ static bool handleGenericOption(StringRef arg) {
1132 return false;1267 return false;
1133}1268}
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
1135static const char *matchFlagWithArg(StringRef Expected,1279static const char *matchFlagWithArg(StringRef Expected,
1136 ArrayRef<const char *>::iterator &ArgIt,1280 ArrayRef<const char *>::iterator &ArgIt,
1137 ArrayRef<const char *> Args) {1281 ArrayRef<const char *> Args) {
...@@ -1181,6 +1325,14 @@ static int ar_main(int argc, char **argv) {...@@ -1181,6 +1325,14 @@ static int ar_main(int argc, char **argv) {
11811325
1182 cl::ExpandResponseFiles(Saver, getRspQuoting(makeArrayRef(argv, argc)), Argv);1326 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
1184 for (ArrayRef<const char *>::iterator ArgIt = Argv.begin();1336 for (ArrayRef<const char *>::iterator ArgIt = Argv.begin();
1185 ArgIt != Argv.end(); ++ArgIt) {1337 ArgIt != Argv.end(); ++ArgIt) {
1186 const char *Match = nullptr;1338 const char *Match = nullptr;
...@@ -1219,16 +1371,35 @@ static int ar_main(int argc, char **argv) {...@@ -1219,16 +1371,35 @@ static int ar_main(int argc, char **argv) {
1219 .Case("gnu", GNU)1371 .Case("gnu", GNU)
1220 .Case("darwin", DARWIN)1372 .Case("darwin", DARWIN)
1221 .Case("bsd", BSD)1373 .Case("bsd", BSD)
1374 .Case("bigarchive", BIGARCHIVE)
1222 .Default(Unknown);1375 .Default(Unknown);
1223 if (FormatType == Unknown)1376 if (FormatType == Unknown)
1224 fail(std::string("Invalid format ") + Match);1377 fail(std::string("Invalid format ") + Match);
1225 continue;1378 continue;
1226 }1379 }
12271380
1381 if ((Match = matchFlagWithArg("output", ArgIt, Argv))) {
1382 OutputDir = Match;
1383 continue;
1384 }
1385
1228 if (matchFlagWithArg("plugin", ArgIt, Argv) ||1386 if (matchFlagWithArg("plugin", ArgIt, Argv) ||
1229 matchFlagWithArg("rsp-quoting", ArgIt, Argv))1387 matchFlagWithArg("rsp-quoting", ArgIt, Argv))
1230 continue;1388 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
1232 Options += *ArgIt + 1;1403 Options += *ArgIt + 1;
1233 }1404 }
12341405