Skip to content

Add emission of Frontend parseable-output in WMO jobs. #58422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 72 additions & 37 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ mapFrontendInvocationToAction(const CompilerInvocation &Invocation) {

static DetailedTaskDescription
constructDetailedTaskDescription(const CompilerInvocation &Invocation,
const InputFile &PrimaryInput,
ArrayRef<InputFile> PrimaryInputs,
ArrayRef<const char *> Args) {
// Command line and arguments
std::string Executable = Invocation.getFrontendOptions().MainExecutablePath;
Expand All @@ -604,24 +604,30 @@ constructDetailedTaskDescription(const CompilerInvocation &Invocation,
CommandLine += std::string(" ") + A;
}

// Primary Input only
Inputs.push_back(CommandInput(PrimaryInput.getFileName()));
// Primary Inputs
for (const auto &input : PrimaryInputs) {
Inputs.push_back(CommandInput(input.getFileName()));
}

// Output for this Primary
auto OutputFile = PrimaryInput.outputFilename();
Outputs.push_back(OutputPair(file_types::lookupTypeForExtension(
llvm::sys::path::extension(OutputFile)),
OutputFile));
for (const auto &input : PrimaryInputs) {
// Main outputs
auto OutputFile = input.outputFilename();
if (!OutputFile.empty()) {
Outputs.push_back(OutputPair(file_types::lookupTypeForExtension(
llvm::sys::path::extension(OutputFile)),
OutputFile));
}

// Supplementary outputs
const auto &primarySpecificFiles = PrimaryInput.getPrimarySpecificPaths();
const auto &supplementaryOutputPaths =
primarySpecificFiles.SupplementaryOutputs;
supplementaryOutputPaths.forEachSetOutput([&](const std::string &output) {
Outputs.push_back(OutputPair(
file_types::lookupTypeForExtension(llvm::sys::path::extension(output)),
output));
});
// Supplementary outputs
const auto &primarySpecificFiles = input.getPrimarySpecificPaths();
const auto &supplementaryOutputPaths =
primarySpecificFiles.SupplementaryOutputs;
supplementaryOutputPaths.forEachSetOutput([&](const std::string &output) {
Outputs.push_back(OutputPair(file_types::lookupTypeForExtension(
llvm::sys::path::extension(output)),
output));
});
}
return DetailedTaskDescription{Executable, Arguments, CommandLine, Inputs,
Outputs};
}
Expand Down Expand Up @@ -2125,15 +2131,26 @@ int swift::performFrontend(ArrayRef<const char *> Args,
// making sure it cannot collide with a real PID (always positive). Non-batch
// compilation gets a real OS PID.
int64_t Pid = IO.hasUniquePrimaryInput() ? OSPid : QUASI_PID_START;
IO.forEachPrimaryInputWithIndex([&](const InputFile &Input,
unsigned idx) -> bool {
emitBeganMessage(
llvm::errs(),
mapFrontendInvocationToAction(Invocation),
constructDetailedTaskDescription(Invocation, Input, Args), Pid - idx,
ProcInfo);
return false;
});

if (IO.hasPrimaryInputs()) {
IO.forEachPrimaryInputWithIndex([&](const InputFile &Input,
unsigned idx) -> bool {
ArrayRef<InputFile> Inputs(Input);
emitBeganMessage(llvm::errs(),
mapFrontendInvocationToAction(Invocation),
constructDetailedTaskDescription(Invocation,
Inputs,
Args), Pid - idx,
ProcInfo);
return false;
});
} else {
// If no primary inputs are present, we are in WMO.
emitBeganMessage(llvm::errs(),
mapFrontendInvocationToAction(Invocation),
constructDetailedTaskDescription(Invocation, IO.getAllInputs(), Args),
OSPid, ProcInfo);
}
}

