Author: Junduo Dong Date: 2022-09-02T18:49:11-07:00 New Revision: 38941da066a7b785ba4771710189172e94e37824
URL: https://github.com/llvm/llvm-project/commit/38941da066a7b785ba4771710189172e94e37824 DIFF: https://github.com/llvm/llvm-project/commit/38941da066a7b785ba4771710189172e94e37824.diff LOG: [Clang] change default storing path of `-ftime-trace` 1. This implementation change the default storing behavior of -ftime-trace only. That is, if the compiling job contains the linking action, the executable file' s directory may be seem as the main work directory. Thus the time trace files would be stored in the same directory of linking result. By this approach, the user can easily get the time-trace files in the main work directory. The improved demo results: ``` $ clang++ -ftime-trace -o main.out /demo/main.cpp $ ls . main.out main-[random-string].json ``` 2. In addition, the main codes of time-trace files' path inference have been refactored. * The <path> of -ftime-trace=<path> is infered in clang driver * After that, -ftime-trace=<path> can be added into clang's options By this approach, the dirty work of path processing and judging can be implemented in driver layer, so that the clang may focus on its main work. # $ clang -ftime-trace -o xxx.out xxx.cpp Differential Revision: https://reviews.llvm.org/D131469 Added: Modified: clang/lib/Driver/Driver.cpp clang/test/Driver/check-time-trace.cpp clang/tools/driver/cc1_main.cpp Removed: ################################################################################ diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index ba359a1d31a53..5f5655fbc34a8 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4510,6 +4510,102 @@ Action *Driver::ConstructPhaseAction( llvm_unreachable("invalid phase in ConstructPhaseAction"); } +// Infer data storing path of the options `-ftime-trace`, `-ftime-trace=<path>` +void InferTimeTracePath(Compilation &C) { + bool HasTimeTrace = + C.getArgs().getLastArg(options::OPT_ftime_trace) != nullptr; + bool HasTimeTraceFile = + C.getArgs().getLastArg(options::OPT_ftime_trace_EQ) != nullptr; + // Whether `-ftime-trace` or `-ftime-trace=<path>` are specified + if (!HasTimeTrace && !HasTimeTraceFile) + return; + + // If `-ftime-trace=<path>` is specified, TracePath is the <path>. + // Else if there is a linking job, TracePath is the parent path of .exe, + // then the OutputFile's name may be appended to it. + // Else, TracePath is "", + // then the full OutputFile's path may be appended to it. + SmallString<128> TracePath(""); + + if (HasTimeTraceFile) { + TracePath = SmallString<128>( + C.getArgs().getLastArg(options::OPT_ftime_trace_EQ)->getValue()); + } else { + // Get linking executable file's parent path as TracePath's parent path, + // default is ".". Filename may be determined and added into TracePath then. + // + // e.g. executable file's path: /usr/local/a.out + // its parent's path: /usr/local + for (auto &J : C.getJobs()) { + if (J.getSource().getKind() == Action::LinkJobClass) { + assert(!J.getOutputFilenames().empty() && + "linking output filename is empty"); + auto OutputFilePath = + SmallString<128>(J.getOutputFilenames()[0].c_str()); + if (llvm::sys::path::has_parent_path(OutputFilePath)) { + TracePath = llvm::sys::path::parent_path(OutputFilePath); + } else { + TracePath = SmallString<128>("."); + } + break; + } + } + } + + // Add or replace the modified -ftime-trace=<path>` to all clang jobs + for (auto &J : C.getJobs()) { + if (J.getSource().getKind() == Action::AssembleJobClass || + J.getSource().getKind() == Action::BackendJobClass || + J.getSource().getKind() == Action::CompileJobClass) { + SmallString<128> TracePathReal = TracePath; + SmallString<128> OutputPath(J.getOutputFilenames()[0].c_str()); + std::string arg = std::string("-ftime-trace="); + if (!HasTimeTraceFile) { + if (TracePathReal.empty()) { + // /xxx/yyy.o => /xxx/yyy.json + llvm::sys::path::replace_extension(OutputPath, "json"); + arg += std::string(OutputPath.c_str()); + } else { + // /xxx/yyy.o => /executable_file_parent_path/yyy.json + llvm::sys::path::append(TracePathReal, + llvm::sys::path::filename(OutputPath)); + llvm::sys::path::replace_extension(TracePathReal, "json"); + arg += std::string(TracePathReal.c_str()); + } + } else { + // /full_file_path_specified or /path_specified/yyy.json + if (llvm::sys::fs::is_directory(TracePathReal)) + llvm::sys::path::append(TracePathReal, + llvm::sys::path::filename(OutputPath)); + llvm::sys::path::replace_extension(TracePathReal, "json"); + arg += std::string(TracePathReal.c_str()); + } + + assert(arg.size() > strlen("-ftime-trace") && + arg.find("-ftime-trace=") == 0 && arg[arg.size() - 1] != '=' && + "invalid `-ftime-trace=<path>`"); + + const std::string::size_type size = arg.size(); + char *buffer = new char[size + 1]; + memcpy(buffer, arg.c_str(), size + 1); + + // Replace `-ftime-trace` or `-ftime-trace=<path>` with the modified + // `-ftime-trace=<infered_path>`. + auto &JArgs = J.getArguments(); + for (unsigned I = 0; I < JArgs.size(); ++I) { + if (StringRef(JArgs[I]).startswith("-ftime-trace=") || + (StringRef(JArgs[I]).equals("-ftime-trace") && !HasTimeTraceFile)) { + ArgStringList NewArgs(JArgs.begin(), JArgs.begin() + I); + NewArgs.push_back(buffer); + NewArgs.append(JArgs.begin() + I + 1, JArgs.end()); + J.replaceArguments(NewArgs); + break; + } + } + } + } +} + void Driver::BuildJobs(Compilation &C) const { llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); @@ -4597,6 +4693,9 @@ void Driver::BuildJobs(Compilation &C) const { /*TargetDeviceOffloadKind*/ Action::OFK_None); } + // set data storing path of the options `-ftime-trace`, `-ftime-trace=<path>` + InferTimeTracePath(C); + // If we have more than one job, then disable integrated-cc1 for now. Do this // also when we need to report process execution statistics. if (C.getJobs().size() > 1 || CCPrintProcessStats) diff --git a/clang/test/Driver/check-time-trace.cpp b/clang/test/Driver/check-time-trace.cpp index 52b3e71394fba..e0d1e935a7331 100644 --- a/clang/test/Driver/check-time-trace.cpp +++ b/clang/test/Driver/check-time-trace.cpp @@ -1,3 +1,8 @@ +// RUN: rm -rf %T/exe && mkdir %T/exe +// RUN: %clangxx -ftime-trace -ftime-trace-granularity=0 -o %T/exe/check-time-trace %s +// RUN: cat %T/exe/check-time-trace*.json \ +// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ +// RUN: | FileCheck %s // RUN: %clangxx -S -ftime-trace -ftime-trace-granularity=0 -o %T/check-time-trace %s // RUN: cat %T/check-time-trace.json \ // RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index de33aa9ea9341..5da37577a1001 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -256,17 +256,10 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { llvm::TimerGroup::clearAll(); if (llvm::timeTraceProfilerEnabled()) { - SmallString<128> Path(Clang->getFrontendOpts().OutputFile); - llvm::sys::path::replace_extension(Path, "json"); - if (!Clang->getFrontendOpts().TimeTracePath.empty()) { - // replace the suffix to '.json' directly - SmallString<128> TracePath(Clang->getFrontendOpts().TimeTracePath); - if (llvm::sys::fs::is_directory(TracePath)) - llvm::sys::path::append(TracePath, llvm::sys::path::filename(Path)); - Path.assign(TracePath); - } + SmallString<128> TracePath(Clang->getFrontendOpts().TimeTracePath); + assert(!TracePath.empty() && "`-ftime-trace=<path>` is empty"); if (auto profilerOutput = Clang->createOutputFile( - Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false, + TracePath.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false, /*useTemporary=*/false)) { llvm::timeTraceProfilerWrite(*profilerOutput); profilerOutput.reset(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits