From 557731b6a357f23564ea1a399e8ec0f235af8b13 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 15 Mar 2021 19:15:27 -0700 Subject: [PATCH 1/2] adding a command line option to force the execution of rewrite steps --- .../CommandLineTool/Commands/Build.cs | 1 + .../CommandLineTool/Commands/Diagnose.cs | 1 + src/QsCompiler/CommandLineTool/Options.cs | 7 +++ src/QsCompiler/Compiler/CompilationLoader.cs | 60 ++++++++++++------- src/QsCompiler/DataStructures/Diagnostics.fs | 6 +- src/QsCompiler/Tests.Compiler/QirTests.fs | 6 +- 6 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/QsCompiler/CommandLineTool/Commands/Build.cs b/src/QsCompiler/CommandLineTool/Commands/Build.cs index 58c5f4e520..d7866cc79c 100644 --- a/src/QsCompiler/CommandLineTool/Commands/Build.cs +++ b/src/QsCompiler/CommandLineTool/Commands/Build.cs @@ -225,6 +225,7 @@ public static int Run(BuildOptions options, ConsoleLogger logger) { ProjectName = options.ProjectName, AssemblyConstants = assemblyConstants, + ForceRewriteStepExecution = options.ForceRewriteStepExecution, TargetPackageAssemblies = options.TargetSpecificDecompositions ?? Enumerable.Empty(), RuntimeCapability = options.RuntimeCapability, SkipMonomorphization = options.RuntimeCapability == RuntimeCapability.FullComputation && options.QirOutputFolder == null, diff --git a/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs b/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs index a39ec54c66..37f6aae02e 100644 --- a/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs +++ b/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs @@ -237,6 +237,7 @@ public static int Run(DiagnoseOptions options, ConsoleLogger logger) var loadOptions = new CompilationLoader.Configuration { AssemblyConstants = assemblyConstants, + ForceRewriteStepExecution = options.ForceRewriteStepExecution, TargetPackageAssemblies = options.TargetSpecificDecompositions ?? Enumerable.Empty(), RuntimeCapability = options.RuntimeCapability, SkipMonomorphization = options.RuntimeCapability == RuntimeCapability.FullComputation, diff --git a/src/QsCompiler/CommandLineTool/Options.cs b/src/QsCompiler/CommandLineTool/Options.cs index 125306fb51..f5ee8d2406 100644 --- a/src/QsCompiler/CommandLineTool/Options.cs +++ b/src/QsCompiler/CommandLineTool/Options.cs @@ -64,6 +64,13 @@ public class CompilationOptions : Options HelpText = "Additional properties to populate the AssemblyConstants dictionary with. Each item is expected to be of the form \"key:value\".")] public IEnumerable? AdditionalAssemblyProperties { get; set; } + [Option( + "force-rewrite-step-execution", + Required = false, + Default = false, + HelpText = "Specifies whether to execute rewrite steps even if their precondition is not satisfied. If this is the case, the transformation output will be ignored and the compilation fails.")] + public bool ForceRewriteStepExecution { get; set; } + [Option( "runtime", Required = false, diff --git a/src/QsCompiler/Compiler/CompilationLoader.cs b/src/QsCompiler/Compiler/CompilationLoader.cs index c02fe63498..e4c0371b31 100644 --- a/src/QsCompiler/Compiler/CompilationLoader.cs +++ b/src/QsCompiler/Compiler/CompilationLoader.cs @@ -61,6 +61,13 @@ public struct Configuration /// public string? ProjectName; + /// + /// If set to true, forces all rewrite steps to execute, regardless of whether their precondition was satisfied. + /// If the precondition of a step is not satisfied, the transformation is executed but the output will be ignored, + /// and an error is generated, indicating a compilation failure. + /// + public bool ForceRewriteStepExecution; + /// /// If set to true, the syntax tree rewrite step that replaces all generation directives /// for all functor specializations is executed during compilation. @@ -547,11 +554,11 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference { if (this.config.RuntimeCapability == null || this.config.RuntimeCapability == RuntimeCapability.FullComputation) { - this.logger?.Log(WarningCode.MissingEntryPoint, Array.Empty()); + this.LogAndUpdate(ref this.compilationStatus.Validation, WarningCode.MissingEntryPoint); } else { - this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.MissingEntryPoint, Array.Empty()); + this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.MissingEntryPoint); } } @@ -730,12 +737,20 @@ private void LogAndUpdate(ref Status current, Exception ex) /// /// Logs an error with the given error code and message parameters, and updates the status passed as reference accordingly. /// - private void LogAndUpdate(ref Status current, ErrorCode code, IEnumerable args) + private void LogAndUpdate(ref Status current, ErrorCode code, params string[] args) { this.logger?.Log(code, args); current = Status.Failed; } + /// + /// Logs an error with the given warning code and message parameters, and updates the status passed as reference accordingly. + /// + private void LogAndUpdate(ref Status current, WarningCode code, params string[] args) + { + this.logger?.Log(code, args); + } + /// /// Logs the given diagnostic and updates the status passed as reference accordingly. /// Adds the given diagnostic to the tracked load diagnostics. @@ -751,7 +766,7 @@ private void LogAndUpdateLoadDiagnostics(ref Status current, Diagnostic d) /// private void OnCompilerException(Exception ex) { - this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.UnexpectedCompilerException, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.UnexpectedCompilerException); this.LogAndUpdate(ref this.compilationStatus.Validation, ex); } @@ -829,7 +844,7 @@ private void PrintLoadedRewriteSteps(IEnumerable rewriteSteps) /// private QsCompilation? ReplaceTargetSpecificImplementations(IEnumerable paths, Uri rewriteStepOrigin, int nrReferences) { - void LogError(ErrorCode errCode, string[] args) => this.LogAndUpdate(ref this.compilationStatus.TargetSpecificReplacements, errCode, args); + void LogError(ErrorCode errCode, params string[] args) => this.LogAndUpdate(ref this.compilationStatus.TargetSpecificReplacements, errCode, args); void LogException(Exception ex) => this.LogAndUpdate(ref this.compilationStatus.TargetSpecificReplacements, ex); (string, ImmutableArray)? LoadReferences(string path) @@ -841,12 +856,12 @@ private void PrintLoadedRewriteSteps(IEnumerable rewriteSteps) { return (path, loaded.Namespaces); } - LogError(ErrorCode.FailedToLoadTargetSpecificDecompositions, new[] { targetDll }); + LogError(ErrorCode.FailedToLoadTargetSpecificDecompositions, targetDll); return null; } catch (Exception ex) { - LogError(ErrorCode.InvalidPathToTargetSpecificDecompositions, new[] { path }); + LogError(ErrorCode.InvalidPathToTargetSpecificDecompositions, path); LogException(ex); return null; } @@ -856,7 +871,7 @@ private void PrintLoadedRewriteSteps(IEnumerable rewriteSteps) var combinedSuccessfully = References.CombineSyntaxTrees(out var replacements, additionalAssemblies: nrReferences, onError: LogError, natives); if (!combinedSuccessfully) { - LogError(ErrorCode.ConflictsInTargetSpecificDecompositions, Array.Empty()); + LogError(ErrorCode.ConflictsInTargetSpecificDecompositions); } var targetSpecificDecompositions = new QsCompilation(replacements, ImmutableArray.Empty); @@ -876,6 +891,7 @@ private Status ExecuteRewriteStep(LoadedStep rewriteStep, QsCompilation compilat rewriteStep.Name == "CSharpGeneration" && severity == DiagnosticSeverity.Information ? Informations.Code(InformationCode.CsharpGenerationGeneratedInfo) : null; + var messageSource = ProjectManager.MessageSource(rewriteStep.Origin); void LogDiagnostics(ref Status status) { try @@ -888,13 +904,11 @@ void LogDiagnostics(ref Status status) } catch { - this.LogAndUpdate(ref status, Warning(WarningCode.RewriteStepDiagnosticsGenerationFailed, rewriteStep.Name)); + this.LogAndUpdate(ref status, WarningCode.RewriteStepDiagnosticsGenerationFailed, rewriteStep.Name, messageSource); } } var status = Status.Succeeded; - var messageSource = ProjectManager.MessageSource(rewriteStep.Origin); - Diagnostic Warning(WarningCode code, params string[] args) => Warnings.LoadWarning(code, args, messageSource); try { transformed = compilation; @@ -902,8 +916,15 @@ void LogDiagnostics(ref Status status) if (preconditionFailed) { LogDiagnostics(ref status); - this.LogAndUpdate(ref status, Warning(WarningCode.PreconditionVerificationFailed, rewriteStep.Name, messageSource)); - return status; + if (this.config.ForceRewriteStepExecution) + { + this.LogAndUpdate(ref status, ErrorCode.PreconditionVerificationFailed, rewriteStep.Name, messageSource); + } + else + { + this.LogAndUpdate(ref status, WarningCode.PreconditionVerificationFailed, rewriteStep.Name, messageSource); + return status; + } } var transformationFailed = rewriteStep.ImplementsTransformation && (!rewriteStep.Transformation(compilation, out transformed) || transformed == null); @@ -949,7 +970,7 @@ private ImmutableDictionary LoadSourceFiles(IEnumerable sou this.compilationStatus.SourceFileLoading = 0; if (sources == null) { - this.LogAndUpdate(ref this.compilationStatus.SourceFileLoading, ErrorCode.SourceFilesMissing, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.SourceFileLoading, ErrorCode.SourceFilesMissing); } void OnException(Exception ex) => this.LogAndUpdate(ref this.compilationStatus.SourceFileLoading, ex); void OnDiagnostic(Diagnostic d) => this.LogAndUpdateLoadDiagnostics(ref this.compilationStatus.SourceFileLoading, d); @@ -971,7 +992,7 @@ private References LoadAssemblies(IEnumerable refs, bool loadTestNames, this.compilationStatus.ReferenceLoading = 0; if (refs == null) { - this.logger?.Log(WarningCode.ReferencesSetToNull, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.ReferenceLoading, WarningCode.ReferencesSetToNull); } void OnException(Exception ex) => this.LogAndUpdate(ref this.compilationStatus.ReferenceLoading, ex); void OnDiagnostic(Diagnostic d) => this.LogAndUpdateLoadDiagnostics(ref this.compilationStatus.ReferenceLoading, d); @@ -991,7 +1012,7 @@ private References LoadAssemblies(IEnumerable refs, bool loadTestNames, private bool WriteSyntaxTreeSerialization(MemoryStream ms) { void LogError() => this.LogAndUpdate( - ref this.compilationStatus.Serialization, ErrorCode.SerializationFailed, Enumerable.Empty()); + ref this.compilationStatus.Serialization, ErrorCode.SerializationFailed); void LogExceptionAndError(Exception ex) { @@ -1041,7 +1062,7 @@ void LogExceptionAndError(Exception ex) catch (Exception ex) { this.LogAndUpdate(ref this.compilationStatus.BinaryFormat, ex); - this.LogAndUpdate(ref this.compilationStatus.BinaryFormat, ErrorCode.GeneratingBinaryFailed, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.BinaryFormat, ErrorCode.GeneratingBinaryFailed); return null; } } @@ -1097,8 +1118,7 @@ bool CanBeIncluded(string dll) var csharpTree = MetadataGeneration.GenerateAssemblyMetadata(references.Where(r => r.Item3).Select(r => r.Item2)); foreach (var (dropped, _, _) in references.Where(r => !r.Item3)) { - var warning = Warnings.LoadWarning(WarningCode.ReferenceCannotBeIncludedInDll, new[] { dropped }, null); - this.LogAndUpdate(ref this.compilationStatus.DllGeneration, warning); + this.LogAndUpdate(ref this.compilationStatus.DllGeneration, WarningCode.ReferencesSetToNull, dropped); } var compilation = CodeAnalysis.CSharp.CSharpCompilation.Create( @@ -1125,7 +1145,7 @@ bool CanBeIncluded(string dll) catch (Exception ex) { this.LogAndUpdate(ref this.compilationStatus.DllGeneration, ex); - this.LogAndUpdate(ref this.compilationStatus.DllGeneration, ErrorCode.GeneratingDllFailed, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.DllGeneration, ErrorCode.GeneratingDllFailed); return null; } } diff --git a/src/QsCompiler/DataStructures/Diagnostics.fs b/src/QsCompiler/DataStructures/Diagnostics.fs index b17303b501..a0ba3ed848 100644 --- a/src/QsCompiler/DataStructures/Diagnostics.fs +++ b/src/QsCompiler/DataStructures/Diagnostics.fs @@ -318,9 +318,9 @@ type ErrorCode = | PreEvaluationFailed = 7111 | RewriteStepExecutionFailed = 7112 | PostconditionVerificationFailed = 7113 + | PreconditionVerificationFailed = 7202 // the corresponding warning code exists | CsharpGenerationGeneratedError = 8001 - | PublishingPerfResultsFailed = 8101 | PerformanceTrackingFailed = 8102 | SyntaxTreeNotMonomorphized = 8103 @@ -377,7 +377,7 @@ type WarningCode = | UnresolvedItemsInGeneratedQs = 7101 | RewriteStepDiagnosticsGenerationFailed = 7201 - | PreconditionVerificationFailed = 7202 + | PreconditionVerificationFailed = 7202 // the corresponding error code exists | RewriteStepLoadedViaReflection = 7203 | FailedToLoadRewriteStepViaReflection = 7204 @@ -877,9 +877,9 @@ type DiagnosticItem = "Executing the transformation for the compilation step \"{0}\" loaded from \"{1}\" failed." | ErrorCode.PostconditionVerificationFailed -> "The postcondition for the compilation step \"{0}\" loaded from \"{1}\" was not satisfied. The transformation has produced incorrect output and should be excluded from the compilation process." + | ErrorCode.PreconditionVerificationFailed -> "The precondition for the compilation step \"{0}\" loaded from \"{1}\" was not met." | ErrorCode.CsharpGenerationGeneratedError -> "" - | ErrorCode.PublishingPerfResultsFailed -> "Performance results failed to be published at \"{0}\"." | ErrorCode.PerformanceTrackingFailed -> "Performance tracking failed with error \"{0}\"." | ErrorCode.SyntaxTreeNotMonomorphized -> diff --git a/src/QsCompiler/Tests.Compiler/QirTests.fs b/src/QsCompiler/Tests.Compiler/QirTests.fs index eed1c450ec..c3f8c27e24 100644 --- a/src/QsCompiler/Tests.Compiler/QirTests.fs +++ b/src/QsCompiler/Tests.Compiler/QirTests.fs @@ -198,7 +198,11 @@ let ``QIR expressions`` () = qirTest false "TestExpressions" [] let ``QIR targeting`` () = let compilerArgs = - [ "--runtime"; "BasicMeasurementFeedback" ] + [ + "--runtime" + "BasicMeasurementFeedback" + "--force-rewrite-step-execution" // to make sure the target specific transformation actually runs + ] |> Seq.append (compilerArgs true "TestTargeting") |> Seq.toArray From 9823f787598604cc3949a3b9e43a8daf502a02e1 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Tue, 16 Mar 2021 17:54:27 -0700 Subject: [PATCH 2/2] formatting --- src/QsCompiler/DataStructures/Diagnostics.fs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/QsCompiler/DataStructures/Diagnostics.fs b/src/QsCompiler/DataStructures/Diagnostics.fs index a0ba3ed848..4d4221f5ab 100644 --- a/src/QsCompiler/DataStructures/Diagnostics.fs +++ b/src/QsCompiler/DataStructures/Diagnostics.fs @@ -318,7 +318,8 @@ type ErrorCode = | PreEvaluationFailed = 7111 | RewriteStepExecutionFailed = 7112 | PostconditionVerificationFailed = 7113 - | PreconditionVerificationFailed = 7202 // the corresponding warning code exists + // the corresponding warning code exists + | PreconditionVerificationFailed = 7202 | CsharpGenerationGeneratedError = 8001 | PublishingPerfResultsFailed = 8101 @@ -377,7 +378,8 @@ type WarningCode = | UnresolvedItemsInGeneratedQs = 7101 | RewriteStepDiagnosticsGenerationFailed = 7201 - | PreconditionVerificationFailed = 7202 // the corresponding error code exists + // the corresponding error code exists + | PreconditionVerificationFailed = 7202 | RewriteStepLoadedViaReflection = 7203 | FailedToLoadRewriteStepViaReflection = 7204 @@ -877,7 +879,8 @@ type DiagnosticItem = "Executing the transformation for the compilation step \"{0}\" loaded from \"{1}\" failed." | ErrorCode.PostconditionVerificationFailed -> "The postcondition for the compilation step \"{0}\" loaded from \"{1}\" was not satisfied. The transformation has produced incorrect output and should be excluded from the compilation process." - | ErrorCode.PreconditionVerificationFailed -> "The precondition for the compilation step \"{0}\" loaded from \"{1}\" was not met." + | ErrorCode.PreconditionVerificationFailed -> + "The precondition for the compilation step \"{0}\" loaded from \"{1}\" was not met." | ErrorCode.CsharpGenerationGeneratedError -> "" | ErrorCode.PublishingPerfResultsFailed -> "Performance results failed to be published at \"{0}\"."