int ReturnValue = 0;
Expand Down Expand Up @@ -2164,23 +2181,41 @@ int swift::performFrontend(ArrayRef<const char *> Args,
// making sure it cannot collide with a real PID (always positive). Non-batch
// compilation gets a real OS PID.
int64_t Pid = IO.hasUniquePrimaryInput() ? OSPid : QUASI_PID_START;
IO.forEachPrimaryInputWithIndex([&](const InputFile &Input,
unsigned idx) -> bool {
assert(FileSpecificDiagnostics.count(Input.getFileName()) != 0 &&
"Expected diagnostic collection for input.");

// Join all diagnostics produced for this file into a single output.
auto PrimaryDiags = FileSpecificDiagnostics.lookup(Input.getFileName());
if (IO.hasPrimaryInputs()) {
IO.forEachPrimaryInputWithIndex([&](const InputFile &Input,
unsigned idx) -> bool {
assert(FileSpecificDiagnostics.count(Input.getFileName()) != 0 &&
"Expected diagnostic collection for input.");

// Join all diagnostics produced for this file into a single output.
auto PrimaryDiags = FileSpecificDiagnostics.lookup(Input.getFileName());
const char *const Delim = "";
std::ostringstream JoinedDiags;
std::copy(PrimaryDiags.begin(), PrimaryDiags.end(),
std::ostream_iterator<std::string>(JoinedDiags, Delim));

emitFinishedMessage(llvm::errs(),
mapFrontendInvocationToAction(Invocation),
JoinedDiags.str(), r, Pid - idx, ProcInfo);
return false;
});
} else {
// If no primary inputs are present, we are in WMO.
std::vector<std::string> AllDiagnostics;
for (const auto &FileDiagnostics : FileSpecificDiagnostics) {
AllDiagnostics.insert(AllDiagnostics.end(),
FileDiagnostics.getValue().begin(),
FileDiagnostics.getValue().end());
}
const char *const Delim = "";
std::ostringstream JoinedDiags;
std::copy(PrimaryDiags.begin(), PrimaryDiags.end(),
std::copy(AllDiagnostics.begin(), AllDiagnostics.end(),
std::ostream_iterator<std::string>(JoinedDiags, Delim));

emitFinishedMessage(llvm::errs(),
mapFrontendInvocationToAction(Invocation),
JoinedDiags.str(), r, Pid - idx, ProcInfo);
return false;
});
JoinedDiags.str(), r, OSPid, ProcInfo);
}
Comment on lines 2211 to +2218
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I notice that this code is essentially duplicated between the two branches, just with slightly different parameters to emitFinishedMessage(). Do you think there's a way you could combine them?

}

return r;
Expand Down
21 changes: 15 additions & 6 deletions test/Frontend/parseable_output.swift
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
// RUN: %target-swift-frontend -primary-file %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s
// RUN: %target-swift-frontend -primary-file %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -emit-module -emit-module-path %t.swiftmodule -serialize-diagnostics -serialize-diagnostics-path %t.dia -frontend-parseable-output 2>&1 | %FileCheck %s
// Check without primary files (WMO):
// RUN: %target-swift-frontend %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -emit-module -emit-module-path %t.swiftmodule -serialize-diagnostics -serialize-diagnostics-path %t.dia -frontend-parseable-output 2>&1 | %FileCheck %s

