| author | |
| committer | |
| log | 56f433b3d9fb18a634c51366d0b18b5025e19260 |
| tree | c4a2418f7c4e7bdd15cc0a5ee5c870c590200cc4 |
| parent | ba4cc03b4f0d71ac3e0147aa3dde449299ce8cd5 |
| signature | Commit is signed but in an unrecognized format. |
3 files changed, 83 insertions(+), 48 deletions(-)
src/zig_clang_cc1_main.cpp+21-27| ... | ... | @@ -12,11 +12,6 @@ |
| 12 | 12 | // |
| 13 | 13 | //===----------------------------------------------------------------------===// |
| 14 | 14 | |
| 15 | #if __GNUC__ >= 9 | |
| 16 | #pragma GCC diagnostic push | |
| 17 | #pragma GCC diagnostic ignored "-Winit-list-lifetime" | |
| 18 | #endif | |
| 19 | ||
| 20 | 15 | #include "clang/Basic/Stack.h" |
| 21 | 16 | #include "clang/Basic/TargetOptions.h" |
| 22 | 17 | #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" |
| ... | ... | @@ -207,12 +202,13 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 207 | 202 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); |
| 208 | 203 | TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; |
| 209 | 204 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); |
| 210 | bool Success = CompilerInvocation::CreateFromArgs( | |
| 211 | Clang->getInvocation(), Argv, Diags); | |
| 212 | ||
| 213 | if (Clang->getFrontendOpts().TimeTrace) | |
| 214 | llvm::timeTraceProfilerInitialize(/* granularity (us) */ 500); | |
| 205 | bool Success = | |
| 206 | CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Argv, Diags); | |
| 215 | 207 | |
| 208 | if (Clang->getFrontendOpts().TimeTrace) { | |
| 209 | llvm::timeTraceProfilerInitialize( | |
| 210 | Clang->getFrontendOpts().TimeTraceGranularity, Argv0); | |
| 211 | } | |
| 216 | 212 | // --print-supported-cpus takes priority over the actual compilation. |
| 217 | 213 | if (Clang->getFrontendOpts().PrintSupportedCPUs) |
| 218 | 214 | return PrintSupportedCPUs(Clang->getTargetOpts().Triple); |
| ... | ... | @@ -239,33 +235,30 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 239 | 235 | |
| 240 | 236 | // Execute the frontend actions. |
| 241 | 237 | { |
| 242 | llvm::TimeTraceScope TimeScope("ExecuteCompiler", StringRef("")); | |
| 238 | llvm::TimeTraceScope TimeScope("ExecuteCompiler"); | |
| 243 | 239 | Success = ExecuteCompilerInvocation(Clang.get()); |
| 244 | 240 | } |
| 245 | 241 | |
| 246 | 242 | // If any timers were active but haven't been destroyed yet, print their |
| 247 | 243 | // results now. This happens in -disable-free mode. |
| 248 | 244 | llvm::TimerGroup::printAll(llvm::errs()); |
| 245 | llvm::TimerGroup::clearAll(); | |
| 249 | 246 | |
| 250 | 247 | if (llvm::timeTraceProfilerEnabled()) { |
| 251 | 248 | SmallString<128> Path(Clang->getFrontendOpts().OutputFile); |
| 252 | 249 | llvm::sys::path::replace_extension(Path, "json"); |
| 253 | auto profilerOutput = | |
| 254 | Clang->createOutputFile(Path.str(), | |
| 255 | /*Binary=*/false, | |
| 256 | /*RemoveFileOnSignal=*/false, "", | |
| 257 | /*Extension=*/"json", | |
| 258 | /*useTemporary=*/false); | |
| 259 | ||
| 260 | llvm::timeTraceProfilerWrite(*profilerOutput); | |
| 261 | // FIXME(ibiryukov): make profilerOutput flush in destructor instead. | |
| 262 | profilerOutput->flush(); | |
| 263 | llvm::timeTraceProfilerCleanup(); | |
| 264 | ||
| 265 | llvm::errs() << "Time trace json-file dumped to " << Path.str() << "\n"; | |
| 266 | llvm::errs() | |
| 267 | << "Use chrome://tracing or Speedscope App " | |
| 268 | "(https://www.speedscope.app) for flamegraph visualization\n"; | |
| 250 | if (auto profilerOutput = | |
| 251 | Clang->createOutputFile(Path.str(), | |
| 252 | /*Binary=*/false, | |
| 253 | /*RemoveFileOnSignal=*/false, "", | |
| 254 | /*Extension=*/"json", | |
| 255 | /*useTemporary=*/false)) { | |
| 256 | ||
| 257 | llvm::timeTraceProfilerWrite(*profilerOutput); | |
| 258 | // FIXME(ibiryukov): make profilerOutput flush in destructor instead. | |
| 259 | profilerOutput->flush(); | |
| 260 | llvm::timeTraceProfilerCleanup(); | |
| 261 | } | |
| 269 | 262 | } |
| 270 | 263 | |
| 271 | 264 | // Our error handler depends on the Diagnostics object, which we're |
| ... | ... | @@ -281,3 +274,4 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 281 | 274 | |
| 282 | 275 | return !Success; |
| 283 | 276 | } |
| 277 |
src/zig_clang_cc1as_main.cpp+18-10| ... | ... | @@ -131,6 +131,7 @@ struct AssemblerInvocation { |
| 131 | 131 | unsigned RelaxAll : 1; |
| 132 | 132 | unsigned NoExecStack : 1; |
| 133 | 133 | unsigned FatalWarnings : 1; |
| 134 | unsigned NoWarn : 1; | |
| 134 | 135 | unsigned IncrementalLinkerCompatible : 1; |
| 135 | 136 | unsigned EmbedBitcode : 1; |
| 136 | 137 | |
| ... | ... | @@ -156,6 +157,7 @@ public: |
| 156 | 157 | RelaxAll = 0; |
| 157 | 158 | NoExecStack = 0; |
| 158 | 159 | FatalWarnings = 0; |
| 160 | NoWarn = 0; | |
| 159 | 161 | IncrementalLinkerCompatible = 0; |
| 160 | 162 | DwarfVersion = 0; |
| 161 | 163 | EmbedBitcode = 0; |
| ... | ... | @@ -179,7 +181,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, |
| 179 | 181 | const unsigned IncludedFlagsBitmask = options::CC1AsOption; |
| 180 | 182 | unsigned MissingArgIndex, MissingArgCount; |
| 181 | 183 | InputArgList Args = OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount, |
| 182 | IncludedFlagsBitmask); | |
| 184 | IncludedFlagsBitmask); | |
| 183 | 185 | |
| 184 | 186 | // Check for missing argument error. |
| 185 | 187 | if (MissingArgCount) { |
| ... | ... | @@ -285,6 +287,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, |
| 285 | 287 | Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); |
| 286 | 288 | Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); |
| 287 | 289 | Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); |
| 290 | Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn); | |
| 288 | 291 | Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); |
| 289 | 292 | Opts.TargetABI = Args.getLastArgValue(OPT_target_abi); |
| 290 | 293 | Opts.IncrementalLinkerCompatible = |
| ... | ... | @@ -313,7 +316,7 @@ getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) { |
| 313 | 316 | |
| 314 | 317 | std::error_code EC; |
| 315 | 318 | auto Out = std::make_unique<raw_fd_ostream>( |
| 316 | Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text)); | |
| 319 | Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_Text)); | |
| 317 | 320 | if (EC) { |
| 318 | 321 | Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message(); |
| 319 | 322 | return nullptr; |
| ... | ... | @@ -350,7 +353,9 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, |
| 350 | 353 | std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); |
| 351 | 354 | assert(MRI && "Unable to create target register info!"); |
| 352 | 355 | |
| 353 | std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple)); | |
| 356 | MCTargetOptions MCOptions; | |
| 357 | std::unique_ptr<MCAsmInfo> MAI( | |
| 358 | TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions)); | |
| 354 | 359 | assert(MAI && "Unable to create target asm info!"); |
| 355 | 360 | |
| 356 | 361 | // Ensure MCAsmInfo initialization occurs before any use, otherwise sections |
| ... | ... | @@ -374,7 +379,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, |
| 374 | 379 | // MCObjectFileInfo needs a MCContext reference in order to initialize itself. |
| 375 | 380 | std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); |
| 376 | 381 | |
| 377 | MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); | |
| 382 | MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr, &MCOptions); | |
| 378 | 383 | |
| 379 | 384 | bool PIC = false; |
| 380 | 385 | if (Opts.RelocationModel == "static") { |
| ... | ... | @@ -431,7 +436,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, |
| 431 | 436 | raw_pwrite_stream *Out = FDOS.get(); |
| 432 | 437 | std::unique_ptr<buffer_ostream> BOS; |
| 433 | 438 | |
| 434 | MCTargetOptions MCOptions; | |
| 439 | MCOptions.MCNoWarn = Opts.NoWarn; | |
| 440 | MCOptions.MCFatalWarnings = Opts.FatalWarnings; | |
| 435 | 441 | MCOptions.ABIName = Opts.TargetABI; |
| 436 | 442 | |
| 437 | 443 | // FIXME: There is a bit of code duplication with addPassesToEmitFile. |
| ... | ... | @@ -569,11 +575,11 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 569 | 575 | return 1; |
| 570 | 576 | |
| 571 | 577 | if (Asm.ShowHelp) { |
| 572 | const OptTable &Opts = getDriverOptTable(); | |
| 573 | Opts.PrintHelp(llvm::outs(), "clang -cc1as [options] file...", | |
| 574 | "Clang Integrated Assembler", | |
| 575 | /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0, | |
| 576 | /*ShowAllAliases=*/false); | |
| 578 | getDriverOptTable().PrintHelp( | |
| 579 | llvm::outs(), "clang -cc1as [options] file...", | |
| 580 | "Clang Integrated Assembler", | |
| 581 | /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0, | |
| 582 | /*ShowAllAliases=*/false); | |
| 577 | 583 | return 0; |
| 578 | 584 | } |
| 579 | 585 | |
| ... | ... | @@ -604,6 +610,8 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
| 604 | 610 | // If any timers were active but haven't been destroyed yet, print their |
| 605 | 611 | // results now. |
| 606 | 612 | TimerGroup::printAll(errs()); |
| 613 | TimerGroup::clearAll(); | |
| 607 | 614 | |
| 608 | 615 | return !!Failed; |
| 609 | 616 | } |
| 617 |
src/zig_clang_driver.cpp+44-11| ... | ... | @@ -13,6 +13,8 @@ |
| 13 | 13 | |
| 14 | 14 | #include "clang/Driver/Driver.h" |
| 15 | 15 | #include "clang/Basic/DiagnosticOptions.h" |
| 16 | #include "clang/Basic/Stack.h" | |
| 17 | #include "clang/Config/config.h" | |
| 16 | 18 | #include "clang/Driver/Compilation.h" |
| 17 | 19 | #include "clang/Driver/DriverDiagnostic.h" |
| 18 | 20 | #include "clang/Driver/Options.h" |
| ... | ... | @@ -29,6 +31,7 @@ |
| 29 | 31 | #include "llvm/Option/OptTable.h" |
| 30 | 32 | #include "llvm/Option/Option.h" |
| 31 | 33 | #include "llvm/Support/CommandLine.h" |
| 34 | #include "llvm/Support/CrashRecoveryContext.h" | |
| 32 | 35 | #include "llvm/Support/ErrorHandling.h" |
| 33 | 36 | #include "llvm/Support/FileSystem.h" |
| 34 | 37 | #include "llvm/Support/Host.h" |
| ... | ... | @@ -236,6 +239,8 @@ static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver, |
| 236 | 239 | *NumberSignPtr = '='; |
| 237 | 240 | } |
| 238 | 241 | |
| 242 | static int ExecuteCC1Tool(ArrayRef<const char *> argv); | |
| 243 | ||
| 239 | 244 | static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { |
| 240 | 245 | // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. |
| 241 | 246 | TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); |
| ... | ... | @@ -266,16 +271,21 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, |
| 266 | 271 | // This lets us create the DiagnosticsEngine with a properly-filled-out |
| 267 | 272 | // DiagnosticOptions instance. |
| 268 | 273 | static DiagnosticOptions * |
| 269 | CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) { | |
| 274 | CreateAndPopulateDiagOpts(ArrayRef<const char *> argv, bool &UseNewCC1Process) { | |
| 270 | 275 | auto *DiagOpts = new DiagnosticOptions; |
| 271 | const OptTable &Opts = getDriverOptTable(); | |
| 272 | 276 | unsigned MissingArgIndex, MissingArgCount; |
| 273 | InputArgList Args = | |
| 274 | Opts.ParseArgs(argv.slice(1), MissingArgIndex, MissingArgCount); | |
| 277 | InputArgList Args = getDriverOptTable().ParseArgs( | |
| 278 | argv.slice(1), MissingArgIndex, MissingArgCount); | |
| 275 | 279 | // We ignore MissingArgCount and the return value of ParseDiagnosticArgs. |
| 276 | 280 | // Any errors that would be diagnosed here will also be diagnosed later, |
| 277 | 281 | // when the DiagnosticsEngine actually exists. |
| 278 | 282 | (void)ParseDiagnosticArgs(*DiagOpts, Args); |
| 283 | ||
| 284 | UseNewCC1Process = | |
| 285 | Args.hasFlag(clang::driver::options::OPT_fno_integrated_cc1, | |
| 286 | clang::driver::options::OPT_fintegrated_cc1, | |
| 287 | /*Default=*/CLANG_SPAWN_CC1); | |
| 288 | ||
| 279 | 289 | return DiagOpts; |
| 280 | 290 | } |
| 281 | 291 | |
| ... | ... | @@ -301,11 +311,17 @@ static void SetInstallDir(SmallVectorImpl<const char *> &argv, |
| 301 | 311 | TheDriver.setInstalledDir(InstalledPathParent); |
| 302 | 312 | } |
| 303 | 313 | |
| 304 | static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) { | |
| 314 | static int ExecuteCC1Tool(ArrayRef<const char *> argv) { | |
| 315 | // If we call the cc1 tool from the clangDriver library (through | |
| 316 | // Driver::CC1Main), we need to clean up the options usage count. The options | |
| 317 | // are currently global, and they might have been used previously by the | |
| 318 | // driver. | |
| 319 | llvm::cl::ResetAllOptionOccurrences(); | |
| 320 | StringRef Tool = argv[1]; | |
| 305 | 321 | void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath; |
| 306 | if (Tool == "") | |
| 322 | if (Tool == "-cc1") | |
| 307 | 323 | return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP); |
| 308 | if (Tool == "as") | |
| 324 | if (Tool == "-cc1as") | |
| 309 | 325 | return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP); |
| 310 | 326 | |
| 311 | 327 | // Reject unknown tools. |
| ... | ... | @@ -316,6 +332,7 @@ static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) { |
| 316 | 332 | |
| 317 | 333 | extern "C" int ZigClang_main(int argc_, const char **argv_); |
| 318 | 334 | int ZigClang_main(int argc_, const char **argv_) { |
| 335 | noteBottomOfStack(); | |
| 319 | 336 | llvm::InitLLVM X(argc_, argv_); |
| 320 | 337 | size_t argv_offset = (strcmp(argv_[1], "-cc1") == 0 || strcmp(argv_[1], "-cc1as") == 0) ? 0 : 1; |
| 321 | 338 | SmallVector<const char *, 256> argv(argv_ + argv_offset, argv_ + argc_); |
| ... | ... | @@ -376,9 +393,11 @@ int ZigClang_main(int argc_, const char **argv_) { |
| 376 | 393 | auto newEnd = std::remove(argv.begin(), argv.end(), nullptr); |
| 377 | 394 | argv.resize(newEnd - argv.begin()); |
| 378 | 395 | } |
| 379 | return ExecuteCC1Tool(argv, argv[1] + 4); | |
| 396 | return ExecuteCC1Tool(argv); | |
| 380 | 397 | } |
| 381 | 398 | |
| 399 | // Handle options that need handling before the real command line parsing in | |
| 400 | // Driver::BuildCompilation() | |
| 382 | 401 | bool CanonicalPrefixes = true; |
| 383 | 402 | for (int i = 1, size = argv.size(); i < size; ++i) { |
| 384 | 403 | // Skip end-of-line response file markers |
| ... | ... | @@ -421,10 +440,16 @@ int ZigClang_main(int argc_, const char **argv_) { |
| 421 | 440 | ApplyQAOverride(argv, OverrideStr, SavedStrings); |
| 422 | 441 | } |
| 423 | 442 | |
| 424 | std::string Path = GetExecutablePath(argv_[0], CanonicalPrefixes); | |
| 443 | std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes); | |
| 444 | ||
| 445 | // Whether the cc1 tool should be called inside the current process, or if we | |
| 446 | // should spawn a new clang subprocess (old behavior). | |
| 447 | // Not having an additional process saves some execution time of Windows, | |
| 448 | // and makes debugging and profiling easier. | |
| 449 | bool UseNewCC1Process; | |
| 425 | 450 | |
| 426 | 451 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = |
| 427 | CreateAndPopulateDiagOpts(argv); | |
| 452 | CreateAndPopulateDiagOpts(argv, UseNewCC1Process); | |
| 428 | 453 | |
| 429 | 454 | TextDiagnosticPrinter *DiagClient |
| 430 | 455 | = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); |
| ... | ... | @@ -452,6 +477,12 @@ int ZigClang_main(int argc_, const char **argv_) { |
| 452 | 477 | |
| 453 | 478 | SetBackdoorDriverOutputsFromEnvVars(TheDriver); |
| 454 | 479 | |
| 480 | if (!UseNewCC1Process) { | |
| 481 | TheDriver.CC1Main = &ExecuteCC1Tool; | |
| 482 | // Ensure the CC1Command actually catches cc1 crashes | |
| 483 | llvm::CrashRecoveryContext::Enable(); | |
| 484 | } | |
| 485 | ||
| 455 | 486 | std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv)); |
| 456 | 487 | int Res = 1; |
| 457 | 488 | if (C && !C->containsError()) { |
| ... | ... | @@ -496,10 +527,11 @@ int ZigClang_main(int argc_, const char **argv_) { |
| 496 | 527 | // If any timers were active but haven't been destroyed yet, print their |
| 497 | 528 | // results now. This happens in -disable-free mode. |
| 498 | 529 | llvm::TimerGroup::printAll(llvm::errs()); |
| 530 | llvm::TimerGroup::clearAll(); | |
| 499 | 531 | |
| 500 | 532 | #ifdef _WIN32 |
| 501 | 533 | // Exit status should not be negative on Win32, unless abnormal termination. |
| 502 | // Once abnormal termiation was caught, negative status should not be | |
| 534 | // Once abnormal termination was caught, negative status should not be | |
| 503 | 535 | // propagated. |
| 504 | 536 | if (Res < 0) |
| 505 | 537 | Res = 1; |
| ... | ... | @@ -509,3 +541,4 @@ int ZigClang_main(int argc_, const char **argv_) { |
| 509 | 541 | // failing command. |
| 510 | 542 | return Res; |
| 511 | 543 | } |
| 544 |