| author | |
| committer | |
| log | da8f81c78b5612464486172329a9162986eb5d6e |
| tree | 292e14965614fc6b59394ba6c4acc6fca3584bb2 |
| parent | dd095e506ab647e79b85541e23b3f696ce999d2f |
4 files changed, 130 insertions(+), 255 deletions(-)
src/zig_clang_cc1_main.cpp+56-66| ... | ... | @@ -26,6 +26,7 @@ |
| 26 | 26 | #include "clang/Frontend/Utils.h" |
| 27 | 27 | #include "clang/FrontendTool/Utils.h" |
| 28 | 28 | #include "llvm/ADT/Statistic.h" |
| 29 | #include "llvm/ADT/StringExtras.h" | |
| 29 | 30 | #include "llvm/Config/llvm-config.h" |
| 30 | 31 | #include "llvm/LinkAllPasses.h" |
| 31 | 32 | #include "llvm/MC/MCSubtargetInfo.h" |
| ... | ... | @@ -39,7 +40,6 @@ |
| 39 | 40 | #include "llvm/Support/ManagedStatic.h" |
| 40 | 41 | #include "llvm/Support/Path.h" |
| 41 | 42 | #include "llvm/Support/Process.h" |
| 42 | #include "llvm/Support/RISCVISAInfo.h" | |
| 43 | 43 | #include "llvm/Support/Signals.h" |
| 44 | 44 | #include "llvm/Support/TargetSelect.h" |
| 45 | 45 | #include "llvm/Support/TimeProfiler.h" |
| ... | ... | @@ -48,6 +48,7 @@ |
| 48 | 48 | #include "llvm/Target/TargetMachine.h" |
| 49 | 49 | #include "llvm/TargetParser/AArch64TargetParser.h" |
| 50 | 50 | #include "llvm/TargetParser/ARMTargetParser.h" |
| 51 | #include "llvm/TargetParser/RISCVISAInfo.h" | |
| 51 | 52 | #include <cstdio> |
| 52 | 53 | |
| 53 | 54 | #ifdef CLANG_HAVE_RLIMITS |
| ... | ... | @@ -78,64 +79,6 @@ static void LLVMErrorHandler(void *UserData, const char *Message, |
| 78 | 79 | } |
| 79 | 80 | |
| 80 | 81 | #ifdef CLANG_HAVE_RLIMITS |
| 81 | #if defined(__linux__) && defined(__PIE__) | |
| 82 | static size_t getCurrentStackAllocation() { | |
| 83 | // If we can't compute the current stack usage, allow for 512K of command | |
| 84 | // line arguments and environment. | |
| 85 | size_t Usage = 512 * 1024; | |
| 86 | if (FILE *StatFile = fopen("/proc/self/stat", "r")) { | |
| 87 | // We assume that the stack extends from its current address to the end of | |
| 88 | // the environment space. In reality, there is another string literal (the | |
| 89 | // program name) after the environment, but this is close enough (we only | |
| 90 | // need to be within 100K or so). | |
| 91 | unsigned long StackPtr, EnvEnd; | |
| 92 | // Disable silly GCC -Wformat warning that complains about length | |
| 93 | // modifiers on ignored format specifiers. We want to retain these | |
| 94 | // for documentation purposes even though they have no effect. | |
| 95 | #if defined(__GNUC__) && !defined(__clang__) | |
| 96 | #pragma GCC diagnostic push | |
| 97 | #pragma GCC diagnostic ignored "-Wformat" | |
| 98 | #endif | |
| 99 | if (fscanf(StatFile, | |
| 100 | "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu " | |
| 101 | "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu " | |
| 102 | "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d " | |
| 103 | "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d", | |
| 104 | &StackPtr, &EnvEnd) == 2) { | |
| 105 | #if defined(__GNUC__) && !defined(__clang__) | |
| 106 | #pragma GCC diagnostic pop | |
| 107 | #endif | |
| 108 | Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd; | |
| 109 | } | |
| 110 | fclose(StatFile); | |
| 111 | } | |
| 112 | return Usage; | |
| 113 | } | |
| 114 | ||
| 115 | #include <alloca.h> | |
| 116 | ||
| 117 | LLVM_ATTRIBUTE_NOINLINE | |
| 118 | static void ensureStackAddressSpace() { | |
| 119 | // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary | |
| 120 | // relatively close to the stack (they are only guaranteed to be 128MiB | |
| 121 | // apart). This results in crashes if we happen to heap-allocate more than | |
| 122 | // 128MiB before we reach our stack high-water mark. | |
| 123 | // | |
| 124 | // To avoid these crashes, ensure that we have sufficient virtual memory | |
| 125 | // pages allocated before we start running. | |
| 126 | size_t Curr = getCurrentStackAllocation(); | |
| 127 | const int kTargetStack = DesiredStackSize - 256 * 1024; | |
| 128 | if (Curr < kTargetStack) { | |
| 129 | volatile char *volatile Alloc = | |
| 130 | static_cast<volatile char *>(alloca(kTargetStack - Curr)); | |
| 131 | Alloc[0] = 0; | |
| 132 | Alloc[kTargetStack - Curr - 1] = 0; | |
| 133 | } | |
| 134 | } | |
| 135 | #else | |
| 136 | static void ensureStackAddressSpace() {} | |
| 137 | #endif | |
| 138 | ||
| 139 | 82 | /// Attempt to ensure that we have at least 8MiB of usable stack space. |
| 140 | 83 | static void ensureSufficientStack() { |
| 141 | 84 | struct rlimit rlim; |
| ... | ... | @@ -159,10 +102,6 @@ static void ensureSufficientStack() { |
| 159 | 102 | rlim.rlim_cur != DesiredStackSize) |
| 160 | 103 | return; |
| 161 | 104 | } |
| 162 | ||
| 163 | // We should now have a stack of size at least DesiredStackSize. Ensure | |
| 164 | // that we can actually use that much, if necessary. | |
| 165 | ensureStackAddressSpace(); | |
| 166 | 105 | } |
| 167 | 106 | #else |
| 168 | 107 | static void ensureSufficientStack() {} |
| ... | ... | @@ -208,9 +147,9 @@ static int PrintSupportedExtensions(std::string TargetStr) { |
| 208 | 147 | DescMap.insert({feature.Key, feature.Desc}); |
| 209 | 148 | |
| 210 | 149 | if (MachineTriple.isRISCV()) |
| 211 | llvm::riscvExtensionsHelp(DescMap); | |
| 150 | llvm::RISCVISAInfo::printSupportedExtensions(DescMap); | |
| 212 | 151 | else if (MachineTriple.isAArch64()) |
| 213 | llvm::AArch64::PrintSupportedExtensions(DescMap); | |
| 152 | llvm::AArch64::PrintSupportedExtensions(); | |
| 214 | 153 | else if (MachineTriple.isARM()) |
| 215 | 154 | llvm::ARM::PrintSupportedExtensions(DescMap); |
| 216 | 155 | else { |
| ... | ... | @@ -223,6 +162,52 @@ static int PrintSupportedExtensions(std::string TargetStr) { |
| 223 | 162 | return 0; |
| 224 | 163 | } |
| 225 | 164 | |
| 165 | static int PrintEnabledExtensions(const TargetOptions& TargetOpts) { | |
| 166 | std::string Error; | |
| 167 | const llvm::Target *TheTarget = | |
| 168 | llvm::TargetRegistry::lookupTarget(TargetOpts.Triple, Error); | |
| 169 | if (!TheTarget) { | |
| 170 | llvm::errs() << Error; | |
| 171 | return 1; | |
| 172 | } | |
| 173 | ||
| 174 | // Create a target machine using the input features, the triple information | |
| 175 | // and a dummy instance of llvm::TargetOptions. Note that this is _not_ the | |
| 176 | // same as the `clang::TargetOptions` instance we have access to here. | |
| 177 | llvm::TargetOptions BackendOptions; | |
| 178 | std::string FeaturesStr = llvm::join(TargetOpts.FeaturesAsWritten, ","); | |
| 179 | std::unique_ptr<llvm::TargetMachine> TheTargetMachine( | |
| 180 | TheTarget->createTargetMachine(TargetOpts.Triple, TargetOpts.CPU, FeaturesStr, BackendOptions, std::nullopt)); | |
| 181 | const llvm::Triple &MachineTriple = TheTargetMachine->getTargetTriple(); | |
| 182 | const llvm::MCSubtargetInfo *MCInfo = TheTargetMachine->getMCSubtargetInfo(); | |
| 183 | ||
| 184 | // Extract the feature names that are enabled for the given target. | |
| 185 | // We do that by capturing the key from the set of SubtargetFeatureKV entries | |
| 186 | // provided by MCSubtargetInfo, which match the '-target-feature' values. | |
| 187 | const std::vector<llvm::SubtargetFeatureKV> Features = | |
| 188 | MCInfo->getEnabledProcessorFeatures(); | |
| 189 | std::set<llvm::StringRef> EnabledFeatureNames; | |
| 190 | for (const llvm::SubtargetFeatureKV &feature : Features) | |
| 191 | EnabledFeatureNames.insert(feature.Key); | |
| 192 | ||
| 193 | if (MachineTriple.isAArch64()) | |
| 194 | llvm::AArch64::printEnabledExtensions(EnabledFeatureNames); | |
| 195 | else if (MachineTriple.isRISCV()) { | |
| 196 | llvm::StringMap<llvm::StringRef> DescMap; | |
| 197 | for (const llvm::SubtargetFeatureKV &feature : Features) | |
| 198 | DescMap.insert({feature.Key, feature.Desc}); | |
| 199 | llvm::RISCVISAInfo::printEnabledExtensions(MachineTriple.isArch64Bit(), | |
| 200 | EnabledFeatureNames, DescMap); | |
| 201 | } else { | |
| 202 | // The option was already checked in Driver::HandleImmediateArgs, | |
| 203 | // so we do not expect to get here if we are not a supported architecture. | |
| 204 | assert(0 && "Unhandled triple for --print-enabled-extensions option."); | |
| 205 | return 1; | |
| 206 | } | |
| 207 | ||
| 208 | return 0; | |
| 209 | } | |
| 210 | ||
| 226 | 211 | int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 227 | 212 | ensureSufficientStack(); |
| 228 | 213 | |
| ... | ... | @@ -256,7 +241,8 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 256 | 241 | |
| 257 | 242 | if (!Clang->getFrontendOpts().TimeTracePath.empty()) { |
| 258 | 243 | llvm::timeTraceProfilerInitialize( |
| 259 | Clang->getFrontendOpts().TimeTraceGranularity, Argv0); | |
| 244 | Clang->getFrontendOpts().TimeTraceGranularity, Argv0, | |
| 245 | Clang->getFrontendOpts().TimeTraceVerbose); | |
| 260 | 246 | } |
| 261 | 247 | // --print-supported-cpus takes priority over the actual compilation. |
| 262 | 248 | if (Clang->getFrontendOpts().PrintSupportedCPUs) |
| ... | ... | @@ -266,6 +252,10 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 266 | 252 | if (Clang->getFrontendOpts().PrintSupportedExtensions) |
| 267 | 253 | return PrintSupportedExtensions(Clang->getTargetOpts().Triple); |
| 268 | 254 | |
| 255 | // --print-enabled-extensions takes priority over the actual compilation. | |
| 256 | if (Clang->getFrontendOpts().PrintEnabledExtensions) | |
| 257 | return PrintEnabledExtensions(Clang->getTargetOpts()); | |
| 258 | ||
| 269 | 259 | // Infer the builtin include path if unspecified. |
| 270 | 260 | if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && |
| 271 | 261 | Clang->getHeaderSearchOpts().ResourceDir.empty()) |
src/zig_clang_cc1as_main.cpp+38-14| ... | ... | @@ -89,10 +89,17 @@ struct AssemblerInvocation { |
| 89 | 89 | /// @{ |
| 90 | 90 | |
| 91 | 91 | std::vector<std::string> IncludePaths; |
| 92 | LLVM_PREFERRED_TYPE(bool) | |
| 92 | 93 | unsigned NoInitialTextSection : 1; |
| 94 | LLVM_PREFERRED_TYPE(bool) | |
| 93 | 95 | unsigned SaveTemporaryLabels : 1; |
| 96 | LLVM_PREFERRED_TYPE(bool) | |
| 94 | 97 | unsigned GenDwarfForAssembly : 1; |
| 98 | LLVM_PREFERRED_TYPE(bool) | |
| 95 | 99 | unsigned RelaxELFRelocations : 1; |
| 100 | LLVM_PREFERRED_TYPE(bool) | |
| 101 | unsigned SSE2AVX : 1; | |
| 102 | LLVM_PREFERRED_TYPE(bool) | |
| 96 | 103 | unsigned Dwarf64 : 1; |
| 97 | 104 | unsigned DwarfVersion; |
| 98 | 105 | std::string DwarfDebugFlags; |
| ... | ... | @@ -117,7 +124,9 @@ struct AssemblerInvocation { |
| 117 | 124 | FT_Obj ///< Object file output. |
| 118 | 125 | }; |
| 119 | 126 | FileType OutputType; |
| 127 | LLVM_PREFERRED_TYPE(bool) | |
| 120 | 128 | unsigned ShowHelp : 1; |
| 129 | LLVM_PREFERRED_TYPE(bool) | |
| 121 | 130 | unsigned ShowVersion : 1; |
| 122 | 131 | |
| 123 | 132 | /// @} |
| ... | ... | @@ -125,19 +134,28 @@ struct AssemblerInvocation { |
| 125 | 134 | /// @{ |
| 126 | 135 | |
| 127 | 136 | unsigned OutputAsmVariant; |
| 137 | LLVM_PREFERRED_TYPE(bool) | |
| 128 | 138 | unsigned ShowEncoding : 1; |
| 139 | LLVM_PREFERRED_TYPE(bool) | |
| 129 | 140 | unsigned ShowInst : 1; |
| 130 | 141 | |
| 131 | 142 | /// @} |
| 132 | 143 | /// @name Assembler Options |
| 133 | 144 | /// @{ |
| 134 | 145 | |
| 146 | LLVM_PREFERRED_TYPE(bool) | |
| 135 | 147 | unsigned RelaxAll : 1; |
| 148 | LLVM_PREFERRED_TYPE(bool) | |
| 136 | 149 | unsigned NoExecStack : 1; |
| 150 | LLVM_PREFERRED_TYPE(bool) | |
| 137 | 151 | unsigned FatalWarnings : 1; |
| 152 | LLVM_PREFERRED_TYPE(bool) | |
| 138 | 153 | unsigned NoWarn : 1; |
| 154 | LLVM_PREFERRED_TYPE(bool) | |
| 139 | 155 | unsigned NoTypeCheck : 1; |
| 156 | LLVM_PREFERRED_TYPE(bool) | |
| 140 | 157 | unsigned IncrementalLinkerCompatible : 1; |
| 158 | LLVM_PREFERRED_TYPE(bool) | |
| 141 | 159 | unsigned EmbedBitcode : 1; |
| 142 | 160 | |
| 143 | 161 | /// Whether to emit DWARF unwind info. |
| ... | ... | @@ -145,8 +163,12 @@ struct AssemblerInvocation { |
| 145 | 163 | |
| 146 | 164 | // Whether to emit compact-unwind for non-canonical entries. |
| 147 | 165 | // Note: maybe overriden by other constraints. |
| 166 | LLVM_PREFERRED_TYPE(bool) | |
| 148 | 167 | unsigned EmitCompactUnwindNonCanonical : 1; |
| 149 | 168 | |
| 169 | LLVM_PREFERRED_TYPE(bool) | |
| 170 | unsigned Crel : 1; | |
| 171 | ||
| 150 | 172 | /// The name of the relocation model to use. |
| 151 | 173 | std::string RelocationModel; |
| 152 | 174 | |
| ... | ... | @@ -177,6 +199,7 @@ public: |
| 177 | 199 | ShowInst = 0; |
| 178 | 200 | ShowEncoding = 0; |
| 179 | 201 | RelaxAll = 0; |
| 202 | SSE2AVX = 0; | |
| 180 | 203 | NoExecStack = 0; |
| 181 | 204 | FatalWarnings = 0; |
| 182 | 205 | NoWarn = 0; |
| ... | ... | @@ -187,6 +210,7 @@ public: |
| 187 | 210 | EmbedBitcode = 0; |
| 188 | 211 | EmitDwarfUnwind = EmitDwarfUnwindType::Default; |
| 189 | 212 | EmitCompactUnwindNonCanonical = false; |
| 213 | Crel = false; | |
| 190 | 214 | } |
| 191 | 215 | |
| 192 | 216 | static bool CreateFromArgs(AssemblerInvocation &Res, |
| ... | ... | @@ -267,6 +291,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, |
| 267 | 291 | } |
| 268 | 292 | |
| 269 | 293 | Opts.RelaxELFRelocations = !Args.hasArg(OPT_mrelax_relocations_no); |
| 294 | Opts.SSE2AVX = Args.hasArg(OPT_msse2avx); | |
| 270 | 295 | if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32)) |
| 271 | 296 | Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64); |
| 272 | 297 | Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); |
| ... | ... | @@ -356,6 +381,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, |
| 356 | 381 | |
| 357 | 382 | Opts.EmitCompactUnwindNonCanonical = |
| 358 | 383 | Args.hasArg(OPT_femit_compact_unwind_non_canonical); |
| 384 | Opts.Crel = Args.hasArg(OPT_crel); | |
| 359 | 385 | |
| 360 | 386 | Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file); |
| 361 | 387 | |
| ... | ... | @@ -409,8 +435,14 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, |
| 409 | 435 | assert(MRI && "Unable to create target register info!"); |
| 410 | 436 | |
| 411 | 437 | MCTargetOptions MCOptions; |
| 438 | MCOptions.MCRelaxAll = Opts.RelaxAll; | |
| 412 | 439 | MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind; |
| 413 | 440 | MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical; |
| 441 | MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels; | |
| 442 | MCOptions.Crel = Opts.Crel; | |
| 443 | MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations; | |
| 444 | MCOptions.X86Sse2Avx = Opts.SSE2AVX; | |
| 445 | MCOptions.CompressDebugSections = Opts.CompressDebugSections; | |
| 414 | 446 | MCOptions.AsSecureLogFile = Opts.AsSecureLogFile; |
| 415 | 447 | |
| 416 | 448 | std::unique_ptr<MCAsmInfo> MAI( |
| ... | ... | @@ -419,9 +451,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, |
| 419 | 451 | |
| 420 | 452 | // Ensure MCAsmInfo initialization occurs before any use, otherwise sections |
| 421 | 453 | // may be created with a combination of default and explicit settings. |
| 422 | MAI->setCompressDebugSections(Opts.CompressDebugSections); | |
| 423 | 454 | |
| 424 | MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations); | |
| 425 | 455 | |
| 426 | 456 | bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; |
| 427 | 457 | if (Opts.OutputPath.empty()) |
| ... | ... | @@ -465,8 +495,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, |
| 465 | 495 | MOFI->setDarwinTargetVariantSDKVersion(Opts.DarwinTargetVariantSDKVersion); |
| 466 | 496 | Ctx.setObjectFileInfo(MOFI.get()); |
| 467 | 497 | |
| 468 | if (Opts.SaveTemporaryLabels) | |
| 469 | Ctx.setAllowTemporaryLabels(false); | |
| 470 | 498 | if (Opts.GenDwarfForAssembly) |
| 471 | 499 | Ctx.setGenDwarfForAssembly(true); |
| 472 | 500 | if (!Opts.DwarfDebugFlags.empty()) |
| ... | ... | @@ -503,6 +531,9 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, |
| 503 | 531 | MCOptions.MCNoWarn = Opts.NoWarn; |
| 504 | 532 | MCOptions.MCFatalWarnings = Opts.FatalWarnings; |
| 505 | 533 | MCOptions.MCNoTypeCheck = Opts.NoTypeCheck; |
| 534 | MCOptions.ShowMCInst = Opts.ShowInst; | |
| 535 | MCOptions.AsmVerbose = true; | |
| 536 | MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory; | |
| 506 | 537 | MCOptions.ABIName = Opts.TargetABI; |
| 507 | 538 | |
| 508 | 539 | // FIXME: There is a bit of code duplication with addPassesToEmitFile. |
| ... | ... | @@ -517,10 +548,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, |
| 517 | 548 | TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); |
| 518 | 549 | |
| 519 | 550 | auto FOut = std::make_unique<formatted_raw_ostream>(*Out); |
| 520 | Str.reset(TheTarget->createAsmStreamer( | |
| 521 | Ctx, std::move(FOut), /*asmverbose*/ true, | |
| 522 | /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB), | |
| 523 | Opts.ShowInst)); | |
| 551 | Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), IP, | |
| 552 | std::move(CE), std::move(MAB))); | |
| 524 | 553 | } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { |
| 525 | 554 | Str.reset(createNullStreamer(Ctx)); |
| 526 | 555 | } else { |
| ... | ... | @@ -543,9 +572,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, |
| 543 | 572 | |
| 544 | 573 | Triple T(Opts.Triple); |
| 545 | 574 | Str.reset(TheTarget->createMCObjectStreamer( |
| 546 | T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI, | |
| 547 | Opts.RelaxAll, Opts.IncrementalLinkerCompatible, | |
| 548 | /*DWARFMustBeAtTheEnd*/ true)); | |
| 575 | T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI)); | |
| 549 | 576 | Str.get()->initSections(Opts.NoExecStack, *STI); |
| 550 | 577 | } |
| 551 | 578 | |
| ... | ... | @@ -558,9 +585,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, |
| 558 | 585 | Str.get()->emitZeros(1); |
| 559 | 586 | } |
| 560 | 587 | |
| 561 | // Assembly to object compilation should leverage assembly info. | |
| 562 | Str->setUseAssemblerInfoForParsing(true); | |
| 563 | ||
| 564 | 588 | bool Failed = false; |
| 565 | 589 | |
| 566 | 590 | std::unique_ptr<MCAsmParser> Parser( |
src/zig_clang_driver.cpp+10-159| ... | ... | @@ -28,6 +28,7 @@ |
| 28 | 28 | #include "llvm/ADT/ArrayRef.h" |
| 29 | 29 | #include "llvm/ADT/SmallString.h" |
| 30 | 30 | #include "llvm/ADT/SmallVector.h" |
| 31 | #include "llvm/ADT/StringSet.h" | |
| 31 | 32 | #include "llvm/Option/ArgList.h" |
| 32 | 33 | #include "llvm/Option/OptTable.h" |
| 33 | 34 | #include "llvm/Option/Option.h" |
| ... | ... | @@ -41,7 +42,6 @@ |
| 41 | 42 | #include "llvm/Support/PrettyStackTrace.h" |
| 42 | 43 | #include "llvm/Support/Process.h" |
| 43 | 44 | #include "llvm/Support/Program.h" |
| 44 | #include "llvm/Support/Regex.h" | |
| 45 | 45 | #include "llvm/Support/Signals.h" |
| 46 | 46 | #include "llvm/Support/StringSaver.h" |
| 47 | 47 | #include "llvm/Support/TargetSelect.h" |
| ... | ... | @@ -73,136 +73,8 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { |
| 73 | 73 | return llvm::sys::fs::getMainExecutable(Argv0, P); |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | static const char *GetStableCStr(std::set<std::string> &SavedStrings, | |
| 77 | StringRef S) { | |
| 78 | return SavedStrings.insert(std::string(S)).first->c_str(); | |
| 79 | } | |
| 80 | ||
| 81 | /// ApplyOneQAOverride - Apply a list of edits to the input argument lists. | |
| 82 | /// | |
| 83 | /// The input string is a space separated list of edits to perform, | |
| 84 | /// they are applied in order to the input argument lists. Edits | |
| 85 | /// should be one of the following forms: | |
| 86 | /// | |
| 87 | /// '#': Silence information about the changes to the command line arguments. | |
| 88 | /// | |
| 89 | /// '^': Add FOO as a new argument at the beginning of the command line. | |
| 90 | /// | |
| 91 | /// '+': Add FOO as a new argument at the end of the command line. | |
| 92 | /// | |
| 93 | /// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command | |
| 94 | /// line. | |
| 95 | /// | |
| 96 | /// 'xOPTION': Removes all instances of the literal argument OPTION. | |
| 97 | /// | |
| 98 | /// 'XOPTION': Removes all instances of the literal argument OPTION, | |
| 99 | /// and the following argument. | |
| 100 | /// | |
| 101 | /// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' | |
| 102 | /// at the end of the command line. | |
| 103 | /// | |
| 104 | /// \param OS - The stream to write edit information to. | |
| 105 | /// \param Args - The vector of command line arguments. | |
| 106 | /// \param Edit - The override command to perform. | |
| 107 | /// \param SavedStrings - Set to use for storing string representations. | |
| 108 | static void ApplyOneQAOverride(raw_ostream &OS, | |
| 109 | SmallVectorImpl<const char*> &Args, | |
| 110 | StringRef Edit, | |
| 111 | std::set<std::string> &SavedStrings) { | |
| 112 | // This does not need to be efficient. | |
| 113 | ||
| 114 | if (Edit[0] == '^') { | |
| 115 | const char *Str = | |
| 116 | GetStableCStr(SavedStrings, Edit.substr(1)); | |
| 117 | OS << "### Adding argument " << Str << " at beginning\n"; | |
| 118 | Args.insert(Args.begin() + 1, Str); | |
| 119 | } else if (Edit[0] == '+') { | |
| 120 | const char *Str = | |
| 121 | GetStableCStr(SavedStrings, Edit.substr(1)); | |
| 122 | OS << "### Adding argument " << Str << " at end\n"; | |
| 123 | Args.push_back(Str); | |
| 124 | } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.ends_with("/") && | |
| 125 | Edit.slice(2, Edit.size() - 1).contains('/')) { | |
| 126 | StringRef MatchPattern = Edit.substr(2).split('/').first; | |
| 127 | StringRef ReplPattern = Edit.substr(2).split('/').second; | |
| 128 | ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); | |
| 129 | ||
| 130 | for (unsigned i = 1, e = Args.size(); i != e; ++i) { | |
| 131 | // Ignore end-of-line response file markers | |
| 132 | if (Args[i] == nullptr) | |
| 133 | continue; | |
| 134 | std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); | |
| 135 | ||
| 136 | if (Repl != Args[i]) { | |
| 137 | OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; | |
| 138 | Args[i] = GetStableCStr(SavedStrings, Repl); | |
| 139 | } | |
| 140 | } | |
| 141 | } else if (Edit[0] == 'x' || Edit[0] == 'X') { | |
| 142 | auto Option = Edit.substr(1); | |
| 143 | for (unsigned i = 1; i < Args.size();) { | |
| 144 | if (Option == Args[i]) { | |
| 145 | OS << "### Deleting argument " << Args[i] << '\n'; | |
| 146 | Args.erase(Args.begin() + i); | |
| 147 | if (Edit[0] == 'X') { | |
| 148 | if (i < Args.size()) { | |
| 149 | OS << "### Deleting argument " << Args[i] << '\n'; | |
| 150 | Args.erase(Args.begin() + i); | |
| 151 | } else | |
| 152 | OS << "### Invalid X edit, end of command line!\n"; | |
| 153 | } | |
| 154 | } else | |
| 155 | ++i; | |
| 156 | } | |
| 157 | } else if (Edit[0] == 'O') { | |
| 158 | for (unsigned i = 1; i < Args.size();) { | |
| 159 | const char *A = Args[i]; | |
| 160 | // Ignore end-of-line response file markers | |
| 161 | if (A == nullptr) | |
| 162 | continue; | |
| 163 | if (A[0] == '-' && A[1] == 'O' && | |
| 164 | (A[2] == '\0' || | |
| 165 | (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || | |
| 166 | ('0' <= A[2] && A[2] <= '9'))))) { | |
| 167 | OS << "### Deleting argument " << Args[i] << '\n'; | |
| 168 | Args.erase(Args.begin() + i); | |
| 169 | } else | |
| 170 | ++i; | |
| 171 | } | |
| 172 | OS << "### Adding argument " << Edit << " at end\n"; | |
| 173 | Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str())); | |
| 174 | } else { | |
| 175 | OS << "### Unrecognized edit: " << Edit << "\n"; | |
| 176 | } | |
| 177 | } | |
| 178 | ||
| 179 | /// ApplyQAOverride - Apply a space separated list of edits to the | |
| 180 | /// input argument lists. See ApplyOneQAOverride. | |
| 181 | static void ApplyQAOverride(SmallVectorImpl<const char*> &Args, | |
| 182 | const char *OverrideStr, | |
| 183 | std::set<std::string> &SavedStrings) { | |
| 184 | raw_ostream *OS = &llvm::errs(); | |
| 185 | ||
| 186 | if (OverrideStr[0] == '#') { | |
| 187 | ++OverrideStr; | |
| 188 | OS = &llvm::nulls(); | |
| 189 | } | |
| 190 | ||
| 191 | *OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n"; | |
| 192 | ||
| 193 | // This does not need to be efficient. | |
| 194 | ||
| 195 | const char *S = OverrideStr; | |
| 196 | while (*S) { | |
| 197 | const char *End = ::strchr(S, ' '); | |
| 198 | if (!End) | |
| 199 | End = S + strlen(S); | |
| 200 | if (End != S) | |
| 201 | ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings); | |
| 202 | S = End; | |
| 203 | if (*S != '\0') | |
| 204 | ++S; | |
| 205 | } | |
| 76 | static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) { | |
| 77 | return SavedStrings.insert(S).first->getKeyData(); | |
| 206 | 78 | } |
| 207 | 79 | |
| 208 | 80 | extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, |
| ... | ... | @@ -212,7 +84,7 @@ extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, |
| 212 | 84 | |
| 213 | 85 | static void insertTargetAndModeArgs(const ParsedClangName &NameParts, |
| 214 | 86 | SmallVectorImpl<const char *> &ArgVector, |
| 215 | std::set<std::string> &SavedStrings) { | |
| 87 | llvm::StringSet<> &SavedStrings) { | |
| 216 | 88 | // Put target and mode arguments at the start of argument list so that |
| 217 | 89 | // arguments specified in command line could override them. Avoid putting |
| 218 | 90 | // them at index 0, as an option like '-cc1' must remain the first. |
| ... | ... | @@ -320,28 +192,6 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, |
| 320 | 192 | DiagClient->setPrefix(std::string(ExeBasename)); |
| 321 | 193 | } |
| 322 | 194 | |
| 323 | static void SetInstallDir(SmallVectorImpl<const char *> &argv, | |
| 324 | Driver &TheDriver, bool CanonicalPrefixes) { | |
| 325 | // Attempt to find the original path used to invoke the driver, to determine | |
| 326 | // the installed path. We do this manually, because we want to support that | |
| 327 | // path being a symlink. | |
| 328 | SmallString<128> InstalledPath(argv[0]); | |
| 329 | ||
| 330 | // Do a PATH lookup, if there are no directory components. | |
| 331 | if (llvm::sys::path::filename(InstalledPath) == InstalledPath) | |
| 332 | if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName( | |
| 333 | llvm::sys::path::filename(InstalledPath.str()))) | |
| 334 | InstalledPath = *Tmp; | |
| 335 | ||
| 336 | // FIXME: We don't actually canonicalize this, we just make it absolute. | |
| 337 | if (CanonicalPrefixes) | |
| 338 | llvm::sys::fs::make_absolute(InstalledPath); | |
| 339 | ||
| 340 | StringRef InstalledPathParent(llvm::sys::path::parent_path(InstalledPath)); | |
| 341 | if (llvm::sys::fs::exists(InstalledPathParent)) | |
| 342 | TheDriver.setInstalledDir(InstalledPathParent); | |
| 343 | } | |
| 344 | ||
| 345 | 195 | static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV, |
| 346 | 196 | const llvm::ToolContext &ToolContext) { |
| 347 | 197 | // If we call the cc1 tool from the clangDriver library (through |
| ... | ... | @@ -363,8 +213,9 @@ static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV, |
| 363 | 213 | if (Tool == "-cc1as") |
| 364 | 214 | return cc1as_main(ArrayRef(ArgV).slice(2), ArgV[0], GetExecutablePathVP); |
| 365 | 215 | // Reject unknown tools. |
| 366 | llvm::errs() << "error: unknown integrated tool '" << Tool << "'. " | |
| 367 | << "Valid tools include '-cc1' and '-cc1as'.\n"; | |
| 216 | llvm::errs() | |
| 217 | << "error: unknown integrated tool '" << Tool << "'. " | |
| 218 | << "Valid tools include '-cc1' and '-cc1as'.\n"; | |
| 368 | 219 | return 1; |
| 369 | 220 | } |
| 370 | 221 | |
| ... | ... | @@ -435,12 +286,13 @@ static int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContex |
| 435 | 286 | } |
| 436 | 287 | } |
| 437 | 288 | |
| 438 | std::set<std::string> SavedStrings; | |
| 289 | llvm::StringSet<> SavedStrings; | |
| 439 | 290 | // Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the |
| 440 | 291 | // scenes. |
| 441 | 292 | if (const char *OverrideStr = ::getenv("CCC_OVERRIDE_OPTIONS")) { |
| 442 | 293 | // FIXME: Driver shouldn't take extra initial argument. |
| 443 | ApplyQAOverride(Args, OverrideStr, SavedStrings); | |
| 294 | driver::applyOverrideOptions(Args, OverrideStr, SavedStrings, | |
| 295 | &llvm::errs()); | |
| 444 | 296 | } |
| 445 | 297 | |
| 446 | 298 | std::string Path = GetExecutablePath(ToolContext.Path, CanonicalPrefixes); |
| ... | ... | @@ -478,7 +330,6 @@ static int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContex |
| 478 | 330 | ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); |
| 479 | 331 | |
| 480 | 332 | Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); |
| 481 | SetInstallDir(Args, TheDriver, CanonicalPrefixes); | |
| 482 | 333 | auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(ProgName); |
| 483 | 334 | TheDriver.setTargetAndMode(TargetAndMode); |
| 484 | 335 | // If -canonical-prefixes is set, GetExecutablePath will have resolved Path |
src/zig_llvm-ar.cpp+26-16| ... | ... | @@ -65,7 +65,7 @@ static void printRanLibHelp(StringRef ToolName) { |
| 65 | 65 | << "USAGE: " + ToolName + " archive...\n\n" |
| 66 | 66 | << "OPTIONS:\n" |
| 67 | 67 | << " -h --help - Display available options\n" |
| 68 | << " -v --version - Display the version of this program\n" | |
| 68 | << " -V --version - Display the version of this program\n" | |
| 69 | 69 | << " -D - Use zero for timestamps and uids/gids " |
| 70 | 70 | "(default)\n" |
| 71 | 71 | << " -U - Use actual timestamps and uids/gids\n" |
| ... | ... | @@ -82,6 +82,7 @@ static void printArHelp(StringRef ToolName) { |
| 82 | 82 | =darwin - darwin |
| 83 | 83 | =bsd - bsd |
| 84 | 84 | =bigarchive - big archive (AIX OS) |
| 85 | =coff - coff | |
| 85 | 86 | --plugin=<string> - ignored for compatibility |
| 86 | 87 | -h --help - display this help and exit |
| 87 | 88 | --output - the directory to extract archive members to |
| ... | ... | @@ -193,7 +194,7 @@ static SmallVector<const char *, 256> PositionalArgs; |
| 193 | 194 | static bool MRI; |
| 194 | 195 | |
| 195 | 196 | namespace { |
| 196 | enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown }; | |
| 197 | enum Format { Default, GNU, COFF, BSD, DARWIN, BIGARCHIVE, Unknown }; | |
| 197 | 198 | } |
| 198 | 199 | |
| 199 | 200 | static Format FormatType = Default; |
| ... | ... | @@ -670,7 +671,7 @@ Expected<std::unique_ptr<Binary>> getAsBinary(const Archive::Child &C, |
| 670 | 671 | } |
| 671 | 672 | |
| 672 | 673 | template <class A> static bool isValidInBitMode(const A &Member) { |
| 673 | if (object::Archive::getDefaultKindForHost() != object::Archive::K_AIXBIG) | |
| 674 | if (object::Archive::getDefaultKind() != object::Archive::K_AIXBIG) | |
| 674 | 675 | return true; |
| 675 | 676 | LLVMContext Context; |
| 676 | 677 | Expected<std::unique_ptr<Binary>> BinOrErr = getAsBinary(Member, &Context); |
| ... | ... | @@ -1025,25 +1026,35 @@ static void performWriteOperation(ArchiveOperation Operation, |
| 1025 | 1026 | Kind = object::Archive::K_GNU; |
| 1026 | 1027 | else if (OldArchive) { |
| 1027 | 1028 | Kind = OldArchive->kind(); |
| 1028 | if (Kind == object::Archive::K_BSD) { | |
| 1029 | auto InferredKind = object::Archive::K_BSD; | |
| 1029 | std::optional<object::Archive::Kind> AltKind; | |
| 1030 | if (Kind == object::Archive::K_BSD) | |
| 1031 | AltKind = object::Archive::K_DARWIN; | |
| 1032 | else if (Kind == object::Archive::K_GNU && !OldArchive->hasSymbolTable()) | |
| 1033 | // If there is no symbol table, we can't tell GNU from COFF format | |
| 1034 | // from the old archive type. | |
| 1035 | AltKind = object::Archive::K_COFF; | |
| 1036 | if (AltKind) { | |
| 1037 | auto InferredKind = Kind; | |
| 1030 | 1038 | if (NewMembersP && !NewMembersP->empty()) |
| 1031 | 1039 | InferredKind = NewMembersP->front().detectKindFromObject(); |
| 1032 | 1040 | else if (!NewMembers.empty()) |
| 1033 | 1041 | InferredKind = NewMembers.front().detectKindFromObject(); |
| 1034 | if (InferredKind == object::Archive::K_DARWIN) | |
| 1035 | Kind = object::Archive::K_DARWIN; | |
| 1042 | if (InferredKind == AltKind) | |
| 1043 | Kind = *AltKind; | |
| 1036 | 1044 | } |
| 1037 | 1045 | } else if (NewMembersP) |
| 1038 | 1046 | Kind = !NewMembersP->empty() ? NewMembersP->front().detectKindFromObject() |
| 1039 | : object::Archive::getDefaultKindForHost(); | |
| 1047 | : object::Archive::getDefaultKind(); | |
| 1040 | 1048 | else |
| 1041 | 1049 | Kind = !NewMembers.empty() ? NewMembers.front().detectKindFromObject() |
| 1042 | : object::Archive::getDefaultKindForHost(); | |
| 1050 | : object::Archive::getDefaultKind(); | |
| 1043 | 1051 | break; |
| 1044 | 1052 | case GNU: |
| 1045 | 1053 | Kind = object::Archive::K_GNU; |
| 1046 | 1054 | break; |
| 1055 | case COFF: | |
| 1056 | Kind = object::Archive::K_COFF; | |
| 1057 | break; | |
| 1047 | 1058 | case BSD: |
| 1048 | 1059 | if (Thin) |
| 1049 | 1060 | fail("only the gnu format has a thin mode"); |
| ... | ... | @@ -1331,7 +1342,7 @@ static int ar_main(int argc, char **argv) { |
| 1331 | 1342 | |
| 1332 | 1343 | // Get BitMode from enviorment variable "OBJECT_MODE" for AIX OS, if |
| 1333 | 1344 | // specified. |
| 1334 | if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) { | |
| 1345 | if (object::Archive::getDefaultKind() == object::Archive::K_AIXBIG) { | |
| 1335 | 1346 | BitMode = getBitMode(getenv("OBJECT_MODE")); |
| 1336 | 1347 | if (BitMode == BitModeTy::Unknown) |
| 1337 | 1348 | BitMode = BitModeTy::Bit32; |
| ... | ... | @@ -1376,6 +1387,7 @@ static int ar_main(int argc, char **argv) { |
| 1376 | 1387 | .Case("darwin", DARWIN) |
| 1377 | 1388 | .Case("bsd", BSD) |
| 1378 | 1389 | .Case("bigarchive", BIGARCHIVE) |
| 1390 | .Case("coff", COFF) | |
| 1379 | 1391 | .Default(Unknown); |
| 1380 | 1392 | if (FormatType == Unknown) |
| 1381 | 1393 | fail(std::string("Invalid format ") + Match); |
| ... | ... | @@ -1392,8 +1404,7 @@ static int ar_main(int argc, char **argv) { |
| 1392 | 1404 | continue; |
| 1393 | 1405 | |
| 1394 | 1406 | if (strncmp(*ArgIt, "-X", 2) == 0) { |
| 1395 | if (object::Archive::getDefaultKindForHost() == | |
| 1396 | object::Archive::K_AIXBIG) { | |
| 1407 | if (object::Archive::getDefaultKind() == object::Archive::K_AIXBIG) { | |
| 1397 | 1408 | Match = *(*ArgIt + 2) != '\0' ? *ArgIt + 2 : *(++ArgIt); |
| 1398 | 1409 | BitMode = getBitMode(Match); |
| 1399 | 1410 | if (BitMode == BitModeTy::Unknown) |
| ... | ... | @@ -1428,12 +1439,11 @@ static int ranlib_main(int argc, char **argv) { |
| 1428 | 1439 | } else if (arg.front() == 'h') { |
| 1429 | 1440 | printHelpMessage(); |
| 1430 | 1441 | return 0; |
| 1431 | } else if (arg.front() == 'v') { | |
| 1442 | } else if (arg.front() == 'V') { | |
| 1432 | 1443 | cl::PrintVersionMessage(); |
| 1433 | 1444 | return 0; |
| 1434 | 1445 | } else if (arg.front() == 'X') { |
| 1435 | if (object::Archive::getDefaultKindForHost() == | |
| 1436 | object::Archive::K_AIXBIG) { | |
| 1446 | if (object::Archive::getDefaultKind() == object::Archive::K_AIXBIG) { | |
| 1437 | 1447 | HasAIXXOption = true; |
| 1438 | 1448 | arg.consume_front("X"); |
| 1439 | 1449 | const char *Xarg = arg.data(); |
| ... | ... | @@ -1464,7 +1474,7 @@ static int ranlib_main(int argc, char **argv) { |
| 1464 | 1474 | } |
| 1465 | 1475 | } |
| 1466 | 1476 | |
| 1467 | if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) { | |
| 1477 | if (object::Archive::getDefaultKind() == object::Archive::K_AIXBIG) { | |
| 1468 | 1478 | // If not specify -X option, get BitMode from enviorment variable |
| 1469 | 1479 | // "OBJECT_MODE" for AIX OS if specify. |
| 1470 | 1480 | if (!HasAIXXOption) { |