// CHECK: {{[1-9][0-9]*}}
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "began",
// CHECK-NEXT: "name": "compile",
// CHECK-NEXT: "command": "{{.*[\\/]}}swift-frontend{{(\.exe)?}}{{.*}}-primary-file {{.*[\\/]}}parseable_output.swift -o {{.*[\\/]}}parseable_output.swift.tmp.out -emit-module -emit-module-path {{.*[\\/]}}parseable_output.swift.tmp.swiftmodule -frontend-parseable-output",
// CHECK-NEXT: "command": "{{.*[\\/]}}swift-frontend{{(\.exe)?}}{{.*}} {{.*[\\/]}}parseable_output.swift {{.*[\\/]}}filelist-other.swift -o {{.*[\\/]}}parseable_output.swift.tmp.out -module-name parseable_output -emit-module -emit-module-path {{.*[\\/]}}parseable_output.swift.tmp.swiftmodule -serialize-diagnostics -serialize-diagnostics-path {{.*[\\/]}}parseable_output.swift.tmp.dia -frontend-parseable-output",
// CHECK-NEXT: "command_executable": "{{.*[\\/]}}swift{{(-frontend|c)?(\.exe)?}}",
// CHECK-NEXT: "command_arguments": [
// CHECK: "-primary-file",
// CHECK-NEXT: "{{.*[\\/]}}parseable_output.swift",
// CHECK: "{{.*[\\/]}}parseable_output.swift",
// CHECK: "-o",
// CHECK-NEXT: "{{.*[\\/]}}parseable_output.swift.tmp.out",
// CHECK-NEXT: "-module-name",
// CHECK-NEXT: "parseable_output",
// CHECK-NEXT: "-emit-module",
// CHECK-NEXT: "-emit-module-path",
// CHECK-NEXT: "{{.*[\\/]}}parseable_output.swift.tmp.swiftmodule",
// CHECK-NEXT: "-serialize-diagnostics",
// CHECK-NEXT: "-serialize-diagnostics-path"
// CHECK-NEXT: "{{.*[\\/]}}parseable_output.swift.tmp.dia",
// CHECK-NEXT: "-frontend-parseable-output"
// CHECK-NEXT: ],
// CHECK-NEXT: "inputs": [
// CHECK-NEXT: "{{.*[\\/]}}parseable_output.swift"
// CHECK-NEXT: ],
// CHECK-NEXT: "outputs": [
// CHECK: "outputs": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "image",
// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output.swift.tmp.out"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "type": "swiftmodule",
// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output.swift.tmp.swiftmodule"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "type": "diagnostics",
// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output.swift.tmp.dia"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "pid": [[PID:[0-9]*]]
Expand Down
9 changes: 5 additions & 4 deletions test/Frontend/parseable_output_error.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// RUN: not %target-swift-frontend -primary-file %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s
// Check without primary files (WMO):
// RUN: not %target-swift-frontend %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s

func foo() {
return 11;
Expand All @@ -7,11 +9,10 @@ func foo() {
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "began",
// CHECK-NEXT: "name": "compile",
// CHECK-NEXT: "command": "{{.*[\\/]}}swift-frontend{{(\.exe)?}}{{.*}}-primary-file {{.*[\\/]}}parseable_output_error.swift -o {{.*[\\/]}}parseable_output_error.swift.tmp.out -emit-module -emit-module-path {{.*[\\/]}}parseable_output_error.swift.tmp.swiftmodule -frontend-parseable-output",
// CHECK-NEXT: "command": "{{.*[\\/]}}swift-frontend{{(\.exe)?}}{{.*}} {{.*[\\/]}}parseable_output_error.swift -o {{.*[\\/]}}parseable_output_error.swift.tmp.out -emit-module -emit-module-path {{.*[\\/]}}parseable_output_error.swift.tmp.swiftmodule -frontend-parseable-output",
// CHECK-NEXT: "command_executable": "{{.*[\\/]}}swift{{(-frontend|c)?(\.exe)?}}",
// CHECK-NEXT: "command_arguments": [
// CHECK: "-primary-file",
// CHECK-NEXT: "{{.*[\\/]}}parseable_output_error.swift",
// CHECK: "{{.*[\\/]}}parseable_output_error.swift",
// CHECK-NEXT: "-o",
// CHECK-NEXT: "{{.*[\\/]}}parseable_output_error.swift.tmp.out",
// CHECK-NEXT: "-emit-module",
Expand Down Expand Up @@ -43,7 +44,7 @@ func foo() {
// CHECK-NEXT: "kind": "finished",
// CHECK-NEXT: "name": "compile",
// CHECK-NEXT: "pid": [[PID]],
// CHECK-NEXT: "output": "{{.*[\\/]}}parseable_output_error.swift:4:12: error: unexpected non-void return value in void function{{.*}}return 11;{{.*[\\/]}}parseable_output_error.swift:4:12: note: did you mean to add a return type?{{.*}}return 11;
// CHECK-NEXT: "output": "{{.*[\\/]}}parseable_output_error.swift:6:12: error: unexpected non-void return value in void function{{.*}}return 11;{{.*[\\/]}}parseable_output_error.swift:6:12: note: did you mean to add a return type?{{.*}}return 11;
// CHECK-NEXT: "process": {
// CHECK-NEXT: "real_pid": [[PID]]
// CHECK-NEXT: },
Expand Down