Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Closed
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
1 change: 1 addition & 0 deletions src/QsCompiler/CommandLineTool/Commands/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>(),
RuntimeCapability = options.RuntimeCapability,
SkipMonomorphization = options.RuntimeCapability == RuntimeCapability.FullComputation && options.QirOutputFolder == null,
Expand Down
1 change: 1 addition & 0 deletions src/QsCompiler/CommandLineTool/Commands/Diagnose.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>(),
RuntimeCapability = options.RuntimeCapability,
SkipMonomorphization = options.RuntimeCapability == RuntimeCapability.FullComputation,
Expand Down
7 changes: 7 additions & 0 deletions src/QsCompiler/CommandLineTool/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>? 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,
Expand Down
60 changes: 40 additions & 20 deletions src/QsCompiler/Compiler/CompilationLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public struct Configuration
/// </summary>
public string? ProjectName;

/// <summary>
/// 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.
/// </summary>
public bool ForceRewriteStepExecution;

/// <summary>
/// If set to true, the syntax tree rewrite step that replaces all generation directives
/// for all functor specializations is executed during compilation.
Expand Down Expand Up @@ -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<string>());
this.LogAndUpdate(ref this.compilationStatus.Validation, WarningCode.MissingEntryPoint);
}
else
{
this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.MissingEntryPoint, Array.Empty<string>());
this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.MissingEntryPoint);
}
}

Expand Down Expand Up @@ -730,12 +737,20 @@ private void LogAndUpdate(ref Status current, Exception ex)
/// <summary>
/// Logs an error with the given error code and message parameters, and updates the status passed as reference accordingly.
/// </summary>
private void LogAndUpdate(ref Status current, ErrorCode code, IEnumerable<string> args)
private void LogAndUpdate(ref Status current, ErrorCode code, params string[] args)
{
this.logger?.Log(code, args);
current = Status.Failed;
}

/// <summary>
/// Logs an error with the given warning code and message parameters, and updates the status passed as reference accordingly.
/// </summary>
private void LogAndUpdate(ref Status current, WarningCode code, params string[] args)
{
this.logger?.Log(code, args);
}

/// <summary>
/// Logs the given diagnostic and updates the status passed as reference accordingly.
/// Adds the given diagnostic to the tracked load diagnostics.
Expand All @@ -751,7 +766,7 @@ private void LogAndUpdateLoadDiagnostics(ref Status current, Diagnostic d)
/// </summary>
private void OnCompilerException(Exception ex)
{
this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.UnexpectedCompilerException, Enumerable.Empty<string>());
this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.UnexpectedCompilerException);
this.LogAndUpdate(ref this.compilationStatus.Validation, ex);
}

Expand Down Expand Up @@ -830,7 +845,7 @@ private void PrintLoadedRewriteSteps(IEnumerable<LoadedStep> rewriteSteps)
/// </summary>
private QsCompilation? ReplaceTargetSpecificImplementations(IEnumerable<string> 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<QsNamespace>)? LoadReferences(string path)
Expand All @@ -842,12 +857,12 @@ private void PrintLoadedRewriteSteps(IEnumerable<LoadedStep> 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;
}
Expand All @@ -857,7 +872,7 @@ private void PrintLoadedRewriteSteps(IEnumerable<LoadedStep> rewriteSteps)
var combinedSuccessfully = References.CombineSyntaxTrees(out var replacements, additionalAssemblies: nrReferences, onError: LogError, natives);
if (!combinedSuccessfully)
{
LogError(ErrorCode.ConflictsInTargetSpecificDecompositions, Array.Empty<string>());
LogError(ErrorCode.ConflictsInTargetSpecificDecompositions);
}

var targetSpecificDecompositions = new QsCompilation(replacements, ImmutableArray<QsQualifiedName>.Empty);
Expand All @@ -877,6 +892,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
Expand All @@ -889,22 +905,27 @@ 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;
var preconditionFailed = rewriteStep.ImplementsPreconditionVerification && !rewriteStep.PreconditionVerification(compilation);
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);
Expand Down Expand Up @@ -950,7 +971,7 @@ private ImmutableDictionary<Uri, string> LoadSourceFiles(IEnumerable<string> sou
this.compilationStatus.SourceFileLoading = 0;
if (sources == null)
{
this.LogAndUpdate(ref this.compilationStatus.SourceFileLoading, ErrorCode.SourceFilesMissing, Enumerable.Empty<string>());
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);
Expand All @@ -972,7 +993,7 @@ private References LoadAssemblies(IEnumerable<string> refs, bool loadTestNames,
this.compilationStatus.ReferenceLoading = 0;
if (refs == null)
{
this.logger?.Log(WarningCode.ReferencesSetToNull, Enumerable.Empty<string>());
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);
Expand All @@ -992,7 +1013,7 @@ private References LoadAssemblies(IEnumerable<string> refs, bool loadTestNames,
private bool WriteSyntaxTreeSerialization(MemoryStream ms)
{
void LogError() => this.LogAndUpdate(
ref this.compilationStatus.Serialization, ErrorCode.SerializationFailed, Enumerable.Empty<string>());
ref this.compilationStatus.Serialization, ErrorCode.SerializationFailed);

void LogExceptionAndError(Exception ex)
{
Expand Down Expand Up @@ -1042,7 +1063,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<string>());
this.LogAndUpdate(ref this.compilationStatus.BinaryFormat, ErrorCode.GeneratingBinaryFailed);
return null;
}
}
Expand Down Expand Up @@ -1098,8 +1119,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(
Expand All @@ -1126,7 +1146,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<string>());
this.LogAndUpdate(ref this.compilationStatus.DllGeneration, ErrorCode.GeneratingDllFailed);
return null;
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/QsCompiler/DataStructures/Diagnostics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,10 @@ type ErrorCode =
| PreEvaluationFailed = 7111
| RewriteStepExecutionFailed = 7112
| PostconditionVerificationFailed = 7113
// the corresponding warning code exists
| PreconditionVerificationFailed = 7202

| CsharpGenerationGeneratedError = 8001

| PublishingPerfResultsFailed = 8101
| PerformanceTrackingFailed = 8102
| SyntaxTreeNotMonomorphized = 8103
Expand Down Expand Up @@ -377,6 +378,7 @@ type WarningCode =
| UnresolvedItemsInGeneratedQs = 7101

| RewriteStepDiagnosticsGenerationFailed = 7201
// the corresponding error code exists
| PreconditionVerificationFailed = 7202
| RewriteStepLoadedViaReflection = 7203
| FailedToLoadRewriteStepViaReflection = 7204
Expand Down Expand Up @@ -877,9 +879,10 @@ 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 ->
Expand Down
6 changes: 5 additions & 1 deletion src/QsCompiler/Tests.Compiler/QirTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,11 @@ let ``QIR expressions`` () = qirTest false "TestExpressions"
[<Fact>]
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

Expand Down