From c7f55a53e5f682cfffe2d937216f8e53a491d34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Mon, 5 Apr 2021 10:57:44 -0700 Subject: [PATCH 001/145] Setup controller project (#597) * Create controller project. * Add script to test the QIR controller. * Test QIR controller as part of the build. * Renamed test controller script. * Update test-case file. --- Simulation.sln | 22 +++++++++ build/test.ps1 | 6 +++ src/Qir/Controller/Controller.cs | 26 ++++++++++ src/Qir/Controller/Program.cs | 48 +++++++++++++++++++ src/Qir/Controller/QirController.csproj | 12 +++++ src/Qir/Controller/test-cases/01.err | 1 + src/Qir/Controller/test-cases/01.in | 1 + src/Qir/Controller/test-cases/01.out | 1 + src/Qir/Controller/test-qir-controller.ps1 | 56 ++++++++++++++++++++++ 9 files changed, 173 insertions(+) create mode 100644 src/Qir/Controller/Controller.cs create mode 100644 src/Qir/Controller/Program.cs create mode 100644 src/Qir/Controller/QirController.csproj create mode 100644 src/Qir/Controller/test-cases/01.err create mode 100644 src/Qir/Controller/test-cases/01.in create mode 100644 src/Qir/Controller/test-cases/01.out create mode 100644 src/Qir/Controller/test-qir-controller.ps1 diff --git a/Simulation.sln b/Simulation.sln index da0f6964563..4ba93680295 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -103,6 +103,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-gen", "src\Qir\Runtime\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tracer-qir", "src\Qir\Runtime\test\QIR-tracer\qsharp\tracer-qir.csproj", "{5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "controller", "controller", "{A25E062D-C685-48DE-99D1-B5BC0DF73F89}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirController", "src\Qir\Controller\QirController.csproj", "{55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -739,6 +743,22 @@ Global {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|x64.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|x64.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|Any CPU.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|x64.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|x64.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -787,6 +807,8 @@ Global {9DF6FEB7-3111-4244-B4EE-A69C64043967} = {3FFDEA49-C6E8-45BB-BCA5-BBC5378F704F} {241693D7-4AA6-47C9-9F27-78F2A1EE0904} = {3FFDEA49-C6E8-45BB-BCA5-BBC5378F704F} {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7} = {3FFDEA49-C6E8-45BB-BCA5-BBC5378F704F} + {A25E062D-C685-48DE-99D1-B5BC0DF73F89} = {C637C9DF-14AA-48CB-95F3-73CE0AC5F9B1} + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3} = {A25E062D-C685-48DE-99D1-B5BC0DF73F89} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/build/test.ps1 b/build/test.ps1 index b80d5ab936f..c4d9e732bf3 100644 --- a/build/test.ps1 +++ b/build/test.ps1 @@ -43,6 +43,12 @@ if ($Env:ENABLE_QIRRUNTIME -ne "false") { if ($LastExitCode -ne 0) { $script:all_ok = $False } + + $qirController = (Join-Path $PSScriptRoot "../src/Qir/Controller") + & "$qirController/test-qir-controller.ps1" + if ($LastExitCode -ne 0) { + $script:all_ok = $False + } } else { Write-Host "Skipping test of qir runtime because ENABLE_QIRRUNTIME variable is set to: $Env:ENABLE_QIRRUNTIME ` and ENABLE_NATIVE variable is set to: $Env:ENABLE_NATIVE." diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs new file mode 100644 index 00000000000..0f613d5fc0c --- /dev/null +++ b/src/Qir/Controller/Controller.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Text; + +namespace Microsoft.Quantum.Qir +{ + internal static class Controller + { + internal static void Execute( + FileInfo input, + FileInfo output, + FileInfo error) + { + var outputFileStream = output.Exists ? output.OpenWrite() : output.Create(); + outputFileStream.Write(new UTF8Encoding().GetBytes("output")); + outputFileStream.Flush(); + outputFileStream.Close(); + var errorFileStream = error.Exists ? error.OpenWrite() : error.Create(); + errorFileStream.Write(new UTF8Encoding().GetBytes("error")); + errorFileStream.Flush(); + errorFileStream.Close(); + } + } +} diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs new file mode 100644 index 00000000000..e7fec1e6fd0 --- /dev/null +++ b/src/Qir/Controller/Program.cs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.CommandLine; +using System.CommandLine.Invocation; +using System.IO; + +namespace Microsoft.Quantum.Qir +{ + class Program + { + static void Main(string[] args) + { + var rootCommand = new RootCommand( + description: "Builds and runs QIR executable."); + + // Create and add options to the root command. + var inputOption = new Option( + aliases: new string[] { "--input"}) + { + Description = "Path to the file that contains the input.", + IsRequired = true + }; + + rootCommand.AddOption(inputOption); + var outputOption = new Option( + aliases: new string[] { "--output"}) + { + Description = "Path to the file to which the output will be written.", + IsRequired = true + }; + + rootCommand.AddOption(outputOption); + var errorOption = new Option( + aliases: new string[] { "--error",}) + { + Description = "Path to the file to which errors will be logged.", + IsRequired = true + }; + + rootCommand.AddOption(errorOption); + + // Bind to a handler and invoke. + rootCommand.Handler = CommandHandler.Create((input, output, error) => Controller.Execute(input, output, error)); + rootCommand.Invoke(args); + } + } +} diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj new file mode 100644 index 00000000000..0c21b5914f9 --- /dev/null +++ b/src/Qir/Controller/QirController.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/src/Qir/Controller/test-cases/01.err b/src/Qir/Controller/test-cases/01.err new file mode 100644 index 00000000000..760589cb5d6 --- /dev/null +++ b/src/Qir/Controller/test-cases/01.err @@ -0,0 +1 @@ +error \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/01.in b/src/Qir/Controller/test-cases/01.in new file mode 100644 index 00000000000..770eab4480b --- /dev/null +++ b/src/Qir/Controller/test-cases/01.in @@ -0,0 +1 @@ +input \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/01.out b/src/Qir/Controller/test-cases/01.out new file mode 100644 index 00000000000..6caf68aff42 --- /dev/null +++ b/src/Qir/Controller/test-cases/01.out @@ -0,0 +1 @@ +output \ No newline at end of file diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 new file mode 100644 index 00000000000..876626b703a --- /dev/null +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -0,0 +1,56 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +$all_ok = $True + +Write-Host "##[info]Test QIR Controller" + +$controllerProject = (Join-Path $PSScriptRoot QirController.csproj) +$testCasesFolder = (Join-Path $PSScriptRoot "test-cases") +$testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") +if (!(Test-Path $testArtifactsFolder -PathType Container)) { + New-Item -ItemType Directory -Force -Path $testArtifactsFolder +} +Get-ChildItem -Path $testArtifactsFolder | Remove-Item -Force + +# Go through each input file in the test cases folder. +Get-ChildItem $testCasesFolder -Filter *.in | +Foreach-Object { + # Get the paths to the output and error files to pass to the QIR controller. + $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) + $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) + dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile + + # Compare the expected content of the output and error files vs the actual content. + $expectedOutputFile = (Join-Path $testCasesFolder ($_.BaseName + ".out")) + $expectedOutput = Get-Content -Path $expectedOutputFile -Raw + $actualOutput = Get-Content -Path $outputFile -Raw + if (-not ($expectedOutput -ceq $actualOutput)) { + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Expected output:" + Write-Host $expectedOutput + Write-Host "##[info]Actual output:" + Write-Host $actualOutput + $script:all_ok = $False + break + } + + $expectedErrorFile = (Join-Path $testCasesFolder ($_.BaseName + ".err")) + $expectedError = Get-Content -Path $expectedErrorFile -Raw + $actualError = Get-Content -Path $errorFile -Raw + if (-not ($expectedError -ceq $actualError)) { + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Expected error:" + Write-Host $expectedError + Write-Host "##[info]Actual error:" + Write-Host $actualError + $script:all_ok = $False + break + } + + Write-Host "##[info]Test case '$($_.BaseName)' passed" +} + +if (-not $all_ok) { + throw "At least one project failed testing. Check the logs." +} From 56469cd85b70347cba5b363400b169c19f0c2b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 6 Apr 2021 14:09:05 -0700 Subject: [PATCH 002/145] Add missing EndProject. --- Simulation.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/Simulation.sln b/Simulation.sln index ca6594be7e6..9a65f34a9db 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -112,6 +112,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandaloneInputReference", "StandaloneInputReference", "{A7DB7367-9FD6-4164-8263-A05077BE54AB}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qir-standalone-input-reference", "src\Qir\Samples\StandaloneInputReference\qsharp\qir-standalone-input-reference.csproj", "{D7D34736-A719-4B45-A33F-2723F59EC29D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU From 1dbd8f61891f81d25c8195b102092ed492730352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 6 Apr 2021 14:39:44 -0700 Subject: [PATCH 003/145] Re-add controller project to Simulation solution. --- Simulation.sln | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/Simulation.sln b/Simulation.sln index 9a65f34a9db..f888733494b 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -93,25 +93,29 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7F7BB60A EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FullstateSimulator", "FullstateSimulator", "{EAC5EAE7-D1B3-4726-AFDB-73000E62176A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qir-test-simulator", "src\Qir\Tests\FullstateSimulator\qsharp\qir-test-simulator.csproj", "{C7531119-9730-497A-9D11-8BBB3761B726}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-test-simulator", "src\Qir\Tests\FullstateSimulator\qsharp\qir-test-simulator.csproj", "{C7531119-9730-497A-9D11-8BBB3761B726}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QIR-dynamic", "QIR-dynamic", "{3DFACF7F-D5C2-455B-AB8A-26908DEF7E2D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qir-test-random", "src\Qir\Tests\QIR-dynamic\qsharp\qir-test-random.csproj", "{5DBF6402-D9CD-4470-A309-3755CFDA42CF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-test-random", "src\Qir\Tests\QIR-dynamic\qsharp\qir-test-random.csproj", "{5DBF6402-D9CD-4470-A309-3755CFDA42CF}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QIR-static", "QIR-static", "{54000816-122C-4AA0-9FE9-B0ABB9547232}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qir-gen", "src\Qir\Tests\QIR-static\qsharp\qir-gen.csproj", "{33ED37AB-61B1-4A49-9952-58D19AA8EF30}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-gen", "src\Qir\Tests\QIR-static\qsharp\qir-gen.csproj", "{33ED37AB-61B1-4A49-9952-58D19AA8EF30}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QIR-tracer", "QIR-tracer", "{522EAA31-6317-42D5-831F-C39313DF03A0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tracer-qir", "src\Qir\Tests\QIR-tracer\qsharp\tracer-qir.csproj", "{002174F4-BFA8-4675-908D-0E9C32ED951A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tracer-qir", "src\Qir\Tests\QIR-tracer\qsharp\tracer-qir.csproj", "{002174F4-BFA8-4675-908D-0E9C32ED951A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{AAFB81D3-BC87-404D-BA64-AF40B2D2E45A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandaloneInputReference", "StandaloneInputReference", "{A7DB7367-9FD6-4164-8263-A05077BE54AB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qir-standalone-input-reference", "src\Qir\Samples\StandaloneInputReference\qsharp\qir-standalone-input-reference.csproj", "{D7D34736-A719-4B45-A33F-2723F59EC29D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-standalone-input-reference", "src\Qir\Samples\StandaloneInputReference\qsharp\qir-standalone-input-reference.csproj", "{D7D34736-A719-4B45-A33F-2723F59EC29D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Controller", "Controller", "{4E07F247-ED93-4497-8B58-022314308E67}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirController", "src\Qir\Controller\QirController.csproj", "{A77E6661-D143-4E3E-BCD1-8E321A966829}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -749,6 +753,22 @@ Global {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|x64.ActiveCfg = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|x64.Build.0 = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|Any CPU.Build.0 = Release|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|x64.ActiveCfg = Release|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|x64.Build.0 = Release|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -802,6 +822,8 @@ Global {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {A7DB7367-9FD6-4164-8263-A05077BE54AB} = {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} {D7D34736-A719-4B45-A33F-2723F59EC29D} = {A7DB7367-9FD6-4164-8263-A05077BE54AB} + {4E07F247-ED93-4497-8B58-022314308E67} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} + {A77E6661-D143-4E3E-BCD1-8E321A966829} = {4E07F247-ED93-4497-8B58-022314308E67} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} From 0cbc02c7828353ce7003f994bb8d6dab14a39c5e Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Wed, 7 Apr 2021 16:00:43 -0700 Subject: [PATCH 004/145] Create initial prototype for controller (with dependencies unimplemented) --- Simulation.sln | 19 + src/Qir/Controller/Constant.cs | 16 + src/Qir/Controller/Controller.cs | 51 +- .../Controller/Driver/IQirDriverGenerator.cs | 20 + .../Controller/Driver/QirDriverGenerator.cs | 17 + src/Qir/Controller/Executable/ClangClient.cs | 22 + src/Qir/Controller/Executable/IClangClient.cs | 15 + .../Executable/IQirExecutableGenerator.cs | 21 + .../Executable/IQuantumExecutableRunner.cs | 21 + .../Executable/QirExecutableGenerator.cs | 24 + .../Executable/QuantumExecutableRunner.cs | 17 + src/Qir/Controller/Program.cs | 22 +- src/Qir/Controller/QirController.csproj | 15 +- .../Tests.QirController/ControllerTests.cs | 125 + .../Tests.QirController.csproj | 20 + .../qir/qir-standalone-input-reference.ll | 1427 +++++++++++ .../qsharp/qir/qir-test-simulator.ll | 1387 +++++++++++ .../QIR-dynamic/qsharp/qir/qir-test-random.ll | 159 ++ .../test/QIR-tracer/qsharp/qir/tracer-qir.ll | 2080 +++++++++++++++++ 19 files changed, 5462 insertions(+), 16 deletions(-) create mode 100644 src/Qir/Controller/Constant.cs create mode 100644 src/Qir/Controller/Driver/IQirDriverGenerator.cs create mode 100644 src/Qir/Controller/Driver/QirDriverGenerator.cs create mode 100644 src/Qir/Controller/Executable/ClangClient.cs create mode 100644 src/Qir/Controller/Executable/IClangClient.cs create mode 100644 src/Qir/Controller/Executable/IQirExecutableGenerator.cs create mode 100644 src/Qir/Controller/Executable/IQuantumExecutableRunner.cs create mode 100644 src/Qir/Controller/Executable/QirExecutableGenerator.cs create mode 100644 src/Qir/Controller/Executable/QuantumExecutableRunner.cs create mode 100644 src/Qir/Controller/Tests.QirController/ControllerTests.cs create mode 100644 src/Qir/Controller/Tests.QirController/Tests.QirController.csproj create mode 100644 src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll create mode 100644 src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll create mode 100644 src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll create mode 100644 src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll diff --git a/Simulation.sln b/Simulation.sln index 4ba93680295..6ab8f7cfd5b 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -107,6 +107,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "controller", "controller", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirController", "src\Qir\Controller\QirController.csproj", "{55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.QirController", "src\Qir\Controller\Tests.QirController\Tests.QirController.csproj", "{2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -759,6 +761,22 @@ Global {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|x64.ActiveCfg = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|x64.Build.0 = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|Any CPU.Build.0 = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|x64.ActiveCfg = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|x64.Build.0 = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -809,6 +827,7 @@ Global {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7} = {3FFDEA49-C6E8-45BB-BCA5-BBC5378F704F} {A25E062D-C685-48DE-99D1-B5BC0DF73F89} = {C637C9DF-14AA-48CB-95F3-73CE0AC5F9B1} {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3} = {A25E062D-C685-48DE-99D1-B5BC0DF73F89} + {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68} = {A25E062D-C685-48DE-99D1-B5BC0DF73F89} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/src/Qir/Controller/Constant.cs b/src/Qir/Controller/Constant.cs new file mode 100644 index 00000000000..42475cb494b --- /dev/null +++ b/src/Qir/Controller/Constant.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Qir +{ + public static class Constant + { + public static class FilePath + { + // TODO validate/improve these names. + public const string BytecodeFilePath = "/home/bytecode.ll"; + public const string DriverFilePath = "/home/driver.cpp"; + public const string ExecutableFilePath = "/home/simulation.exe"; + } + } +} diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 0f613d5fc0c..5d43815a7b4 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -2,25 +2,48 @@ // Licensed under the MIT License. using System.IO; -using System.Text; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Driver; +using Microsoft.Quantum.Qir.Executable; +using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; namespace Microsoft.Quantum.Qir { - internal static class Controller + public static class Controller { - internal static void Execute( - FileInfo input, - FileInfo output, - FileInfo error) + public static async Task ExecuteAsync( + FileInfo inputFile, + FileInfo outputFile, + DirectoryInfo libraryDirectory, + FileInfo errorFile, + FileInfo bytecodeFile, + IQirDriverGenerator driverGenerator, + IQirExecutableGenerator executableGenerator, + IQuantumExecutableRunner executableRunner) { - var outputFileStream = output.Exists ? output.OpenWrite() : output.Create(); - outputFileStream.Write(new UTF8Encoding().GetBytes("output")); - outputFileStream.Flush(); - outputFileStream.Close(); - var errorFileStream = error.Exists ? error.OpenWrite() : error.Create(); - errorFileStream.Write(new UTF8Encoding().GetBytes("error")); - errorFileStream.Flush(); - errorFileStream.Close(); + // TODO: Error handling. + // TODO: Logging. + // Step 1: Parse input. + using var inputFileStream = inputFile.OpenRead(); + var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); + + // Step 2: Create bytecode file. + using (var bytecodeFileStream = bytecodeFile.OpenWrite()) + { + await bytecodeFileStream.WriteAsync(input.QirBytecode.Array, input.QirBytecode.Offset, input.QirBytecode.Count); + } + + // Step 3: Create the driver file. + var driverFile = new FileInfo(Constant.FilePath.DriverFilePath); + await driverGenerator.GenerateQirDriverCppAsync(input.EntryPoint, driverFile); + + // Step 4: Create the executable. + var executableFile = new FileInfo(Constant.FilePath.ExecutableFilePath); + await executableGenerator.GenerateExecutableAsync(driverFile, bytecodeFile, libraryDirectory, executableFile); + + // Step 5: Run the executable. + using var outputFileStream = outputFile.Exists ? outputFile.OpenWrite() : outputFile.Create(); + await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); } } } diff --git a/src/Qir/Controller/Driver/IQirDriverGenerator.cs b/src/Qir/Controller/Driver/IQirDriverGenerator.cs new file mode 100644 index 00000000000..5e26df14ee5 --- /dev/null +++ b/src/Qir/Controller/Driver/IQirDriverGenerator.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Driver +{ + public interface IQirDriverGenerator + { + /// + /// Generates the C++ driver source file to compile with the bytecode. + /// + /// Entry point information. + /// The file to which the source will be written. + /// + Task GenerateQirDriverCppAsync(EntryPointOperation entryPointOperation, FileInfo driverFile); + } +} diff --git a/src/Qir/Controller/Driver/QirDriverGenerator.cs b/src/Qir/Controller/Driver/QirDriverGenerator.cs new file mode 100644 index 00000000000..34caeb01f59 --- /dev/null +++ b/src/Qir/Controller/Driver/QirDriverGenerator.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Driver +{ + public class QirDriverGenerator : IQirDriverGenerator + { + public Task GenerateQirDriverCppAsync(EntryPointOperation entryPointOperation, FileInfo driverFile) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/src/Qir/Controller/Executable/ClangClient.cs b/src/Qir/Controller/Executable/ClangClient.cs new file mode 100644 index 00000000000..4a6c993dd86 --- /dev/null +++ b/src/Qir/Controller/Executable/ClangClient.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.CommandLine.Invocation; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Executable +{ + public class ClangClient : IClangClient + { + private const string LinkFlag = " -l "; + + public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string outputPath) + { + var inputsArg = string.Join(' ', inputFiles); + var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; + var arguments = $"{inputsArg} -L {libraryPath} {librariesArg} -o {outputPath}"; + var result = await Process.ExecuteAsync("clang", arguments, stdOut: s => { Console.WriteLine(s); }, stdErr: s => { Console.WriteLine(s); }); + } + } +} diff --git a/src/Qir/Controller/Executable/IClangClient.cs b/src/Qir/Controller/Executable/IClangClient.cs new file mode 100644 index 00000000000..313c92f3e89 --- /dev/null +++ b/src/Qir/Controller/Executable/IClangClient.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Executable +{ + /// + /// Wraps the 'clang' tool used for compilation. + /// + public interface IClangClient + { + Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string outputPath); + } +} diff --git a/src/Qir/Controller/Executable/IQirExecutableGenerator.cs b/src/Qir/Controller/Executable/IQirExecutableGenerator.cs new file mode 100644 index 00000000000..54854cfed21 --- /dev/null +++ b/src/Qir/Controller/Executable/IQirExecutableGenerator.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Executable +{ + public interface IQirExecutableGenerator + { + /// + /// Generates a quantum simulation program executable. + /// + /// The C++ source driver file. + /// The QIR bytecode. + /// Location of the libraries that must be linked. + /// File path to create the executable at. + /// + Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, FileInfo executableFile); + } +} diff --git a/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs b/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs new file mode 100644 index 00000000000..135fbbbfb4f --- /dev/null +++ b/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Executable +{ + public interface IQuantumExecutableRunner + { + /// + /// Runs a quantum program executable with the given arguments. + /// + /// Location of the executable to run. + /// Entry point and arguments to pass. + /// Location to write program output. + /// + Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile); + } +} diff --git a/src/Qir/Controller/Executable/QirExecutableGenerator.cs b/src/Qir/Controller/Executable/QirExecutableGenerator.cs new file mode 100644 index 00000000000..1b521c6f762 --- /dev/null +++ b/src/Qir/Controller/Executable/QirExecutableGenerator.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Executable +{ + public class QirExecutableGenerator : IQirExecutableGenerator + { + private readonly IClangClient clangClient; + + public QirExecutableGenerator(IClangClient clangClient) + { + this.clangClient = clangClient; + } + + public Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, FileInfo executableFile) + { + // TODO: Compile and link libraries- "Microsoft.Quantum.Qir.Runtime", "Microsoft.Quantum.Qir.QSharp.Foundation", "Microsoft.Quantum.Qir.QSharp.Core" + throw new System.NotImplementedException(); + } + } +} diff --git a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs new file mode 100644 index 00000000000..14a35fc8659 --- /dev/null +++ b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Executable +{ + public class QuantumExecutableRunner : IQuantumExecutableRunner + { + public Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index e7fec1e6fd0..20a5791de12 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -4,6 +4,8 @@ using System.CommandLine; using System.CommandLine.Invocation; using System.IO; +using Microsoft.Quantum.Qir.Driver; +using Microsoft.Quantum.Qir.Executable; namespace Microsoft.Quantum.Qir { @@ -31,6 +33,15 @@ static void Main(string[] args) }; rootCommand.AddOption(outputOption); + + var libraryDirectoryOption = new Option( + aliases: new string[] { "--libraryDirectory" }) + { + Description = "Path to the directory containing the libraries that must be linked to the driver executable.", + IsRequired = true + }; + + rootCommand.AddOption(libraryDirectoryOption); var errorOption = new Option( aliases: new string[] { "--error",}) { @@ -40,8 +51,17 @@ static void Main(string[] args) rootCommand.AddOption(errorOption); + var execGenerator = new QirExecutableGenerator(new ClangClient()); + var driverGenerator = new QirDriverGenerator(); + var execRunner = new QuantumExecutableRunner(); + + // The bytecode file is not needed as an input to the program, but we provide the path as an argument to the controller so it can be configured by tests. + var bytecodeFile = new FileInfo(Constant.FilePath.BytecodeFilePath); + // Bind to a handler and invoke. - rootCommand.Handler = CommandHandler.Create((input, output, error) => Controller.Execute(input, output, error)); + rootCommand.Handler = CommandHandler.Create( + async (input, output, libraryDirectory, error) => + await Controller.ExecuteAsync(input, output, libraryDirectory, error, bytecodeFile, driverGenerator, execGenerator, execRunner)); rootCommand.Invoke(args); } } diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index 0c21b5914f9..e6f5c6fa3fc 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -1,11 +1,24 @@ - + Exe netcoreapp3.1 + Microsoft.Quantum.Qir + + 5 + + + + + + + + + + diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs new file mode 100644 index 00000000000..83c6b17c2b7 --- /dev/null +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir; +using Microsoft.Quantum.Qir.Driver; +using Microsoft.Quantum.Qir.Executable; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper; +using Moq; +using Xunit; +using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; + +namespace Tests.QirController +{ + public class ControllerTests : IDisposable + { + private Mock driverGeneratorMock; + private Mock executableGeneratorMock; + private Mock executableRunnerMock; + private FileInfo inputFile; + private FileInfo bytecodeFile; + private FileInfo errorFile; + private FileInfo outputFile; + private QirExecutionWrapper input; + + public ControllerTests() + { + driverGeneratorMock = new Mock(); + executableGeneratorMock = new Mock(); + executableRunnerMock = new Mock(); + inputFile = new FileInfo($"{Guid.NewGuid()}-input"); + bytecodeFile = new FileInfo($"{Guid.NewGuid()}-bytecode"); + errorFile = new FileInfo($"{Guid.NewGuid()}-error"); + outputFile = new FileInfo($"{Guid.NewGuid()}-output"); + + // Create a QirExecutableWrapper to be used by the tests. + byte[] bytecode = { 1, 2, 3, 4, 5 }; + input = new QirExecutionWrapper() + { + EntryPoint = new EntryPointOperation() + { + Arguments = new List + { + new Argument() + { + Position = 0, + Name = "argname", + Values = new List { new ArgumentValue { String = "argvalue" } }, + } + } + }, + QirBytecode = new ArraySegment(bytecode, 1, 3), + }; + using var fileStream = inputFile.OpenWrite(); + QirExecutionWrapperSerialization.SerializeToFastBinary(input, fileStream); + } + + public void Dispose() + { + inputFile.Delete(); + bytecodeFile.Delete(); + errorFile.Delete(); + outputFile.Delete(); + } + + [Fact] + public async Task TestExecute() + { + var libraryDirectory = new DirectoryInfo("libraries"); + var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); + var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Callback(() => + { + // Verify that the "bytecode" file was created correctly. + using var bytecode = bytecodeFile.OpenRead(); + Assert.Equal(bytecode.Length, input.QirBytecode.Count); + for (var i = 0; i < bytecode.Length; ++i) + { + Assert.Equal(input.QirBytecode[i], bytecode.ReadByte()); + } + }); + + await Controller.ExecuteAsync( + inputFile, + outputFile, + libraryDirectory, + errorFile, + bytecodeFile, + driverGeneratorMock.Object, + executableGeneratorMock.Object, + executableRunnerMock.Object); + + // Verify driver was created. + driverGeneratorMock.Verify(obj => obj.GenerateQirDriverCppAsync( + It.Is(entryPoint => EntryPointsAreEqual(entryPoint, input.EntryPoint)), + It.Is(fileInfo => fileInfo.FullName == expectedDriverPath.FullName))); + + // Verify executable was generated. + executableGeneratorMock.Verify(obj => obj.GenerateExecutableAsync( + It.Is(driverPath => driverPath.FullName == expectedDriverPath.FullName), + It.Is(actualBytecodeFile => actualBytecodeFile.FullName == bytecodeFile.FullName), + It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), + It.Is(actualExecutableFile => actualExecutableFile.FullName == expectedExecutablePath.FullName))); + + // Verify executable was run. + executableRunnerMock.Verify(obj => obj.RunExecutableAsync( + It.Is(actualExecutableFile => actualExecutableFile.FullName == expectedExecutablePath.FullName), + It.Is(entryPoint => EntryPointsAreEqual(entryPoint, input.EntryPoint)), + It.Is(actualOutputFile => actualOutputFile.FullName == outputFile.FullName))); + } + + private bool EntryPointsAreEqual(EntryPointOperation entryPointA, EntryPointOperation entryPointB) + { + var method = typeof(Extensions) + .GetMethod("ValueEquals", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(EntryPointOperation), typeof(EntryPointOperation) }, null); + object[] parameters = { entryPointA, entryPointB }; + return (bool)method.Invoke(null, parameters); + } + } +} diff --git a/src/Qir/Controller/Tests.QirController/Tests.QirController.csproj b/src/Qir/Controller/Tests.QirController/Tests.QirController.csproj new file mode 100644 index 00000000000..ba5183ca742 --- /dev/null +++ b/src/Qir/Controller/Tests.QirController/Tests.QirController.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp3.1 + false + + + + + + + + + + + + + + + diff --git a/src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll b/src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll new file mode 100644 index 00000000000..3b75c0034f7 --- /dev/null +++ b/src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll @@ -0,0 +1,1427 @@ + +%Range = type { i64, i64, i64 } +%Tuple = type opaque +%Result = type opaque +%Array = type opaque +%String = type opaque +%Callable = type opaque + +@PauliI = constant i2 0 +@PauliX = constant i2 1 +@PauliY = constant i2 -1 +@PauliZ = constant i2 -2 +@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } +@0 = internal constant [36 x i8] c"Exercise Supported Inputs Reference\00" +@1 = internal constant [11 x i8] c"intValue: \00" +@Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@2 = internal constant [11 x i8] c"intArray: \00" +@3 = internal constant [3 x i8] c" (\00" +@4 = internal constant [2 x i8] c")\00" +@5 = internal constant [14 x i8] c"doubleValue: \00" +@Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@6 = internal constant [14 x i8] c"doubleArray: \00" +@7 = internal constant [3 x i8] c" (\00" +@8 = internal constant [2 x i8] c")\00" +@9 = internal constant [12 x i8] c"boolValue: \00" +@Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@10 = internal constant [12 x i8] c"boolArray: \00" +@11 = internal constant [3 x i8] c" (\00" +@12 = internal constant [2 x i8] c")\00" +@13 = internal constant [13 x i8] c"pauliValue: \00" +@Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@14 = internal constant [13 x i8] c"pauliArray: \00" +@15 = internal constant [3 x i8] c" (\00" +@16 = internal constant [2 x i8] c")\00" +@17 = internal constant [13 x i8] c"rangeValue: \00" +@18 = internal constant [14 x i8] c"resultValue: \00" +@Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@19 = internal constant [14 x i8] c"resultArray: \00" +@20 = internal constant [3 x i8] c" (\00" +@21 = internal constant [2 x i8] c")\00" +@22 = internal constant [14 x i8] c"stringValue: \00" +@23 = internal constant [2 x i8] c"[\00" +@24 = internal constant [3 x i8] c", \00" +@25 = internal constant [2 x i8] c"]\00" +@26 = internal constant [2 x i8] c"[\00" +@27 = internal constant [3 x i8] c", \00" +@28 = internal constant [2 x i8] c"]\00" +@29 = internal constant [2 x i8] c"[\00" +@30 = internal constant [3 x i8] c", \00" +@31 = internal constant [2 x i8] c"]\00" +@32 = internal constant [2 x i8] c"[\00" +@33 = internal constant [3 x i8] c", \00" +@34 = internal constant [2 x i8] c"]\00" +@35 = internal constant [2 x i8] c"[\00" +@36 = internal constant [3 x i8] c", \00" +@37 = internal constant [2 x i8] c"]\00" +@38 = internal constant [3 x i8] c"()\00" + +define void @Quantum__StandaloneSupportedInputs__ExerciseInputs__body(i64 %intValue, %Array* %intArray, double %doubleValue, %Array* %doubleArray, i1 %boolValue, %Array* %boolArray, i2 %pauliValue, %Array* %pauliArray, %Range %rangeValue, %Result* %resultValue, %Array* %resultArray, %String* %stringValue) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %intArray, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %doubleArray, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %boolArray, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %pauliArray, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %resultArray, i32 1) + %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @0, i32 0, i32 0)) + call void @__quantum__rt__message(%String* %0) + %1 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @1, i32 0, i32 0)) + %2 = call %String* @__quantum__rt__int_to_string(i64 %intValue) + %3 = call %String* @__quantum__rt__string_concatenate(%String* %1, %String* %2) + call void @__quantum__rt__string_update_reference_count(%String* %1, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %2, i32 -1) + call void @__quantum__rt__message(%String* %3) + %4 = call %String* @Quantum__StandaloneSupportedInputs___58b06fb8838645aba850713a715678d6_ArrayToString__body(%Array* %intArray) + %5 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %6 = call i64 @Microsoft__Quantum__Arrays___8487a9df7d0d4ac5a6694fb1d077b2b4_Count__body(%Callable* %5, %Array* %intArray) + %7 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @2, i32 0, i32 0)) + call void @__quantum__rt__string_update_reference_count(%String* %4, i32 1) + %8 = call %String* @__quantum__rt__string_concatenate(%String* %7, %String* %4) + call void @__quantum__rt__string_update_reference_count(%String* %7, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %4, i32 -1) + %9 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @3, i32 0, i32 0)) + %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) + call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) + %11 = call %String* @__quantum__rt__int_to_string(i64 %6) + %12 = call %String* @__quantum__rt__string_concatenate(%String* %10, %String* %11) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) + %13 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @4, i32 0, i32 0)) + %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) + call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) + call void @__quantum__rt__message(%String* %14) + %15 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @5, i32 0, i32 0)) + %16 = call %String* @__quantum__rt__double_to_string(double %doubleValue) + %17 = call %String* @__quantum__rt__string_concatenate(%String* %15, %String* %16) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %16, i32 -1) + call void @__quantum__rt__message(%String* %17) + %18 = call %String* @Quantum__StandaloneSupportedInputs___651cdf0b91af440a8c52eefc05d57b06_ArrayToString__body(%Array* %doubleArray) + %19 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %20 = call i64 @Microsoft__Quantum__Arrays___1575e931e75b478d9338ff1c1ba98161_Count__body(%Callable* %19, %Array* %doubleArray) + %21 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @6, i32 0, i32 0)) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 1) + %22 = call %String* @__quantum__rt__string_concatenate(%String* %21, %String* %18) + call void @__quantum__rt__string_update_reference_count(%String* %21, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) + %23 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @7, i32 0, i32 0)) + %24 = call %String* @__quantum__rt__string_concatenate(%String* %22, %String* %23) + call void @__quantum__rt__string_update_reference_count(%String* %22, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %23, i32 -1) + %25 = call %String* @__quantum__rt__int_to_string(i64 %20) + %26 = call %String* @__quantum__rt__string_concatenate(%String* %24, %String* %25) + call void @__quantum__rt__string_update_reference_count(%String* %24, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %25, i32 -1) + %27 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @8, i32 0, i32 0)) + %28 = call %String* @__quantum__rt__string_concatenate(%String* %26, %String* %27) + call void @__quantum__rt__string_update_reference_count(%String* %26, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %27, i32 -1) + call void @__quantum__rt__message(%String* %28) + %29 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @9, i32 0, i32 0)) + %30 = call %String* @__quantum__rt__bool_to_string(i1 %boolValue) + %31 = call %String* @__quantum__rt__string_concatenate(%String* %29, %String* %30) + call void @__quantum__rt__string_update_reference_count(%String* %29, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %30, i32 -1) + call void @__quantum__rt__message(%String* %31) + %32 = call %String* @Quantum__StandaloneSupportedInputs___f5a60aadd6b1405d8efce41485ff4d80_ArrayToString__body(%Array* %boolArray) + %33 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %34 = call i64 @Microsoft__Quantum__Arrays___67c459c137a0446995c133a29250678d_Count__body(%Callable* %33, %Array* %boolArray) + %35 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @10, i32 0, i32 0)) + call void @__quantum__rt__string_update_reference_count(%String* %32, i32 1) + %36 = call %String* @__quantum__rt__string_concatenate(%String* %35, %String* %32) + call void @__quantum__rt__string_update_reference_count(%String* %35, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %32, i32 -1) + %37 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @11, i32 0, i32 0)) + %38 = call %String* @__quantum__rt__string_concatenate(%String* %36, %String* %37) + call void @__quantum__rt__string_update_reference_count(%String* %36, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %37, i32 -1) + %39 = call %String* @__quantum__rt__int_to_string(i64 %34) + %40 = call %String* @__quantum__rt__string_concatenate(%String* %38, %String* %39) + call void @__quantum__rt__string_update_reference_count(%String* %38, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %39, i32 -1) + %41 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @12, i32 0, i32 0)) + %42 = call %String* @__quantum__rt__string_concatenate(%String* %40, %String* %41) + call void @__quantum__rt__string_update_reference_count(%String* %40, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %41, i32 -1) + call void @__quantum__rt__message(%String* %42) + %43 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @13, i32 0, i32 0)) + %44 = call %String* @__quantum__rt__pauli_to_string(i2 %pauliValue) + %45 = call %String* @__quantum__rt__string_concatenate(%String* %43, %String* %44) + call void @__quantum__rt__string_update_reference_count(%String* %43, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %44, i32 -1) + call void @__quantum__rt__message(%String* %45) + %46 = call %String* @Quantum__StandaloneSupportedInputs___ec0b3349aeaf419f9d7d96decefd1869_ArrayToString__body(%Array* %pauliArray) + %47 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %48 = call i64 @Microsoft__Quantum__Arrays___c71932228c1b4b6fb8c3c63c9d8e35e4_Count__body(%Callable* %47, %Array* %pauliArray) + %49 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @14, i32 0, i32 0)) + call void @__quantum__rt__string_update_reference_count(%String* %46, i32 1) + %50 = call %String* @__quantum__rt__string_concatenate(%String* %49, %String* %46) + call void @__quantum__rt__string_update_reference_count(%String* %49, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %46, i32 -1) + %51 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @15, i32 0, i32 0)) + %52 = call %String* @__quantum__rt__string_concatenate(%String* %50, %String* %51) + call void @__quantum__rt__string_update_reference_count(%String* %50, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %51, i32 -1) + %53 = call %String* @__quantum__rt__int_to_string(i64 %48) + %54 = call %String* @__quantum__rt__string_concatenate(%String* %52, %String* %53) + call void @__quantum__rt__string_update_reference_count(%String* %52, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %53, i32 -1) + %55 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @16, i32 0, i32 0)) + %56 = call %String* @__quantum__rt__string_concatenate(%String* %54, %String* %55) + call void @__quantum__rt__string_update_reference_count(%String* %54, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %55, i32 -1) + call void @__quantum__rt__message(%String* %56) + %57 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @17, i32 0, i32 0)) + %58 = call %String* @__quantum__rt__range_to_string(%Range %rangeValue) + %59 = call %String* @__quantum__rt__string_concatenate(%String* %57, %String* %58) + call void @__quantum__rt__string_update_reference_count(%String* %57, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %58, i32 -1) + call void @__quantum__rt__message(%String* %59) + %60 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @18, i32 0, i32 0)) + %61 = call %String* @__quantum__rt__result_to_string(%Result* %resultValue) + %62 = call %String* @__quantum__rt__string_concatenate(%String* %60, %String* %61) + call void @__quantum__rt__string_update_reference_count(%String* %60, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %61, i32 -1) + call void @__quantum__rt__message(%String* %62) + %63 = call %String* @Quantum__StandaloneSupportedInputs___c22db911562e4518b3ec04b3a395976a_ArrayToString__body(%Array* %resultArray) + %64 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %65 = call i64 @Microsoft__Quantum__Arrays___aa464afb2404486a86d7d9b45b4e8d2c_Count__body(%Callable* %64, %Array* %resultArray) + %66 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @19, i32 0, i32 0)) + call void @__quantum__rt__string_update_reference_count(%String* %63, i32 1) + %67 = call %String* @__quantum__rt__string_concatenate(%String* %66, %String* %63) + call void @__quantum__rt__string_update_reference_count(%String* %66, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %63, i32 -1) + %68 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @20, i32 0, i32 0)) + %69 = call %String* @__quantum__rt__string_concatenate(%String* %67, %String* %68) + call void @__quantum__rt__string_update_reference_count(%String* %67, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %68, i32 -1) + %70 = call %String* @__quantum__rt__int_to_string(i64 %65) + %71 = call %String* @__quantum__rt__string_concatenate(%String* %69, %String* %70) + call void @__quantum__rt__string_update_reference_count(%String* %69, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %70, i32 -1) + %72 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @21, i32 0, i32 0)) + %73 = call %String* @__quantum__rt__string_concatenate(%String* %71, %String* %72) + call void @__quantum__rt__string_update_reference_count(%String* %71, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %72, i32 -1) + call void @__quantum__rt__message(%String* %73) + %74 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @22, i32 0, i32 0)) + call void @__quantum__rt__string_update_reference_count(%String* %stringValue, i32 1) + %75 = call %String* @__quantum__rt__string_concatenate(%String* %74, %String* %stringValue) + call void @__quantum__rt__string_update_reference_count(%String* %74, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %stringValue, i32 -1) + call void @__quantum__rt__message(%String* %75) + call void @__quantum__rt__array_update_alias_count(%Array* %intArray, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %doubleArray, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %boolArray, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %pauliArray, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %resultArray, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %3, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %4, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %5, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %5, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %28, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %31, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %32, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %33, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %33, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %42, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %45, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %46, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %47, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %47, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %56, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %59, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %62, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %63, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %64, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %64, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %73, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %75, i32 -1) + ret void +} + +declare void @__quantum__rt__array_update_alias_count(%Array*, i32) + +declare %String* @__quantum__rt__string_create(i8*) + +declare void @__quantum__rt__message(%String*) + +declare void @__quantum__rt__string_update_reference_count(%String*, i32) + +declare %String* @__quantum__rt__int_to_string(i64) + +declare %String* @__quantum__rt__string_concatenate(%String*, %String*) + +define %String* @Quantum__StandaloneSupportedInputs___58b06fb8838645aba850713a715678d6_ArrayToString__body(%Array* %array) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %first = alloca i1, align 1 + store i1 true, i1* %first, align 1 + %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @23, i32 0, i32 0)) + %itemsString = alloca %String*, align 8 + store %String* %0, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) + %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %2 = sub i64 %1, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] + %4 = icmp sle i64 %3, %2 + br i1 %4, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) + %6 = bitcast i8* %5 to i64* + %item = load i64, i64* %6, align 4 + %7 = load i1, i1* %first, align 1 + br i1 %7, label %then0__1, label %else__1 + +then0__1: ; preds = %body__1 + store i1 false, i1* %first, align 1 + %8 = load %String*, %String** %itemsString, align 8 + %9 = call %String* @__quantum__rt__int_to_string(i64 %item) + %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) + store %String* %10, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) + br label %continue__1 + +else__1: ; preds = %body__1 + %11 = load %String*, %String** %itemsString, align 8 + %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @24, i32 0, i32 0)) + %13 = call %String* @__quantum__rt__int_to_string(i64 %item) + %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) + call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) + %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) + store %String* %15, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %16 = add i64 %3, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %17 = load %String*, %String** %itemsString, align 8 + %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @25, i32 0, i32 0)) + %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) + store %String* %19, %String** %itemsString, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) + ret %String* %19 +} + +define i64 @Microsoft__Quantum__Arrays___8487a9df7d0d4ac5a6694fb1d077b2b4_Count__body(%Callable* %predicate, %Array* %array) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %totalFound = alloca i64, align 8 + store i64 0, i64* %totalFound, align 4 + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %1 = sub i64 %0, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %3 = icmp sle i64 %2, %1 + br i1 %3, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) + %5 = bitcast i8* %4 to i64* + %element = load i64, i64* %5, align 4 + %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i64* getelementptr (i64, i64* null, i32 1) to i64)) + %7 = bitcast %Tuple* %6 to { i64 }* + %8 = getelementptr inbounds { i64 }, { i64 }* %7, i32 0, i32 0 + store i64 %element, i64* %8, align 4 + %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) + call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) + %10 = bitcast %Tuple* %9 to { i1 }* + %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 + %12 = load i1, i1* %11, align 1 + br i1 %12, label %then0__1, label %continue__1 + +then0__1: ; preds = %body__1 + %13 = load i64, i64* %totalFound, align 4 + %14 = add i64 %13, 1 + store i64 %14, i64* %totalFound, align 4 + br label %continue__1 + +continue__1: ; preds = %then0__1, %body__1 + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %15 = add i64 %2, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = load i64, i64* %totalFound, align 4 + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + ret i64 %16 +} + +define void @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { i64 }* + %1 = getelementptr inbounds { i64 }, { i64 }* %0, i32 0, i32 0 + %2 = load i64, i64* %1, align 4 + %3 = call i1 @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body(i64 %2) + %4 = bitcast %Tuple* %result-tuple to { i1 }* + %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 + store i1 %3, i1* %5, align 1 + ret void +} + +declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i32)*]*, %Tuple*) + +declare %String* @__quantum__rt__double_to_string(double) + +define %String* @Quantum__StandaloneSupportedInputs___651cdf0b91af440a8c52eefc05d57b06_ArrayToString__body(%Array* %array) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %first = alloca i1, align 1 + store i1 true, i1* %first, align 1 + %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @26, i32 0, i32 0)) + %itemsString = alloca %String*, align 8 + store %String* %0, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) + %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %2 = sub i64 %1, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] + %4 = icmp sle i64 %3, %2 + br i1 %4, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) + %6 = bitcast i8* %5 to double* + %item = load double, double* %6, align 8 + %7 = load i1, i1* %first, align 1 + br i1 %7, label %then0__1, label %else__1 + +then0__1: ; preds = %body__1 + store i1 false, i1* %first, align 1 + %8 = load %String*, %String** %itemsString, align 8 + %9 = call %String* @__quantum__rt__double_to_string(double %item) + %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) + store %String* %10, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) + br label %continue__1 + +else__1: ; preds = %body__1 + %11 = load %String*, %String** %itemsString, align 8 + %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @27, i32 0, i32 0)) + %13 = call %String* @__quantum__rt__double_to_string(double %item) + %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) + call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) + %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) + store %String* %15, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %16 = add i64 %3, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %17 = load %String*, %String** %itemsString, align 8 + %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @28, i32 0, i32 0)) + %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) + store %String* %19, %String** %itemsString, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) + ret %String* %19 +} + +define i64 @Microsoft__Quantum__Arrays___1575e931e75b478d9338ff1c1ba98161_Count__body(%Callable* %predicate, %Array* %array) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %totalFound = alloca i64, align 8 + store i64 0, i64* %totalFound, align 4 + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %1 = sub i64 %0, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %3 = icmp sle i64 %2, %1 + br i1 %3, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) + %5 = bitcast i8* %4 to double* + %element = load double, double* %5, align 8 + %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64)) + %7 = bitcast %Tuple* %6 to { double }* + %8 = getelementptr inbounds { double }, { double }* %7, i32 0, i32 0 + store double %element, double* %8, align 8 + %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) + call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) + %10 = bitcast %Tuple* %9 to { i1 }* + %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 + %12 = load i1, i1* %11, align 1 + br i1 %12, label %then0__1, label %continue__1 + +then0__1: ; preds = %body__1 + %13 = load i64, i64* %totalFound, align 4 + %14 = add i64 %13, 1 + store i64 %14, i64* %totalFound, align 4 + br label %continue__1 + +continue__1: ; preds = %then0__1, %body__1 + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %15 = add i64 %2, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = load i64, i64* %totalFound, align 4 + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + ret i64 %16 +} + +define void @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { double }* + %1 = getelementptr inbounds { double }, { double }* %0, i32 0, i32 0 + %2 = load double, double* %1, align 8 + %3 = call i1 @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body(double %2) + %4 = bitcast %Tuple* %result-tuple to { i1 }* + %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 + store i1 %3, i1* %5, align 1 + ret void +} + +declare %String* @__quantum__rt__bool_to_string(i1) + +define %String* @Quantum__StandaloneSupportedInputs___f5a60aadd6b1405d8efce41485ff4d80_ArrayToString__body(%Array* %array) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %first = alloca i1, align 1 + store i1 true, i1* %first, align 1 + %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @29, i32 0, i32 0)) + %itemsString = alloca %String*, align 8 + store %String* %0, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) + %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %2 = sub i64 %1, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] + %4 = icmp sle i64 %3, %2 + br i1 %4, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) + %6 = bitcast i8* %5 to i1* + %item = load i1, i1* %6, align 1 + %7 = load i1, i1* %first, align 1 + br i1 %7, label %then0__1, label %else__1 + +then0__1: ; preds = %body__1 + store i1 false, i1* %first, align 1 + %8 = load %String*, %String** %itemsString, align 8 + %9 = call %String* @__quantum__rt__bool_to_string(i1 %item) + %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) + store %String* %10, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) + br label %continue__1 + +else__1: ; preds = %body__1 + %11 = load %String*, %String** %itemsString, align 8 + %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @30, i32 0, i32 0)) + %13 = call %String* @__quantum__rt__bool_to_string(i1 %item) + %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) + call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) + %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) + store %String* %15, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %16 = add i64 %3, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %17 = load %String*, %String** %itemsString, align 8 + %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @31, i32 0, i32 0)) + %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) + store %String* %19, %String** %itemsString, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) + ret %String* %19 +} + +define i64 @Microsoft__Quantum__Arrays___67c459c137a0446995c133a29250678d_Count__body(%Callable* %predicate, %Array* %array) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %totalFound = alloca i64, align 8 + store i64 0, i64* %totalFound, align 4 + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %1 = sub i64 %0, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %3 = icmp sle i64 %2, %1 + br i1 %3, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) + %5 = bitcast i8* %4 to i1* + %element = load i1, i1* %5, align 1 + %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) + %7 = bitcast %Tuple* %6 to { i1 }* + %8 = getelementptr inbounds { i1 }, { i1 }* %7, i32 0, i32 0 + store i1 %element, i1* %8, align 1 + %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) + call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) + %10 = bitcast %Tuple* %9 to { i1 }* + %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 + %12 = load i1, i1* %11, align 1 + br i1 %12, label %then0__1, label %continue__1 + +then0__1: ; preds = %body__1 + %13 = load i64, i64* %totalFound, align 4 + %14 = add i64 %13, 1 + store i64 %14, i64* %totalFound, align 4 + br label %continue__1 + +continue__1: ; preds = %then0__1, %body__1 + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %15 = add i64 %2, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = load i64, i64* %totalFound, align 4 + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + ret i64 %16 +} + +define void @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { i1 }* + %1 = getelementptr inbounds { i1 }, { i1 }* %0, i32 0, i32 0 + %2 = load i1, i1* %1, align 1 + %3 = call i1 @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body(i1 %2) + %4 = bitcast %Tuple* %result-tuple to { i1 }* + %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 + store i1 %3, i1* %5, align 1 + ret void +} + +declare %String* @__quantum__rt__pauli_to_string(i2) + +define %String* @Quantum__StandaloneSupportedInputs___ec0b3349aeaf419f9d7d96decefd1869_ArrayToString__body(%Array* %array) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %first = alloca i1, align 1 + store i1 true, i1* %first, align 1 + %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @32, i32 0, i32 0)) + %itemsString = alloca %String*, align 8 + store %String* %0, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) + %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %2 = sub i64 %1, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] + %4 = icmp sle i64 %3, %2 + br i1 %4, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) + %6 = bitcast i8* %5 to i2* + %item = load i2, i2* %6, align 1 + %7 = load i1, i1* %first, align 1 + br i1 %7, label %then0__1, label %else__1 + +then0__1: ; preds = %body__1 + store i1 false, i1* %first, align 1 + %8 = load %String*, %String** %itemsString, align 8 + %9 = call %String* @__quantum__rt__pauli_to_string(i2 %item) + %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) + store %String* %10, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) + br label %continue__1 + +else__1: ; preds = %body__1 + %11 = load %String*, %String** %itemsString, align 8 + %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @33, i32 0, i32 0)) + %13 = call %String* @__quantum__rt__pauli_to_string(i2 %item) + %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) + call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) + %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) + store %String* %15, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %16 = add i64 %3, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %17 = load %String*, %String** %itemsString, align 8 + %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @34, i32 0, i32 0)) + %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) + store %String* %19, %String** %itemsString, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) + ret %String* %19 +} + +define i64 @Microsoft__Quantum__Arrays___c71932228c1b4b6fb8c3c63c9d8e35e4_Count__body(%Callable* %predicate, %Array* %array) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %totalFound = alloca i64, align 8 + store i64 0, i64* %totalFound, align 4 + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %1 = sub i64 %0, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %3 = icmp sle i64 %2, %1 + br i1 %3, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) + %5 = bitcast i8* %4 to i2* + %element = load i2, i2* %5, align 1 + %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i2* getelementptr (i2, i2* null, i32 1) to i64)) + %7 = bitcast %Tuple* %6 to { i2 }* + %8 = getelementptr inbounds { i2 }, { i2 }* %7, i32 0, i32 0 + store i2 %element, i2* %8, align 1 + %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) + call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) + %10 = bitcast %Tuple* %9 to { i1 }* + %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 + %12 = load i1, i1* %11, align 1 + br i1 %12, label %then0__1, label %continue__1 + +then0__1: ; preds = %body__1 + %13 = load i64, i64* %totalFound, align 4 + %14 = add i64 %13, 1 + store i64 %14, i64* %totalFound, align 4 + br label %continue__1 + +continue__1: ; preds = %then0__1, %body__1 + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %15 = add i64 %2, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = load i64, i64* %totalFound, align 4 + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + ret i64 %16 +} + +define void @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { i2 }* + %1 = getelementptr inbounds { i2 }, { i2 }* %0, i32 0, i32 0 + %2 = load i2, i2* %1, align 1 + %3 = call i1 @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body(i2 %2) + %4 = bitcast %Tuple* %result-tuple to { i1 }* + %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 + store i1 %3, i1* %5, align 1 + ret void +} + +declare %String* @__quantum__rt__range_to_string(%Range) + +declare %String* @__quantum__rt__result_to_string(%Result*) + +define %String* @Quantum__StandaloneSupportedInputs___c22db911562e4518b3ec04b3a395976a_ArrayToString__body(%Array* %array) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %first = alloca i1, align 1 + store i1 true, i1* %first, align 1 + %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @35, i32 0, i32 0)) + %itemsString = alloca %String*, align 8 + store %String* %0, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) + %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %2 = sub i64 %1, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] + %4 = icmp sle i64 %3, %2 + br i1 %4, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) + %6 = bitcast i8* %5 to %Result** + %item = load %Result*, %Result** %6, align 8 + %7 = load i1, i1* %first, align 1 + br i1 %7, label %then0__1, label %else__1 + +then0__1: ; preds = %body__1 + store i1 false, i1* %first, align 1 + %8 = load %String*, %String** %itemsString, align 8 + %9 = call %String* @__quantum__rt__result_to_string(%Result* %item) + %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) + store %String* %10, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) + br label %continue__1 + +else__1: ; preds = %body__1 + %11 = load %String*, %String** %itemsString, align 8 + %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @36, i32 0, i32 0)) + %13 = call %String* @__quantum__rt__result_to_string(%Result* %item) + %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) + call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) + %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) + store %String* %15, %String** %itemsString, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %16 = add i64 %3, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %17 = load %String*, %String** %itemsString, align 8 + %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @37, i32 0, i32 0)) + %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) + store %String* %19, %String** %itemsString, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) + ret %String* %19 +} + +define i64 @Microsoft__Quantum__Arrays___aa464afb2404486a86d7d9b45b4e8d2c_Count__body(%Callable* %predicate, %Array* %array) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) + %totalFound = alloca i64, align 8 + store i64 0, i64* %totalFound, align 4 + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) + %1 = sub i64 %0, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %3 = icmp sle i64 %2, %1 + br i1 %3, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) + %5 = bitcast i8* %4 to %Result** + %element = load %Result*, %Result** %5, align 8 + %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) + %7 = bitcast %Tuple* %6 to { %Result* }* + %8 = getelementptr inbounds { %Result* }, { %Result* }* %7, i32 0, i32 0 + store %Result* %element, %Result** %8, align 8 + %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) + call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) + %10 = bitcast %Tuple* %9 to { i1 }* + %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 + %12 = load i1, i1* %11, align 1 + br i1 %12, label %then0__1, label %continue__1 + +then0__1: ; preds = %body__1 + %13 = load i64, i64* %totalFound, align 4 + %14 = add i64 %13, 1 + store i64 %14, i64* %totalFound, align 4 + br label %continue__1 + +continue__1: ; preds = %then0__1, %body__1 + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %15 = add i64 %2, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = load i64, i64* %totalFound, align 4 + call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) + ret i64 %16 +} + +define void @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Result* }* + %1 = getelementptr inbounds { %Result* }, { %Result* }* %0, i32 0, i32 0 + %2 = load %Result*, %Result** %1, align 8 + %3 = call i1 @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body(%Result* %2) + %4 = bitcast %Tuple* %result-tuple to { i1 }* + %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 + store i1 %3, i1* %5, align 1 + ret void +} + +declare void @__quantum__rt__capture_update_reference_count(%Callable*, i32) + +declare void @__quantum__rt__callable_update_reference_count(%Callable*, i32) + +declare i64 @__quantum__rt__array_get_size_1d(%Array*) + +declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) + +define i1 @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body(i64 %input) { +entry: + ret i1 true +} + +define i1 @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body(double %input) { +entry: + ret i1 true +} + +define i1 @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body(i1 %input) { +entry: + ret i1 true +} + +define i1 @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body(i2 %input) { +entry: + ret i1 true +} + +define i1 @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body(%Result* %input) { +entry: + ret i1 true +} + +declare void @__quantum__rt__capture_update_alias_count(%Callable*, i32) + +declare void @__quantum__rt__callable_update_alias_count(%Callable*, i32) + +declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*) + +declare %Tuple* @__quantum__rt__tuple_create(i64) + +declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i32) + +define void @Quantum__StandaloneSupportedInputs__ExerciseInputs__Interop(i64 %intValue, { i64, i8* }* %intArray, double %doubleValue, { i64, i8* }* %doubleArray, i8 %boolValue, { i64, i8* }* %boolArray, i8 %pauliValue, { i64, i8* }* %pauliArray, { i64, i64, i64 }* %rangeValue, i8 %resultValue, { i64, i8* }* %resultArray, i8* %stringValue) #0 { +entry: + %0 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 0 + %1 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 1 + %2 = load i64, i64* %0, align 4 + %3 = load i8*, i8** %1, align 8 + %4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %2) + %5 = ptrtoint i8* %3 to i64 + %6 = sub i64 %2, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %7 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %8 = icmp sle i64 %7, %6 + br i1 %8, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %9 = mul i64 %7, 8 + %10 = add i64 %5, %9 + %11 = inttoptr i64 %10 to i64* + %12 = load i64, i64* %11, align 4 + %13 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %4, i64 %7) + %14 = bitcast i8* %13 to i64* + store i64 %12, i64* %14, align 4 + br label %exiting__1 + +exiting__1: ; preds = %body__1 + %15 = add i64 %7, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 0 + %17 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 1 + %18 = load i64, i64* %16, align 4 + %19 = load i8*, i8** %17, align 8 + %20 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %18) + %21 = ptrtoint i8* %19 to i64 + %22 = sub i64 %18, 1 + br label %header__2 + +header__2: ; preds = %exiting__2, %exit__1 + %23 = phi i64 [ 0, %exit__1 ], [ %31, %exiting__2 ] + %24 = icmp sle i64 %23, %22 + br i1 %24, label %body__2, label %exit__2 + +body__2: ; preds = %header__2 + %25 = mul i64 %23, 8 + %26 = add i64 %21, %25 + %27 = inttoptr i64 %26 to double* + %28 = load double, double* %27, align 8 + %29 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %20, i64 %23) + %30 = bitcast i8* %29 to double* + store double %28, double* %30, align 8 + br label %exiting__2 + +exiting__2: ; preds = %body__2 + %31 = add i64 %23, 1 + br label %header__2 + +exit__2: ; preds = %header__2 + %32 = trunc i8 %boolValue to i1 + %33 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 0 + %34 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 1 + %35 = load i64, i64* %33, align 4 + %36 = load i8*, i8** %34, align 8 + %37 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %35) + %38 = ptrtoint i8* %36 to i64 + %39 = sub i64 %35, 1 + br label %header__3 + +header__3: ; preds = %exiting__3, %exit__2 + %40 = phi i64 [ 0, %exit__2 ], [ %49, %exiting__3 ] + %41 = icmp sle i64 %40, %39 + br i1 %41, label %body__3, label %exit__3 + +body__3: ; preds = %header__3 + %42 = mul i64 %40, 1 + %43 = add i64 %38, %42 + %44 = inttoptr i64 %43 to i8* + %45 = load i8, i8* %44, align 1 + %46 = trunc i8 %45 to i1 + %47 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %37, i64 %40) + %48 = bitcast i8* %47 to i1* + store i1 %46, i1* %48, align 1 + br label %exiting__3 + +exiting__3: ; preds = %body__3 + %49 = add i64 %40, 1 + br label %header__3 + +exit__3: ; preds = %header__3 + %50 = trunc i8 %pauliValue to i2 + %51 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 0 + %52 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 1 + %53 = load i64, i64* %51, align 4 + %54 = load i8*, i8** %52, align 8 + %55 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %53) + %56 = ptrtoint i8* %54 to i64 + %57 = sub i64 %53, 1 + br label %header__4 + +header__4: ; preds = %exiting__4, %exit__3 + %58 = phi i64 [ 0, %exit__3 ], [ %67, %exiting__4 ] + %59 = icmp sle i64 %58, %57 + br i1 %59, label %body__4, label %exit__4 + +body__4: ; preds = %header__4 + %60 = mul i64 %58, 1 + %61 = add i64 %56, %60 + %62 = inttoptr i64 %61 to i8* + %63 = load i8, i8* %62, align 1 + %64 = trunc i8 %63 to i2 + %65 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %55, i64 %58) + %66 = bitcast i8* %65 to i2* + store i2 %64, i2* %66, align 1 + br label %exiting__4 + +exiting__4: ; preds = %body__4 + %67 = add i64 %58, 1 + br label %header__4 + +exit__4: ; preds = %header__4 + %68 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 0 + %69 = load i64, i64* %68, align 4 + %70 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 1 + %71 = load i64, i64* %70, align 4 + %72 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 2 + %73 = load i64, i64* %72, align 4 + %74 = load %Range, %Range* @EmptyRange, align 4 + %75 = insertvalue %Range %74, i64 %69, 0 + %76 = insertvalue %Range %75, i64 %71, 1 + %77 = insertvalue %Range %76, i64 %73, 2 + %78 = icmp eq i8 %resultValue, 0 + %79 = call %Result* @__quantum__rt__result_get_zero() + %80 = call %Result* @__quantum__rt__result_get_one() + %81 = select i1 %78, %Result* %79, %Result* %80 + %82 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 0 + %83 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 1 + %84 = load i64, i64* %82, align 4 + %85 = load i8*, i8** %83, align 8 + %86 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %84) + %87 = ptrtoint i8* %85 to i64 + %88 = sub i64 %84, 1 + br label %header__5 + +header__5: ; preds = %exiting__5, %exit__4 + %89 = phi i64 [ 0, %exit__4 ], [ %101, %exiting__5 ] + %90 = icmp sle i64 %89, %88 + br i1 %90, label %body__5, label %exit__5 + +body__5: ; preds = %header__5 + %91 = mul i64 %89, 1 + %92 = add i64 %87, %91 + %93 = inttoptr i64 %92 to i8* + %94 = load i8, i8* %93, align 1 + %95 = icmp eq i8 %94, 0 + %96 = call %Result* @__quantum__rt__result_get_zero() + %97 = call %Result* @__quantum__rt__result_get_one() + %98 = select i1 %95, %Result* %96, %Result* %97 + %99 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %89) + %100 = bitcast i8* %99 to %Result** + store %Result* %98, %Result** %100, align 8 + br label %exiting__5 + +exiting__5: ; preds = %body__5 + %101 = add i64 %89, 1 + br label %header__5 + +exit__5: ; preds = %header__5 + %102 = call %String* @__quantum__rt__string_create(i8* %stringValue) + call void @Quantum__StandaloneSupportedInputs__ExerciseInputs__body(i64 %intValue, %Array* %4, double %doubleValue, %Array* %20, i1 %32, %Array* %37, i2 %50, %Array* %55, %Range %77, %Result* %81, %Array* %86, %String* %102) + call void @__quantum__rt__array_update_reference_count(%Array* %4, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %20, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %37, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %55, i32 -1) + %103 = sub i64 %84, 1 + br label %header__6 + +header__6: ; preds = %exiting__6, %exit__5 + %104 = phi i64 [ 0, %exit__5 ], [ %109, %exiting__6 ] + %105 = icmp sle i64 %104, %103 + br i1 %105, label %body__6, label %exit__6 + +body__6: ; preds = %header__6 + %106 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %104) + %107 = bitcast i8* %106 to %Result** + %108 = load %Result*, %Result** %107, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %108, i32 -1) + br label %exiting__6 + +exiting__6: ; preds = %body__6 + %109 = add i64 %104, 1 + br label %header__6 + +exit__6: ; preds = %header__6 + call void @__quantum__rt__array_update_reference_count(%Array* %86, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %102, i32 -1) + ret void +} + +declare %Array* @__quantum__rt__array_create_1d(i32, i64) + +declare %Result* @__quantum__rt__result_get_zero() + +declare %Result* @__quantum__rt__result_get_one() + +declare void @__quantum__rt__array_update_reference_count(%Array*, i32) + +declare void @__quantum__rt__result_update_reference_count(%Result*, i32) + +define void @Quantum__StandaloneSupportedInputs__ExerciseInputs(i64 %intValue, { i64, i8* }* %intArray, double %doubleValue, { i64, i8* }* %doubleArray, i8 %boolValue, { i64, i8* }* %boolArray, i8 %pauliValue, { i64, i8* }* %pauliArray, { i64, i64, i64 }* %rangeValue, i8 %resultValue, { i64, i8* }* %resultArray, i8* %stringValue) #1 { +entry: + %0 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 0 + %1 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 1 + %2 = load i64, i64* %0, align 4 + %3 = load i8*, i8** %1, align 8 + %4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %2) + %5 = ptrtoint i8* %3 to i64 + %6 = sub i64 %2, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %7 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %8 = icmp sle i64 %7, %6 + br i1 %8, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %9 = mul i64 %7, 8 + %10 = add i64 %5, %9 + %11 = inttoptr i64 %10 to i64* + %12 = load i64, i64* %11, align 4 + %13 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %4, i64 %7) + %14 = bitcast i8* %13 to i64* + store i64 %12, i64* %14, align 4 + br label %exiting__1 + +exiting__1: ; preds = %body__1 + %15 = add i64 %7, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 0 + %17 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 1 + %18 = load i64, i64* %16, align 4 + %19 = load i8*, i8** %17, align 8 + %20 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %18) + %21 = ptrtoint i8* %19 to i64 + %22 = sub i64 %18, 1 + br label %header__2 + +header__2: ; preds = %exiting__2, %exit__1 + %23 = phi i64 [ 0, %exit__1 ], [ %31, %exiting__2 ] + %24 = icmp sle i64 %23, %22 + br i1 %24, label %body__2, label %exit__2 + +body__2: ; preds = %header__2 + %25 = mul i64 %23, 8 + %26 = add i64 %21, %25 + %27 = inttoptr i64 %26 to double* + %28 = load double, double* %27, align 8 + %29 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %20, i64 %23) + %30 = bitcast i8* %29 to double* + store double %28, double* %30, align 8 + br label %exiting__2 + +exiting__2: ; preds = %body__2 + %31 = add i64 %23, 1 + br label %header__2 + +exit__2: ; preds = %header__2 + %32 = trunc i8 %boolValue to i1 + %33 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 0 + %34 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 1 + %35 = load i64, i64* %33, align 4 + %36 = load i8*, i8** %34, align 8 + %37 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %35) + %38 = ptrtoint i8* %36 to i64 + %39 = sub i64 %35, 1 + br label %header__3 + +header__3: ; preds = %exiting__3, %exit__2 + %40 = phi i64 [ 0, %exit__2 ], [ %49, %exiting__3 ] + %41 = icmp sle i64 %40, %39 + br i1 %41, label %body__3, label %exit__3 + +body__3: ; preds = %header__3 + %42 = mul i64 %40, 1 + %43 = add i64 %38, %42 + %44 = inttoptr i64 %43 to i8* + %45 = load i8, i8* %44, align 1 + %46 = trunc i8 %45 to i1 + %47 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %37, i64 %40) + %48 = bitcast i8* %47 to i1* + store i1 %46, i1* %48, align 1 + br label %exiting__3 + +exiting__3: ; preds = %body__3 + %49 = add i64 %40, 1 + br label %header__3 + +exit__3: ; preds = %header__3 + %50 = trunc i8 %pauliValue to i2 + %51 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 0 + %52 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 1 + %53 = load i64, i64* %51, align 4 + %54 = load i8*, i8** %52, align 8 + %55 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %53) + %56 = ptrtoint i8* %54 to i64 + %57 = sub i64 %53, 1 + br label %header__4 + +header__4: ; preds = %exiting__4, %exit__3 + %58 = phi i64 [ 0, %exit__3 ], [ %67, %exiting__4 ] + %59 = icmp sle i64 %58, %57 + br i1 %59, label %body__4, label %exit__4 + +body__4: ; preds = %header__4 + %60 = mul i64 %58, 1 + %61 = add i64 %56, %60 + %62 = inttoptr i64 %61 to i8* + %63 = load i8, i8* %62, align 1 + %64 = trunc i8 %63 to i2 + %65 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %55, i64 %58) + %66 = bitcast i8* %65 to i2* + store i2 %64, i2* %66, align 1 + br label %exiting__4 + +exiting__4: ; preds = %body__4 + %67 = add i64 %58, 1 + br label %header__4 + +exit__4: ; preds = %header__4 + %68 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 0 + %69 = load i64, i64* %68, align 4 + %70 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 1 + %71 = load i64, i64* %70, align 4 + %72 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 2 + %73 = load i64, i64* %72, align 4 + %74 = load %Range, %Range* @EmptyRange, align 4 + %75 = insertvalue %Range %74, i64 %69, 0 + %76 = insertvalue %Range %75, i64 %71, 1 + %77 = insertvalue %Range %76, i64 %73, 2 + %78 = icmp eq i8 %resultValue, 0 + %79 = call %Result* @__quantum__rt__result_get_zero() + %80 = call %Result* @__quantum__rt__result_get_one() + %81 = select i1 %78, %Result* %79, %Result* %80 + %82 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 0 + %83 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 1 + %84 = load i64, i64* %82, align 4 + %85 = load i8*, i8** %83, align 8 + %86 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %84) + %87 = ptrtoint i8* %85 to i64 + %88 = sub i64 %84, 1 + br label %header__5 + +header__5: ; preds = %exiting__5, %exit__4 + %89 = phi i64 [ 0, %exit__4 ], [ %101, %exiting__5 ] + %90 = icmp sle i64 %89, %88 + br i1 %90, label %body__5, label %exit__5 + +body__5: ; preds = %header__5 + %91 = mul i64 %89, 1 + %92 = add i64 %87, %91 + %93 = inttoptr i64 %92 to i8* + %94 = load i8, i8* %93, align 1 + %95 = icmp eq i8 %94, 0 + %96 = call %Result* @__quantum__rt__result_get_zero() + %97 = call %Result* @__quantum__rt__result_get_one() + %98 = select i1 %95, %Result* %96, %Result* %97 + %99 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %89) + %100 = bitcast i8* %99 to %Result** + store %Result* %98, %Result** %100, align 8 + br label %exiting__5 + +exiting__5: ; preds = %body__5 + %101 = add i64 %89, 1 + br label %header__5 + +exit__5: ; preds = %header__5 + %102 = call %String* @__quantum__rt__string_create(i8* %stringValue) + call void @Quantum__StandaloneSupportedInputs__ExerciseInputs__body(i64 %intValue, %Array* %4, double %doubleValue, %Array* %20, i1 %32, %Array* %37, i2 %50, %Array* %55, %Range %77, %Result* %81, %Array* %86, %String* %102) + %103 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @38, i32 0, i32 0)) + call void @__quantum__rt__message(%String* %103) + call void @__quantum__rt__array_update_reference_count(%Array* %4, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %20, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %37, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %55, i32 -1) + %104 = sub i64 %84, 1 + br label %header__6 + +header__6: ; preds = %exiting__6, %exit__5 + %105 = phi i64 [ 0, %exit__5 ], [ %110, %exiting__6 ] + %106 = icmp sle i64 %105, %104 + br i1 %106, label %body__6, label %exit__6 + +body__6: ; preds = %header__6 + %107 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %105) + %108 = bitcast i8* %107 to %Result** + %109 = load %Result*, %Result** %108, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %109, i32 -1) + br label %exiting__6 + +exiting__6: ; preds = %body__6 + %110 = add i64 %105, 1 + br label %header__6 + +exit__6: ; preds = %header__6 + call void @__quantum__rt__array_update_reference_count(%Array* %86, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %102, i32 -1) + call void @__quantum__rt__string_update_reference_count(%String* %103, i32 -1) + ret void +} + +attributes #0 = { "InteropFriendly" } +attributes #1 = { "EntryPoint" } diff --git a/src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll b/src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll new file mode 100644 index 00000000000..a86f7f54e43 --- /dev/null +++ b/src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll @@ -0,0 +1,1387 @@ + +%Range = type { i64, i64, i64 } +%Tuple = type opaque +%Callable = type opaque +%Array = type opaque +%Qubit = type opaque +%Result = type opaque +%String = type opaque + +@PauliI = constant i2 0 +@PauliX = constant i2 1 +@PauliY = constant i2 -1 +@PauliZ = constant i2 -2 +@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } +@Microsoft__Quantum__Intrinsic__X = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper] +@Microsoft__Quantum__Intrinsic__Y = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper] +@Microsoft__Quantum__Intrinsic__Z = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper] +@Microsoft__Quantum__Intrinsic__H = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__ctladj__wrapper] +@Microsoft__Quantum__Intrinsic__S = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper] +@Microsoft__Quantum__Intrinsic__T = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__ctladj__wrapper] +@Microsoft__Quantum__Intrinsic__R = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__ctladj__wrapper] +@PartialApplication__1 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__ctladj__wrapper] +@MemoryManagement__1 = constant [2 x void (%Tuple*, i32)*] [void (%Tuple*, i32)* @MemoryManagement__1__RefCount, void (%Tuple*, i32)* @MemoryManagement__1__AliasCount] + +@Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__Interop = alias i64 (), i64 ()* @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__body + +define i64 @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__body() #0 { +entry: + %res = alloca i64, align 8 + store i64 0, i64* %res, align 4 + %0 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__X, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %1 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %0) + store i64 %1, i64* %res, align 4 + %2 = icmp ne i64 %1, 0 + br i1 %2, label %then0__1, label %continue__1 + +then0__1: ; preds = %entry + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + ret i64 %1 + +continue__1: ; preds = %entry + %3 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Y, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %4 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %3) + store i64 %4, i64* %res, align 4 + %5 = icmp ne i64 %4, 0 + br i1 %5, label %then0__2, label %continue__2 + +then0__2: ; preds = %continue__1 + %6 = add i64 10, %4 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + ret i64 %6 + +continue__2: ; preds = %continue__1 + %7 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Z, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %8 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %7) + store i64 %8, i64* %res, align 4 + %9 = icmp ne i64 %8, 0 + br i1 %9, label %then0__3, label %continue__3 + +then0__3: ; preds = %continue__2 + %10 = add i64 20, %8 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) + ret i64 %10 + +continue__3: ; preds = %continue__2 + %11 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__H, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %12 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %11) + store i64 %12, i64* %res, align 4 + %13 = icmp ne i64 %12, 0 + br i1 %13, label %then0__4, label %continue__4 + +then0__4: ; preds = %continue__3 + %14 = add i64 30, %12 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) + ret i64 %14 + +continue__4: ; preds = %continue__3 + %15 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__S, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %16 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %15) + store i64 %16, i64* %res, align 4 + %17 = icmp ne i64 %16, 0 + br i1 %17, label %then0__5, label %continue__5 + +then0__5: ; preds = %continue__4 + %18 = add i64 40, %16 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) + ret i64 %18 + +continue__5: ; preds = %continue__4 + %19 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__T, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %20 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %19) + store i64 %20, i64* %res, align 4 + %21 = icmp ne i64 %20, 0 + br i1 %21, label %then0__6, label %continue__6 + +then0__6: ; preds = %continue__5 + %22 = add i64 50, %20 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) + ret i64 %22 + +continue__6: ; preds = %continue__5 + %23 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Callable*, i2, double }* getelementptr ({ %Callable*, i2, double }, { %Callable*, i2, double }* null, i32 1) to i64)) + %24 = bitcast %Tuple* %23 to { %Callable*, i2, double }* + %25 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %24, i32 0, i32 0 + %26 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %24, i32 0, i32 1 + %27 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %24, i32 0, i32 2 + %28 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__R, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %29 = load i2, i2* @PauliX, align 1 + store %Callable* %28, %Callable** %25, align 8 + store i2 %29, i2* %26, align 1 + store double 4.200000e-01, double* %27, align 8 + %30 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__1, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %23) + %31 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %30) + store i64 %31, i64* %res, align 4 + %32 = icmp ne i64 %31, 0 + br i1 %32, label %then0__7, label %continue__7 + +then0__7: ; preds = %continue__6 + %33 = add i64 60, %31 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %30, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %30, i32 -1) + ret i64 %33 + +continue__7: ; preds = %continue__6 + %targets = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) + %ctls = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %paulis = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) + %34 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %35 = bitcast i8* %34 to i2* + %36 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %37 = bitcast i8* %36 to i2* + %38 = load i2, i2* @PauliX, align 1 + %39 = load i2, i2* @PauliY, align 1 + store i2 %38, i2* %35, align 1 + store i2 %39, i2* %37, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) + call void @__quantum__qis__exp__body(%Array* %paulis, double 4.200000e-01, %Array* %targets) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %paulis, i32 -1) + %paulis__1 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) + %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__1, i64 0) + %41 = bitcast i8* %40 to i2* + %42 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__1, i64 1) + %43 = bitcast i8* %42 to i2* + %44 = load i2, i2* @PauliX, align 1 + %45 = load i2, i2* @PauliY, align 1 + store i2 %44, i2* %41, align 1 + store i2 %45, i2* %43, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis__1, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) + call void @__quantum__qis__exp__adj(%Array* %paulis__1, double 4.200000e-01, %Array* %targets) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis__1, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %paulis__1, i32 -1) + %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %targets, i64 0) + %47 = bitcast i8* %46 to %Qubit** + %48 = load %Qubit*, %Qubit** %47, align 8 + %49 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %48) + %50 = call %Result* @__quantum__rt__result_get_zero() + %51 = call i1 @__quantum__rt__result_equal(%Result* %49, %Result* %50) + %52 = xor i1 %51, true + br i1 %52, label %then0__8, label %continue__8 + +then0__8: ; preds = %continue__7 + store i64 1, i64* %res, align 4 + br label %continue__8 + +continue__8: ; preds = %then0__8, %continue__7 + %53 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %54 = bitcast i8* %53 to %Qubit** + %qubit = load %Qubit*, %Qubit** %54, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit) + %55 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) + %56 = bitcast i8* %55 to %Qubit** + %qubit__1 = load %Qubit*, %Qubit** %56, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %paulis__2 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) + %57 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__2, i64 0) + %58 = bitcast i8* %57 to i2* + %59 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__2, i64 1) + %60 = bitcast i8* %59 to i2* + %61 = load i2, i2* @PauliX, align 1 + %62 = load i2, i2* @PauliY, align 1 + store i2 %61, i2* %58, align 1 + store i2 %62, i2* %60, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis__2, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) + %63 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) + %64 = bitcast %Tuple* %63 to { %Array*, double, %Array* }* + %65 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %64, i32 0, i32 0 + %66 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %64, i32 0, i32 1 + %67 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %64, i32 0, i32 2 + store %Array* %paulis__2, %Array** %65, align 8 + store double 4.200000e-01, double* %66, align 8 + store %Array* %targets, %Array** %67, align 8 + call void @__quantum__qis__exp__ctl(%Array* %ctls, { %Array*, double, %Array* }* %64) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis__2, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %paulis__2, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %63, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %paulis__3 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) + %68 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__3, i64 0) + %69 = bitcast i8* %68 to i2* + %70 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__3, i64 1) + %71 = bitcast i8* %70 to i2* + %72 = load i2, i2* @PauliX, align 1 + %73 = load i2, i2* @PauliY, align 1 + store i2 %72, i2* %69, align 1 + store i2 %73, i2* %71, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis__3, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) + %74 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) + %75 = bitcast %Tuple* %74 to { %Array*, double, %Array* }* + %76 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %75, i32 0, i32 0 + %77 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %75, i32 0, i32 1 + %78 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %75, i32 0, i32 2 + store %Array* %paulis__3, %Array** %76, align 8 + store double 4.200000e-01, double* %77, align 8 + store %Array* %targets, %Array** %78, align 8 + call void @__quantum__qis__exp__ctladj(%Array* %ctls, { %Array*, double, %Array* }* %75) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis__3, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %paulis__3, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %74, i32 -1) + %79 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %80 = bitcast i8* %79 to %Qubit** + %qubit__2 = load %Qubit*, %Qubit** %80, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__2) + %81 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) + %82 = bitcast i8* %81 to %Qubit** + %qubit__3 = load %Qubit*, %Qubit** %82, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__3) + %83 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %targets, i64 0) + %84 = bitcast i8* %83 to %Qubit** + %85 = load %Qubit*, %Qubit** %84, align 8 + %86 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %85) + %87 = call %Result* @__quantum__rt__result_get_zero() + %88 = call i1 @__quantum__rt__result_equal(%Result* %86, %Result* %87) + %89 = xor i1 %88, true + br i1 %89, label %then0__9, label %continue__9 + +then0__9: ; preds = %continue__8 + store i64 2, i64* %res, align 4 + br label %continue__9 + +continue__9: ; preds = %then0__9, %continue__8 + call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %49, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %86, i32 -1) + call void @__quantum__rt__qubit_release_array(%Array* %targets) + call void @__quantum__rt__qubit_release_array(%Array* %ctls) + %90 = load i64, i64* %res, align 4 + %91 = icmp ne i64 %90, 0 + br i1 %91, label %then0__10, label %continue__10 + +then0__10: ; preds = %continue__9 + %92 = add i64 70, %90 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %30, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %30, i32 -1) + ret i64 %92 + +continue__10: ; preds = %continue__9 + %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 3) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) + %93 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %94 = bitcast i8* %93 to %Qubit** + %qubit__4 = load %Qubit*, %Qubit** %94, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__4) + %95 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %96 = bitcast i8* %95 to %Qubit** + %qubit__5 = load %Qubit*, %Qubit** %96, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__5) + %bases = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 3) + %97 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 0) + %98 = bitcast i8* %97 to i2* + %99 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 1) + %100 = bitcast i8* %99 to i2* + %101 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 2) + %102 = bitcast i8* %101 to i2* + %103 = load i2, i2* @PauliX, align 1 + %104 = load i2, i2* @PauliZ, align 1 + %105 = load i2, i2* @PauliX, align 1 + store i2 %103, i2* %98, align 1 + store i2 %104, i2* %100, align 1 + store i2 %105, i2* %102, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) + %106 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qs) + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %bases, i32 -1) + %107 = call %Result* @__quantum__rt__result_get_zero() + %108 = call i1 @__quantum__rt__result_equal(%Result* %106, %Result* %107) + %109 = xor i1 %108, true + br i1 %109, label %then0__11, label %continue__11 + +then0__11: ; preds = %continue__10 + store i64 80, i64* %res, align 4 + br label %continue__11 + +continue__11: ; preds = %then0__11, %continue__10 + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %106, i32 -1) + call void @__quantum__rt__qubit_release_array(%Array* %qs) + %110 = load i64, i64* %res, align 4 + call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %30, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %30, i32 -1) + ret i64 %110 +} + +define i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %op) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 1) + %res = alloca i64, align 8 + store i64 0, i64* %res, align 4 + %target = call %Qubit* @__quantum__rt__qubit_allocate() + %ctls = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) + %1 = bitcast %Tuple* %0 to { %Qubit* }* + %2 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %1, i32 0, i32 0 + store %Qubit* %target, %Qubit** %2, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %op, %Tuple* %0, %Tuple* null) + %3 = call %Callable* @__quantum__rt__callable_copy(%Callable* %op, i1 false) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 1) + call void @__quantum__rt__callable_make_adjoint(%Callable* %3) + %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) + %5 = bitcast %Tuple* %4 to { %Qubit* }* + %6 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %5, i32 0, i32 0 + store %Qubit* %target, %Qubit** %6, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %3, %Tuple* %4, %Tuple* null) + %7 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %target) + %8 = call %Result* @__quantum__rt__result_get_zero() + %9 = call i1 @__quantum__rt__result_equal(%Result* %7, %Result* %8) + %10 = xor i1 %9, true + br i1 %10, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + store i64 1, i64* %res, align 4 + br label %continue__1 + +else__1: ; preds = %entry + %11 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %12 = bitcast i8* %11 to %Qubit** + %qubit = load %Qubit*, %Qubit** %12, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit) + %13 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) + %14 = bitcast i8* %13 to %Qubit** + %qubit__1 = load %Qubit*, %Qubit** %14, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__1) + %15 = call %Callable* @__quantum__rt__callable_copy(%Callable* %op, i1 false) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 1) + call void @__quantum__rt__callable_make_controlled(%Callable* %15) + %16 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) + %17 = bitcast %Tuple* %16 to { %Array*, %Qubit* }* + %18 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %17, i32 0, i32 0 + %19 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %17, i32 0, i32 1 + store %Array* %ctls, %Array** %18, align 8 + store %Qubit* %target, %Qubit** %19, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %15, %Tuple* %16, %Tuple* null) + %20 = call %Callable* @__quantum__rt__callable_copy(%Callable* %op, i1 false) + call void @__quantum__rt__capture_update_reference_count(%Callable* %20, i32 1) + call void @__quantum__rt__callable_make_controlled(%Callable* %20) + call void @__quantum__rt__callable_make_adjoint(%Callable* %20) + %21 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) + %22 = bitcast %Tuple* %21 to { %Array*, %Qubit* }* + %23 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %22, i32 0, i32 0 + %24 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %22, i32 0, i32 1 + store %Array* %ctls, %Array** %23, align 8 + store %Qubit* %target, %Qubit** %24, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %20, %Tuple* %21, %Tuple* null) + %25 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %target) + %26 = call %Result* @__quantum__rt__result_get_zero() + %27 = call i1 @__quantum__rt__result_equal(%Result* %25, %Result* %26) + %28 = xor i1 %27, true + br i1 %28, label %then0__2, label %else__2 + +then0__2: ; preds = %else__1 + store i64 2, i64* %res, align 4 + br label %continue__2 + +else__2: ; preds = %else__1 + %29 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %30 = bitcast i8* %29 to %Qubit** + %qubit__2 = load %Qubit*, %Qubit** %30, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__2) + %31 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) + %32 = bitcast i8* %31 to %Qubit** + %qubit__3 = load %Qubit*, %Qubit** %32, align 8 + call void @__quantum__qis__h__body(%Qubit* %qubit__3) + br label %continue__2 + +continue__2: ; preds = %else__2, %then0__2 + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %16, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %20, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %20, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %21, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %25, i32 -1) + br label %continue__1 + +continue__1: ; preds = %continue__2, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %0, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %7, i32 -1) + call void @__quantum__rt__qubit_release(%Qubit* %target) + call void @__quantum__rt__qubit_release_array(%Array* %ctls) + %33 = load i64, i64* %res, align 4 + call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 -1) + ret i64 %33 +} + +define void @Microsoft__Quantum__Intrinsic__X__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i32)*]*, %Tuple*) + +declare void @__quantum__rt__capture_update_reference_count(%Callable*, i32) + +declare void @__quantum__rt__callable_update_reference_count(%Callable*, i32) + +define void @Microsoft__Quantum__Intrinsic__Y__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__T__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__T__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__T__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__T__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +declare %Tuple* @__quantum__rt__tuple_create(i64) + +define void @Microsoft__Quantum__Intrinsic__R__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { i2, double, %Qubit* }* + %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 + %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 + %4 = load i2, i2* %1, align 1 + %5 = load double, double* %2, align 8 + %6 = load %Qubit*, %Qubit** %3, align 8 + call void @Microsoft__Quantum__Intrinsic__R__body(i2 %4, double %5, %Qubit* %6) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__R__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { i2, double, %Qubit* }* + %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 + %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 + %4 = load i2, i2* %1, align 1 + %5 = load double, double* %2, align 8 + %6 = load %Qubit*, %Qubit** %3, align 8 + call void @Microsoft__Quantum__Intrinsic__R__adj(i2 %4, double %5, %Qubit* %6) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__R__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, { i2, double, %Qubit* }* }* + %1 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load { i2, double, %Qubit* }*, { i2, double, %Qubit* }** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__R__ctl(%Array* %3, { i2, double, %Qubit* }* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__R__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, { i2, double, %Qubit* }* }* + %1 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load { i2, double, %Qubit* }*, { i2, double, %Qubit* }** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__R__ctladj(%Array* %3, { i2, double, %Qubit* }* %4) + ret void +} + +define void @Lifted__PartialApplication__1__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* + %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 1 + %2 = load i2, i2* %1, align 1 + %3 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 2 + %4 = load double, double* %3, align 8 + %5 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %6 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %5, i32 0, i32 0 + %7 = load %Qubit*, %Qubit** %6, align 8 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) + %9 = bitcast %Tuple* %8 to { i2, double, %Qubit* }* + %10 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 2 + store i2 %2, i2* %10, align 1 + store double %4, double* %11, align 8 + store %Qubit* %7, %Qubit** %12, align 8 + %13 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) + ret void +} + +define void @Lifted__PartialApplication__1__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* + %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 1 + %2 = load i2, i2* %1, align 1 + %3 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 2 + %4 = load double, double* %3, align 8 + %5 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %6 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %5, i32 0, i32 0 + %7 = load %Qubit*, %Qubit** %6, align 8 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) + %9 = bitcast %Tuple* %8 to { i2, double, %Qubit* }* + %10 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 2 + store i2 %2, i2* %10, align 1 + store double %4, double* %11, align 8 + store %Qubit* %7, %Qubit** %12, align 8 + %13 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13, align 8 + %15 = call %Callable* @__quantum__rt__callable_copy(%Callable* %14, i1 false) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 1) + call void @__quantum__rt__callable_make_adjoint(%Callable* %15) + call void @__quantum__rt__callable_invoke(%Callable* %15, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) + ret void +} + +define void @Lifted__PartialApplication__1__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + %5 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* + %6 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 1 + %7 = load i2, i2* %6, align 1 + %8 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 2 + %9 = load double, double* %8, align 8 + %10 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) + %11 = bitcast %Tuple* %10 to { i2, double, %Qubit* }* + %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 0 + %13 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 1 + %14 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 2 + store i2 %7, i2* %12, align 1 + store double %9, double* %13, align 8 + store %Qubit* %4, %Qubit** %14, align 8 + %15 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) + %16 = bitcast %Tuple* %15 to { %Array*, { i2, double, %Qubit* }* }* + %17 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 0 + %18 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 1 + store %Array* %3, %Array** %17, align 8 + store { i2, double, %Qubit* }* %11, { i2, double, %Qubit* }** %18, align 8 + %19 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 0 + %20 = load %Callable*, %Callable** %19, align 8 + %21 = call %Callable* @__quantum__rt__callable_copy(%Callable* %20, i1 false) + call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 1) + call void @__quantum__rt__callable_make_controlled(%Callable* %21) + call void @__quantum__rt__callable_invoke(%Callable* %21, %Tuple* %15, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %10, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %15, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %21, i32 -1) + ret void +} + +define void @Lifted__PartialApplication__1__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + %5 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* + %6 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 1 + %7 = load i2, i2* %6, align 1 + %8 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 2 + %9 = load double, double* %8, align 8 + %10 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) + %11 = bitcast %Tuple* %10 to { i2, double, %Qubit* }* + %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 0 + %13 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 1 + %14 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 2 + store i2 %7, i2* %12, align 1 + store double %9, double* %13, align 8 + store %Qubit* %4, %Qubit** %14, align 8 + %15 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) + %16 = bitcast %Tuple* %15 to { %Array*, { i2, double, %Qubit* }* }* + %17 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 0 + %18 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 1 + store %Array* %3, %Array** %17, align 8 + store { i2, double, %Qubit* }* %11, { i2, double, %Qubit* }** %18, align 8 + %19 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 0 + %20 = load %Callable*, %Callable** %19, align 8 + %21 = call %Callable* @__quantum__rt__callable_copy(%Callable* %20, i1 false) + call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 1) + call void @__quantum__rt__callable_make_adjoint(%Callable* %21) + call void @__quantum__rt__callable_make_controlled(%Callable* %21) + call void @__quantum__rt__callable_invoke(%Callable* %21, %Tuple* %15, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %10, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %15, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %21, i32 -1) + ret void +} + +define void @MemoryManagement__1__RefCount(%Tuple* %capture-tuple, i32 %count-change) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* + %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1, align 8 + call void @__quantum__rt__capture_update_reference_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i32 %count-change) + ret void +} + +define void @MemoryManagement__1__AliasCount(%Tuple* %capture-tuple, i32 %count-change) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* + %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1, align 8 + call void @__quantum__rt__capture_update_alias_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i32 %count-change) + ret void +} + +declare %Qubit* @__quantum__rt__qubit_allocate() + +declare %Array* @__quantum__rt__qubit_allocate_array(i64) + +declare void @__quantum__rt__array_update_alias_count(%Array*, i32) + +declare %Array* @__quantum__rt__array_create_1d(i32, i64) + +declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) + +declare void @__quantum__qis__exp__body(%Array*, double, %Array*) + +declare void @__quantum__rt__array_update_reference_count(%Array*, i32) + +declare void @__quantum__qis__exp__adj(%Array*, double, %Array*) + +define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qubit) { +entry: + %bases = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 1) + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 0) + %1 = bitcast i8* %0 to i2* + %2 = load i2, i2* @PauliZ, align 1 + store i2 %2, i2* %1, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) + %qubits = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %3 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) + %4 = bitcast i8* %3 to %Qubit** + store %Qubit* %qubit, %Qubit** %4, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %5 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %bases, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %qubits, i32 -1) + ret %Result* %5 +} + +declare %Result* @__quantum__rt__result_get_zero() + +declare i1 @__quantum__rt__result_equal(%Result*, %Result*) + +declare void @__quantum__qis__h__body(%Qubit*) + +declare void @__quantum__qis__exp__ctl(%Array*, { %Array*, double, %Array* }*) + +declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i32) + +declare void @__quantum__qis__exp__ctladj(%Array*, { %Array*, double, %Array* }*) + +declare void @__quantum__rt__result_update_reference_count(%Result*, i32) + +declare void @__quantum__rt__qubit_release_array(%Array*) + +declare %Result* @__quantum__qis__measure__body(%Array*, %Array*) + +declare void @__quantum__rt__capture_update_alias_count(%Callable*, i32) + +declare void @__quantum__rt__callable_update_alias_count(%Callable*, i32) + +declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*) + +declare %Callable* @__quantum__rt__callable_copy(%Callable*, i1) + +declare void @__quantum__rt__callable_make_adjoint(%Callable*) + +declare void @__quantum__rt__callable_make_controlled(%Callable*) + +declare void @__quantum__rt__qubit_release(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__Exp__body(%Array* %paulis, double %theta, %Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + call void @__quantum__qis__exp__body(%Array* %paulis, double %theta, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Exp__adj(%Array* %paulis, double %theta, %Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + call void @__quantum__qis__exp__adj(%Array* %paulis, double %theta, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Exp__ctl(%Array* %__controlQubits__, { %Array*, double, %Array* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %1 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 0 + %paulis = load %Array*, %Array** %1, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) + %2 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 1 + %theta = load double, double* %2, align 8 + %3 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 2 + %qubits = load %Array*, %Array** %3, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) + %5 = bitcast %Tuple* %4 to { %Array*, double, %Array* }* + %6 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 0 + %7 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 1 + %8 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 2 + store %Array* %paulis, %Array** %6, align 8 + store double %theta, double* %7, align 8 + store %Array* %qubits, %Array** %8, align 8 + call void @__quantum__qis__exp__ctl(%Array* %__controlQubits__, { %Array*, double, %Array* }* %5) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Exp__ctladj(%Array* %__controlQubits__, { %Array*, double, %Array* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %1 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 0 + %paulis = load %Array*, %Array** %1, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) + %2 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 1 + %theta = load double, double* %2, align 8 + %3 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 2 + %qubits = load %Array*, %Array** %3, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) + %5 = bitcast %Tuple* %4 to { %Array*, double, %Array* }* + %6 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 0 + %7 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 1 + %8 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 2 + store %Array* %paulis, %Array** %6, align 8 + store double %theta, double* %7, align 8 + store %Array* %qubits, %Array** %8, align 8 + call void @__quantum__qis__exp__ctladj(%Array* %__controlQubits__, { %Array*, double, %Array* }* %5) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__body(%Qubit* %qubit) { +entry: + call void @__quantum__qis__t__body(%Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__t__body(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__T__adj(%Qubit* %qubit) { +entry: + call void @__quantum__qis__t__adj(%Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__t__adj(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__T__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__t__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__t__ctl(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__T__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__t__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__t__ctladj(%Array*, %Qubit*) + +define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %bases, %Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %0 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret %Result* %0 +} + +define void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %qubit) { +entry: + call void @__quantum__qis__z__body(%Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__z__body(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %qubit) { +entry: + call void @__quantum__qis__z__body(%Qubit* %qubit) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__z__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__z__ctl(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__z__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %qubit) { +entry: + call void @__quantum__qis__x__body(%Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__x__body(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %qubit) { +entry: + call void @__quantum__qis__x__body(%Qubit* %qubit) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__x__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__x__ctl(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__x__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qubit) { +entry: + call void @__quantum__qis__h__body(%Qubit* %qubit) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qubit) { +entry: + call void @__quantum__qis__h__body(%Qubit* %qubit) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__h__ctl(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %qubit) { +entry: + call void @__quantum__qis__s__body(%Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__s__body(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %qubit) { +entry: + call void @__quantum__qis__s__adj(%Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__s__adj(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__s__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__s__ctl(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__s__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__s__ctladj(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__R__body(i2 %pauli, double %theta, %Qubit* %qubit) { +entry: + call void @__quantum__qis__r__body(i2 %pauli, double %theta, %Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__r__body(i2, double, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__R__adj(i2 %pauli, double %theta, %Qubit* %qubit) { +entry: + call void @__quantum__qis__r__adj(i2 %pauli, double %theta, %Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__r__adj(i2, double, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__R__ctl(%Array* %__controlQubits__, { i2, double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 + %pauli = load i2, i2* %1, align 1 + %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 + %theta = load double, double* %2, align 8 + %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 + %qubit = load %Qubit*, %Qubit** %3, align 8 + %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) + %5 = bitcast %Tuple* %4 to { i2, double, %Qubit* }* + %6 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 0 + %7 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 1 + %8 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 2 + store i2 %pauli, i2* %6, align 1 + store double %theta, double* %7, align 8 + store %Qubit* %qubit, %Qubit** %8, align 8 + call void @__quantum__qis__r__ctl(%Array* %__controlQubits__, { i2, double, %Qubit* }* %5) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) + ret void +} + +declare void @__quantum__qis__r__ctl(%Array*, { i2, double, %Qubit* }*) + +define void @Microsoft__Quantum__Intrinsic__R__ctladj(%Array* %__controlQubits__, { i2, double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 + %pauli = load i2, i2* %1, align 1 + %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 + %theta = load double, double* %2, align 8 + %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 + %qubit = load %Qubit*, %Qubit** %3, align 8 + %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) + %5 = bitcast %Tuple* %4 to { i2, double, %Qubit* }* + %6 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 0 + %7 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 1 + %8 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 2 + store i2 %pauli, i2* %6, align 1 + store double %theta, double* %7, align 8 + store %Qubit* %qubit, %Qubit** %8, align 8 + call void @__quantum__qis__r__ctladj(%Array* %__controlQubits__, { i2, double, %Qubit* }* %5) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) + ret void +} + +declare void @__quantum__qis__r__ctladj(%Array*, { i2, double, %Qubit* }*) + +define void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %qubit) { +entry: + call void @__quantum__qis__y__body(%Qubit* %qubit) + ret void +} + +declare void @__quantum__qis__y__body(%Qubit*) + +define void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %qubit) { +entry: + call void @__quantum__qis__y__body(%Qubit* %qubit) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__y__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__y__ctl(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__y__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS() #1 { +entry: + %0 = call i64 @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__body() + %1 = call %String* @__quantum__rt__int_to_string(i64 %0) + call void @__quantum__rt__message(%String* %1) + call void @__quantum__rt__string_update_reference_count(%String* %1, i32 -1) + ret void +} + +declare void @__quantum__rt__message(%String*) + +declare %String* @__quantum__rt__int_to_string(i64) + +declare void @__quantum__rt__string_update_reference_count(%String*, i32) + +declare void @__quantum__rt__tuple_update_alias_count(%Tuple*, i32) + +attributes #0 = { "InteropFriendly" } +attributes #1 = { "EntryPoint" } diff --git a/src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll b/src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll new file mode 100644 index 00000000000..227d27613fc --- /dev/null +++ b/src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll @@ -0,0 +1,159 @@ + +%Range = type { i64, i64, i64 } +%Qubit = type opaque +%Result = type opaque +%Array = type opaque +%String = type opaque + +@PauliI = constant i2 0 +@PauliX = constant i2 1 +@PauliY = constant i2 -1 +@PauliZ = constant i2 -2 +@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } + +@Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__Interop = alias i64 (), i64 ()* @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__body + +define i64 @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__body() #0 { +entry: + %randomNumber = alloca i64, align 8 + store i64 0, i64* %randomNumber, align 4 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %i = phi i64 [ 1, %entry ], [ %8, %exiting__1 ] + %0 = icmp sle i64 %i, 64 + br i1 %0, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %q = call %Qubit* @__quantum__rt__qubit_allocate() + call void @__quantum__qis__h__body(%Qubit* %q) + %1 = load i64, i64* %randomNumber, align 4 + %2 = shl i64 %1, 1 + store i64 %2, i64* %randomNumber, align 4 + %3 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %q) + %4 = call %Result* @__quantum__rt__result_get_one() + %5 = call i1 @__quantum__rt__result_equal(%Result* %3, %Result* %4) + br i1 %5, label %then0__1, label %continue__1 + +then0__1: ; preds = %body__1 + %6 = load i64, i64* %randomNumber, align 4 + %7 = add i64 %6, 1 + store i64 %7, i64* %randomNumber, align 4 + br label %continue__1 + +continue__1: ; preds = %then0__1, %body__1 + call void @__quantum__rt__result_update_reference_count(%Result* %3, i32 -1) + call void @__quantum__rt__qubit_release(%Qubit* %q) + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %8 = add i64 %i, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %9 = load i64, i64* %randomNumber, align 4 + ret i64 %9 +} + +declare %Qubit* @__quantum__rt__qubit_allocate() + +declare %Array* @__quantum__rt__qubit_allocate_array(i64) + +declare void @__quantum__qis__h__body(%Qubit*) + +define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qubit) { +entry: + %bases = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 1) + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 0) + %1 = bitcast i8* %0 to i2* + %2 = load i2, i2* @PauliZ, align 1 + store i2 %2, i2* %1, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) + %qubits = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %3 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) + %4 = bitcast i8* %3 to %Qubit** + store %Qubit* %qubit, %Qubit** %4, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %5 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %bases, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %qubits, i32 -1) + ret %Result* %5 +} + +declare %Result* @__quantum__rt__result_get_one() + +declare i1 @__quantum__rt__result_equal(%Result*, %Result*) + +declare void @__quantum__rt__result_update_reference_count(%Result*, i32) + +declare void @__quantum__rt__qubit_release(%Qubit*) + +declare %Array* @__quantum__rt__array_create_1d(i32, i64) + +declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) + +declare void @__quantum__rt__array_update_alias_count(%Array*, i32) + +declare %Result* @__quantum__qis__measure__body(%Array*, %Array*) + +declare void @__quantum__rt__array_update_reference_count(%Array*, i32) + +define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %bases, %Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %0 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret %Result* %0 +} + +define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qubit) { +entry: + call void @__quantum__qis__h__body(%Qubit* %qubit) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qubit) { +entry: + call void @__quantum__qis__h__body(%Qubit* %qubit) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +declare void @__quantum__qis__h__ctl(%Array*, %Qubit*) + +define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator() #1 { +entry: + %0 = call i64 @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__body() + %1 = call %String* @__quantum__rt__int_to_string(i64 %0) + call void @__quantum__rt__message(%String* %1) + call void @__quantum__rt__string_update_reference_count(%String* %1, i32 -1) + ret void +} + +declare void @__quantum__rt__message(%String*) + +declare %String* @__quantum__rt__int_to_string(i64) + +declare void @__quantum__rt__string_update_reference_count(%String*, i32) + +attributes #0 = { "InteropFriendly" } +attributes #1 = { "EntryPoint" } diff --git a/src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll b/src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll new file mode 100644 index 00000000000..31a343b650f --- /dev/null +++ b/src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll @@ -0,0 +1,2080 @@ + +%Range = type { i64, i64, i64 } +%Tuple = type opaque +%Result = type opaque +%Qubit = type opaque +%Array = type opaque +%Callable = type opaque +%String = type opaque + +@PauliI = constant i2 0 +@PauliX = constant i2 1 +@PauliY = constant i2 -1 +@PauliZ = constant i2 -2 +@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } +@Microsoft__Quantum__Testing__Tracer__Delay = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Testing__Tracer__Delay__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@Microsoft__Quantum__Intrinsic__X = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper] +@PartialApplication__1 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@MemoryManagement__1 = constant [2 x void (%Tuple*, i32)*] [void (%Tuple*, i32)* @MemoryManagement__1__RefCount, void (%Tuple*, i32)* @MemoryManagement__1__AliasCount] +@Microsoft__Quantum__Intrinsic__Y = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper] +@PartialApplication__2 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__2__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@Microsoft__Quantum__Intrinsic__Z = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper] +@PartialApplication__3 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__3__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@Microsoft__Quantum__Intrinsic__S = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper] +@PartialApplication__4 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__4__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] +@MemoryManagement__2 = constant [2 x void (%Tuple*, i32)*] [void (%Tuple*, i32)* @MemoryManagement__2__RefCount, void (%Tuple*, i32)* @MemoryManagement__2__AliasCount] + +define %Result* @Microsoft__Quantum__Instructions__Mx__body(%Qubit* %qb) { +entry: + %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb) + ret %Result* %0 +} + +declare %Result* @__quantum__qis__single_qubit_measure(i64, i64, %Qubit*) + +define %Result* @Microsoft__Quantum__Instructions__Mxx__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret %Result* %0 +} + +declare void @__quantum__rt__array_update_alias_count(%Array*, i32) + +declare %Result* @__quantum__qis__joint_measure(i64, i64, %Array*) + +define %Result* @Microsoft__Quantum__Instructions__Mxz__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mz__body(%Qubit* %qb) { +entry: + %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mzx__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Instructions__Mzz__body(%Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %0 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret %Result* %0 +} + +define void @Microsoft__Quantum__Instructions__Sx__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) + ret void +} + +declare void @__quantum__qis__single_qubit_op(i64, i64, %Qubit*) + +define void @Microsoft__Quantum__Instructions__Sx__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sx__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +declare void @__quantum__qis__single_qubit_op_ctl(i64, i64, %Array*, %Qubit*) + +define void @Microsoft__Quantum__Instructions__Sx__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Sz__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tx__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Instructions__Tz__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__ApplyConditionallyIntrinsic__body(%Array* %measurementResults, %Array* %resultsValues, %Callable* %onEqualOp, %Callable* %onNonEqualOp) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %measurementResults, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %resultsValues, i32 1) + call void @__quantum__rt__capture_update_alias_count(%Callable* %onEqualOp, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onEqualOp, i32 1) + call void @__quantum__rt__capture_update_alias_count(%Callable* %onNonEqualOp, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onNonEqualOp, i32 1) + call void @__quantum__qis__apply_conditionally(%Array* %measurementResults, %Array* %resultsValues, %Callable* %onEqualOp, %Callable* %onNonEqualOp) + call void @__quantum__rt__array_update_alias_count(%Array* %measurementResults, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %resultsValues, i32 -1) + call void @__quantum__rt__capture_update_alias_count(%Callable* %onEqualOp, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onEqualOp, i32 -1) + call void @__quantum__rt__capture_update_alias_count(%Callable* %onNonEqualOp, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onNonEqualOp, i32 -1) + ret void +} + +declare void @__quantum__rt__capture_update_alias_count(%Callable*, i32) + +declare void @__quantum__rt__callable_update_alias_count(%Callable*, i32) + +declare void @__quantum__qis__apply_conditionally(%Array*, %Array*, %Callable*, %Callable*) + +define void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %measurementResult, %Callable* %onResultZeroOp, %Callable* %onResultOneOp) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultZeroOp, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultZeroOp, i32 1) + call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultOneOp, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultOneOp, i32 1) + %0 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %1 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 0) + %2 = bitcast i8* %1 to %Result** + store %Result* %measurementResult, %Result** %2, align 8 + %3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 0) + %5 = bitcast i8* %4 to %Result** + %6 = call %Result* @__quantum__rt__result_get_zero() + store %Result* %6, %Result** %5, align 8 + call void @__quantum__qis__apply_conditionally(%Array* %0, %Array* %3, %Callable* %onResultZeroOp, %Callable* %onResultOneOp) + call void @__quantum__rt__result_update_reference_count(%Result* %measurementResult, i32 1) + call void @__quantum__rt__result_update_reference_count(%Result* %6, i32 1) + call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultZeroOp, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultZeroOp, i32 -1) + call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultOneOp, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultOneOp, i32 -1) + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %7 = phi i64 [ 0, %entry ], [ %12, %exiting__1 ] + %8 = icmp sle i64 %7, 0 + br i1 %8, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 %7) + %10 = bitcast i8* %9 to %Result** + %11 = load %Result*, %Result** %10, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %11, i32 -1) + br label %exiting__1 + +exiting__1: ; preds = %body__1 + %12 = add i64 %7, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + call void @__quantum__rt__array_update_reference_count(%Array* %0, i32 -1) + br label %header__2 + +header__2: ; preds = %exiting__2, %exit__1 + %13 = phi i64 [ 0, %exit__1 ], [ %18, %exiting__2 ] + %14 = icmp sle i64 %13, 0 + br i1 %14, label %body__2, label %exit__2 + +body__2: ; preds = %header__2 + %15 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 %13) + %16 = bitcast i8* %15 to %Result** + %17 = load %Result*, %Result** %16, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %17, i32 -1) + br label %exiting__2 + +exiting__2: ; preds = %body__2 + %18 = add i64 %13, 1 + br label %header__2 + +exit__2: ; preds = %header__2 + call void @__quantum__rt__array_update_reference_count(%Array* %3, i32 -1) + ret void +} + +declare %Array* @__quantum__rt__array_create_1d(i32, i64) + +declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) + +declare %Result* @__quantum__rt__result_get_zero() + +declare void @__quantum__rt__result_update_reference_count(%Result*, i32) + +declare void @__quantum__rt__array_update_reference_count(%Array*, i32) + +define void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) { +entry: + %ctls = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %1 = bitcast i8* %0 to %Qubit** + store %Qubit* %control, %Qubit** %1, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + br i1 true, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %target) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %target) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %control, %Qubit* %target) { +entry: + call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %ctls, { %Qubit*, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 + %control = load %Qubit*, %Qubit** %1, align 8 + %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 + %target = load %Qubit*, %Qubit** %2, align 8 + %3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 0) + %5 = bitcast i8* %4 to %Qubit** + store %Qubit* %control, %Qubit** %5, align 8 + %ctls__1 = call %Array* @__quantum__rt__array_concatenate(%Array* %ctls, %Array* %3) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 1) + %6 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls__1) + %7 = icmp eq i64 %6, 1 + br i1 %7, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls__1, %Qubit* %target) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls__1, %Qubit* %target) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %3, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__1, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +declare %Array* @__quantum__rt__array_concatenate(%Array*, %Array*) + +declare i64 @__quantum__rt__array_get_size_1d(%Array*) + +define void @Microsoft__Quantum__Intrinsic__CNOT__ctladj(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 + %control = load %Qubit*, %Qubit** %1, align 8 + %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 + %target = load %Qubit*, %Qubit** %2, align 8 + %3 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) + %4 = bitcast %Tuple* %3 to { %Qubit*, %Qubit* }* + %5 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %4, i32 0, i32 0 + %6 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %4, i32 0, i32 1 + store %Qubit* %control, %Qubit** %5, align 8 + store %Qubit* %target, %Qubit** %6, align 8 + call void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %4) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %3, i32 -1) + ret void +} + +declare %Tuple* @__quantum__rt__tuple_create(i64) + +declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i32) + +define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qb) { +entry: + %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) + ret %Result* %0 +} + +define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %paulis, %Array* %qubits) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %0 = call %Result* @__quantum__rt__result_get_one() + %res = alloca %Result*, align 8 + store %Result* %0, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %0, i32 1) + %haveY = alloca i1, align 1 + store i1 false, i1* %haveY, align 1 + %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %paulis) + %2 = sub i64 %1, 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %i = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] + %3 = icmp sle i64 %i, %2 + br i1 %3, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %5 = bitcast i8* %4 to i2* + %6 = load i2, i2* %5, align 1 + %7 = load i2, i2* @PauliY, align 1 + %8 = icmp eq i2 %6, %7 + br i1 %8, label %condContinue__1, label %condFalse__1 + +condFalse__1: ; preds = %body__1 + %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %10 = bitcast i8* %9 to i2* + %11 = load i2, i2* %10, align 1 + %12 = load i2, i2* @PauliI, align 1 + %13 = icmp eq i2 %11, %12 + br label %condContinue__1 + +condContinue__1: ; preds = %condFalse__1, %body__1 + %14 = phi i1 [ %8, %body__1 ], [ %13, %condFalse__1 ] + br i1 %14, label %then0__1, label %continue__1 + +then0__1: ; preds = %condContinue__1 + store i1 true, i1* %haveY, align 1 + br label %continue__1 + +continue__1: ; preds = %then0__1, %condContinue__1 + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %15 = add i64 %i, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %16 = load i1, i1* %haveY, align 1 + br i1 %16, label %then0__2, label %test1__1 + +then0__2: ; preds = %exit__1 + %17 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qubits) + call void @__quantum__rt__result_update_reference_count(%Result* %17, i32 1) + store %Result* %17, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %17, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %0, i32 -1) + br label %continue__2 + +test1__1: ; preds = %exit__1 + %18 = icmp sgt i64 %1, 2 + br i1 %18, label %then1__1, label %test2__1 + +then1__1: ; preds = %test1__1 + %19 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qubits) + call void @__quantum__rt__result_update_reference_count(%Result* %19, i32 1) + %20 = load %Result*, %Result** %res, align 8 + store %Result* %19, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %19, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %20, i32 -1) + br label %continue__2 + +test2__1: ; preds = %test1__1 + %21 = icmp eq i64 %1, 1 + br i1 %21, label %then2__1, label %test3__1 + +then2__1: ; preds = %test2__1 + %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %23 = bitcast i8* %22 to i2* + %24 = load i2, i2* %23, align 1 + %25 = load i2, i2* @PauliX, align 1 + %26 = icmp eq i2 %24, %25 + br i1 %26, label %then0__3, label %else__1 + +then0__3: ; preds = %then2__1 + %27 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) + %28 = bitcast i8* %27 to %Qubit** + %qb = load %Qubit*, %Qubit** %28, align 8 + %29 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb) + call void @__quantum__rt__result_update_reference_count(%Result* %29, i32 1) + %30 = load %Result*, %Result** %res, align 8 + store %Result* %29, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %29, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %30, i32 -1) + br label %continue__3 + +else__1: ; preds = %then2__1 + %31 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) + %32 = bitcast i8* %31 to %Qubit** + %qb__1 = load %Qubit*, %Qubit** %32, align 8 + %33 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__1) + call void @__quantum__rt__result_update_reference_count(%Result* %33, i32 1) + %34 = load %Result*, %Result** %res, align 8 + store %Result* %33, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %33, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %34, i32 -1) + br label %continue__3 + +continue__3: ; preds = %else__1, %then0__3 + br label %continue__2 + +test3__1: ; preds = %test2__1 + %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %36 = bitcast i8* %35 to i2* + %37 = load i2, i2* %36, align 1 + %38 = load i2, i2* @PauliX, align 1 + %39 = icmp eq i2 %37, %38 + br i1 %39, label %condTrue__1, label %condContinue__2 + +condTrue__1: ; preds = %test3__1 + %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %41 = bitcast i8* %40 to i2* + %42 = load i2, i2* %41, align 1 + %43 = load i2, i2* @PauliX, align 1 + %44 = icmp eq i2 %42, %43 + br label %condContinue__2 + +condContinue__2: ; preds = %condTrue__1, %test3__1 + %45 = phi i1 [ %44, %condTrue__1 ], [ %39, %test3__1 ] + br i1 %45, label %then3__1, label %test4__1 + +then3__1: ; preds = %condContinue__2 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %46 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %46, i32 1) + %47 = load %Result*, %Result** %res, align 8 + store %Result* %46, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %46, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %47, i32 -1) + br label %continue__2 + +test4__1: ; preds = %condContinue__2 + %48 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %49 = bitcast i8* %48 to i2* + %50 = load i2, i2* %49, align 1 + %51 = load i2, i2* @PauliX, align 1 + %52 = icmp eq i2 %50, %51 + br i1 %52, label %condTrue__2, label %condContinue__3 + +condTrue__2: ; preds = %test4__1 + %53 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %54 = bitcast i8* %53 to i2* + %55 = load i2, i2* %54, align 1 + %56 = load i2, i2* @PauliZ, align 1 + %57 = icmp eq i2 %55, %56 + br label %condContinue__3 + +condContinue__3: ; preds = %condTrue__2, %test4__1 + %58 = phi i1 [ %57, %condTrue__2 ], [ %52, %test4__1 ] + br i1 %58, label %then4__1, label %test5__1 + +then4__1: ; preds = %condContinue__3 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %59 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %59, i32 1) + %60 = load %Result*, %Result** %res, align 8 + store %Result* %59, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %59, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %60, i32 -1) + br label %continue__2 + +test5__1: ; preds = %condContinue__3 + %61 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %62 = bitcast i8* %61 to i2* + %63 = load i2, i2* %62, align 1 + %64 = load i2, i2* @PauliZ, align 1 + %65 = icmp eq i2 %63, %64 + br i1 %65, label %condTrue__3, label %condContinue__4 + +condTrue__3: ; preds = %test5__1 + %66 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %67 = bitcast i8* %66 to i2* + %68 = load i2, i2* %67, align 1 + %69 = load i2, i2* @PauliX, align 1 + %70 = icmp eq i2 %68, %69 + br label %condContinue__4 + +condContinue__4: ; preds = %condTrue__3, %test5__1 + %71 = phi i1 [ %70, %condTrue__3 ], [ %65, %test5__1 ] + br i1 %71, label %then5__1, label %test6__1 + +then5__1: ; preds = %condContinue__4 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %72 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %72, i32 1) + %73 = load %Result*, %Result** %res, align 8 + store %Result* %72, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %72, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %73, i32 -1) + br label %continue__2 + +test6__1: ; preds = %condContinue__4 + %74 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %75 = bitcast i8* %74 to i2* + %76 = load i2, i2* %75, align 1 + %77 = load i2, i2* @PauliZ, align 1 + %78 = icmp eq i2 %76, %77 + br i1 %78, label %condTrue__4, label %condContinue__5 + +condTrue__4: ; preds = %test6__1 + %79 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %80 = bitcast i8* %79 to i2* + %81 = load i2, i2* %80, align 1 + %82 = load i2, i2* @PauliZ, align 1 + %83 = icmp eq i2 %81, %82 + br label %condContinue__5 + +condContinue__5: ; preds = %condTrue__4, %test6__1 + %84 = phi i1 [ %83, %condTrue__4 ], [ %78, %test6__1 ] + br i1 %84, label %then6__1, label %continue__2 + +then6__1: ; preds = %condContinue__5 + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) + %85 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qubits) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %85, i32 1) + %86 = load %Result*, %Result** %res, align 8 + store %Result* %85, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %85, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %86, i32 -1) + br label %continue__2 + +continue__2: ; preds = %then6__1, %condContinue__5, %then5__1, %then4__1, %then3__1, %continue__3, %then1__1, %then0__2 + %87 = load %Result*, %Result** %res, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) + ret %Result* %87 +} + +declare %Result* @__quantum__rt__result_get_one() + +define void @Microsoft__Quantum__Intrinsic__Rx__body(double %theta, %Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Rx__adj(double %theta, %Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Rx__ctl(%Array* %ctls, { double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 + %theta = load double, double* %1, align 8 + %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 + %qb = load %Qubit*, %Qubit** %2, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Rx__ctladj(%Array* %ctls, { double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 + %theta = load double, double* %1, align 8 + %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 + %qb = load %Qubit*, %Qubit** %2, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Ry__body(double %theta, %Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Ry__adj(double %theta, %Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Ry__ctl(%Array* %ctls, { double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 + %theta = load double, double* %1, align 8 + %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 + %qb = load %Qubit*, %Qubit** %2, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Ry__ctladj(%Array* %ctls, { double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 + %theta = load double, double* %1, align 8 + %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 + %qb = load %Qubit*, %Qubit** %2, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Rz__body(double %theta, %Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Rz__adj(double %theta, %Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Rz__ctl(%Array* %ctls, { double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 + %theta = load double, double* %1, align 8 + %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 + %qb = load %Qubit*, %Qubit** %2, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Rz__ctladj(%Array* %ctls, { double, %Qubit* }* %0) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 + %theta = load double, double* %1, align 8 + %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 + %qb = load %Qubit*, %Qubit** %2, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__T__ctladj(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %qb) { +entry: + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %ctls, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { +entry: + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) + %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) + %1 = icmp eq i64 %0, 1 + br i1 %1, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %__controlQubits__, %Qubit* %qb) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) + ret void +} + +define %Tuple* @Microsoft__Quantum__Core__Attribute__body() { +entry: + ret %Tuple* null +} + +define %Tuple* @Microsoft__Quantum__Core__EntryPoint__body() { +entry: + ret %Tuple* null +} + +define %Tuple* @Microsoft__Quantum__Core__Inline__body() { +entry: + ret %Tuple* null +} + +define void @Microsoft__Quantum__Testing__Tracer__Delay__body(%Callable* %op, %Qubit* %arg, %Tuple* %aux) { +entry: + call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 1) + %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) + %1 = bitcast %Tuple* %0 to { %Qubit* }* + %2 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %1, i32 0, i32 0 + store %Qubit* %arg, %Qubit** %2, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %op, %Tuple* %0, %Tuple* null) + call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 -1) + call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 -1) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %0, i32 -1) + ret void +} + +declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*) + +define void @Microsoft__Quantum__Testing__Tracer__TestCoreIntrinsics__body() { +entry: + %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 3) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %1 = bitcast i8* %0 to %Qubit** + %qb = load %Qubit*, %Qubit** %1, align 8 + call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) + %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %3 = bitcast i8* %2 to %Qubit** + %qb__1 = load %Qubit*, %Qubit** %3, align 8 + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__1) + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %5 = bitcast i8* %4 to %Qubit** + %qb__2 = load %Qubit*, %Qubit** %5, align 8 + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__2) + %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %7 = bitcast i8* %6 to %Qubit** + %qb__3 = load %Qubit*, %Qubit** %7, align 8 + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__3) + %8 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %9 = bitcast i8* %8 to %Qubit** + %10 = load %Qubit*, %Qubit** %9, align 8 + %11 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %12 = bitcast i8* %11 to %Qubit** + %13 = load %Qubit*, %Qubit** %12, align 8 + call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %10, %Qubit* %13) + %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %15 = bitcast i8* %14 to %Qubit** + %qb__4 = load %Qubit*, %Qubit** %15, align 8 + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__4) + %16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %17 = bitcast i8* %16 to %Qubit** + %qb__5 = load %Qubit*, %Qubit** %17, align 8 + call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__5) + %18 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %19 = bitcast i8* %18 to %Qubit** + %qb__6 = load %Qubit*, %Qubit** %19, align 8 + call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb__6) + %20 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %21 = bitcast i8* %20 to %Qubit** + %qb__7 = load %Qubit*, %Qubit** %21, align 8 + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__7) + %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %23 = bitcast i8* %22 to %Qubit** + %qb__9 = load %Qubit*, %Qubit** %23, align 8 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__9) + call void @__quantum__qis__inject_barrier(i64 42, i64 0) + %24 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %25 = bitcast i8* %24 to %Qubit** + %qb__11 = load %Qubit*, %Qubit** %25, align 8 + call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb__11) + %26 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %27 = bitcast i8* %26 to %Qubit** + %qb__13 = load %Qubit*, %Qubit** %27, align 8 + call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__13) + %28 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %29 = bitcast i8* %28 to %Qubit** + %qb__15 = load %Qubit*, %Qubit** %29, align 8 + call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__15) + %30 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %31 = bitcast i8* %30 to %Qubit** + %qb__17 = load %Qubit*, %Qubit** %31, align 8 + call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__17) + %32 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %33 = bitcast i8* %32 to %Qubit** + %34 = load %Qubit*, %Qubit** %33, align 8 + %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %36 = bitcast i8* %35 to %Qubit** + %37 = load %Qubit*, %Qubit** %36, align 8 + call void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %34, %Qubit* %37) + %38 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %39 = bitcast i8* %38 to %Qubit** + %qb__19 = load %Qubit*, %Qubit** %39, align 8 + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__19) + %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %41 = bitcast i8* %40 to %Qubit** + %qb__20 = load %Qubit*, %Qubit** %41, align 8 + call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__20) + %42 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %43 = bitcast i8* %42 to %Qubit** + %qb__21 = load %Qubit*, %Qubit** %43, align 8 + call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb__21) + %44 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %45 = bitcast i8* %44 to %Qubit** + %qb__22 = load %Qubit*, %Qubit** %45, align 8 + call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__22) + %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %47 = bitcast i8* %46 to %Qubit** + %qb__24 = load %Qubit*, %Qubit** %47, align 8 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__24) + %c = call %Qubit* @__quantum__rt__qubit_allocate() + %ctls = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %48 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) + %49 = bitcast i8* %48 to %Qubit** + store %Qubit* %c, %Qubit** %49, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) + %50 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %51 = bitcast i8* %50 to %Qubit** + %qb__26 = load %Qubit*, %Qubit** %51, align 8 + br i1 true, label %then0__1, label %else__1 + +then0__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %qb__26) + br label %continue__1 + +else__1: ; preds = %entry + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %qb__26) + br label %continue__1 + +continue__1: ; preds = %else__1, %then0__1 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls, i32 -1) + %ctls__1 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %52 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__1, i64 0) + %53 = bitcast i8* %52 to %Qubit** + store %Qubit* %c, %Qubit** %53, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 1) + %54 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %55 = bitcast i8* %54 to %Qubit** + %qb__27 = load %Qubit*, %Qubit** %55, align 8 + br i1 true, label %then0__2, label %else__2 + +then0__2: ; preds = %continue__1 + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls__1, %Qubit* %qb__27) + br label %continue__2 + +else__2: ; preds = %continue__1 + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls__1, %Qubit* %qb__27) + br label %continue__2 + +continue__2: ; preds = %else__2, %then0__2 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__1, i32 -1) + %ctls__2 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %56 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__2, i64 0) + %57 = bitcast i8* %56 to %Qubit** + store %Qubit* %c, %Qubit** %57, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i32 1) + %58 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %59 = bitcast i8* %58 to %Qubit** + %qb__28 = load %Qubit*, %Qubit** %59, align 8 + br i1 true, label %then0__3, label %else__3 + +then0__3: ; preds = %continue__2 + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls__2, %Qubit* %qb__28) + br label %continue__3 + +else__3: ; preds = %continue__2 + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls__2, %Qubit* %qb__28) + br label %continue__3 + +continue__3: ; preds = %else__3, %then0__3 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__2, i32 -1) + %ctls__3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %60 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__3, i64 0) + %61 = bitcast i8* %60 to %Qubit** + store %Qubit* %c, %Qubit** %61, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i32 1) + %62 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %63 = bitcast i8* %62 to %Qubit** + %qb__29 = load %Qubit*, %Qubit** %63, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls__3, %Qubit* %qb__29) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__3, i32 -1) + %ctls__4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %64 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__4, i64 0) + %65 = bitcast i8* %64 to %Qubit** + store %Qubit* %c, %Qubit** %65, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i32 1) + %66 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %67 = bitcast i8* %66 to %Qubit** + %qb__30 = load %Qubit*, %Qubit** %67, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls__4, %Qubit* %qb__30) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__4, i32 -1) + %ctls__5 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %68 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__5, i64 0) + %69 = bitcast i8* %68 to %Qubit** + store %Qubit* %c, %Qubit** %69, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i32 1) + %70 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %71 = bitcast i8* %70 to %Qubit** + %qb__31 = load %Qubit*, %Qubit** %71, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls__5, %Qubit* %qb__31) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__5, i32 -1) + %ctls__6 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %72 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__6, i64 0) + %73 = bitcast i8* %72 to %Qubit** + store %Qubit* %c, %Qubit** %73, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i32 1) + %74 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %75 = bitcast i8* %74 to %Qubit** + %qb__32 = load %Qubit*, %Qubit** %75, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls__6, %Qubit* %qb__32) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__6, i32 -1) + %ctls__7 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %76 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__7, i64 0) + %77 = bitcast i8* %76 to %Qubit** + store %Qubit* %c, %Qubit** %77, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 1) + %78 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %79 = bitcast i8* %78 to %Qubit** + %qb__33 = load %Qubit*, %Qubit** %79, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls__7, %Qubit* %qb__33) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__7, i32 -1) + %ctls__9 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) + %80 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__9, i64 0) + %81 = bitcast i8* %80 to %Qubit** + store %Qubit* %c, %Qubit** %81, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 1) + %82 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %83 = bitcast i8* %82 to %Qubit** + %qb__35 = load %Qubit*, %Qubit** %83, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls__9, %Qubit* %qb__35) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %ctls__9, i32 -1) + call void @__quantum__rt__qubit_release(%Qubit* %c) + %cc = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %84 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %85 = bitcast i8* %84 to %Qubit** + %qb__37 = load %Qubit*, %Qubit** %85, align 8 + %86 = call i64 @__quantum__rt__array_get_size_1d(%Array* %cc) + %87 = icmp eq i64 %86, 1 + br i1 %87, label %then0__4, label %else__4 + +then0__4: ; preds = %continue__3 + call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %cc, %Qubit* %qb__37) + br label %continue__4 + +else__4: ; preds = %continue__3 + call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %cc, %Qubit* %qb__37) + br label %continue__4 + +continue__4: ; preds = %else__4, %then0__4 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %88 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %89 = bitcast i8* %88 to %Qubit** + %qb__38 = load %Qubit*, %Qubit** %89, align 8 + %90 = icmp eq i64 %86, 1 + br i1 %90, label %then0__5, label %else__5 + +then0__5: ; preds = %continue__4 + call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %cc, %Qubit* %qb__38) + br label %continue__5 + +else__5: ; preds = %continue__4 + call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %cc, %Qubit* %qb__38) + br label %continue__5 + +continue__5: ; preds = %else__5, %then0__5 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %91 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %92 = bitcast i8* %91 to %Qubit** + %qb__39 = load %Qubit*, %Qubit** %92, align 8 + %93 = icmp eq i64 %86, 1 + br i1 %93, label %then0__6, label %else__6 + +then0__6: ; preds = %continue__5 + call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %cc, %Qubit* %qb__39) + br label %continue__6 + +else__6: ; preds = %continue__5 + call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %cc, %Qubit* %qb__39) + br label %continue__6 + +continue__6: ; preds = %else__6, %then0__6 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %94 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %95 = bitcast i8* %94 to %Qubit** + %qb__40 = load %Qubit*, %Qubit** %95, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %cc, %Qubit* %qb__40) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %96 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %97 = bitcast i8* %96 to %Qubit** + %qb__41 = load %Qubit*, %Qubit** %97, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %cc, %Qubit* %qb__41) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %98 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %99 = bitcast i8* %98 to %Qubit** + %qb__42 = load %Qubit*, %Qubit** %99, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %cc, %Qubit* %qb__42) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %100 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %101 = bitcast i8* %100 to %Qubit** + %qb__43 = load %Qubit*, %Qubit** %101, align 8 + call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %cc, %Qubit* %qb__43) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %102 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %103 = bitcast i8* %102 to %Qubit** + %qb__44 = load %Qubit*, %Qubit** %103, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %cc, %Qubit* %qb__44) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + %104 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %105 = bitcast i8* %104 to %Qubit** + %qb__46 = load %Qubit*, %Qubit** %105, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) + call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %cc, %Qubit* %qb__46) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) + call void @__quantum__rt__qubit_release_array(%Array* %cc) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) + call void @__quantum__rt__qubit_release_array(%Array* %qs) + ret void +} + +declare %Qubit* @__quantum__rt__qubit_allocate() + +declare %Array* @__quantum__rt__qubit_allocate_array(i64) + +declare void @__quantum__qis__inject_barrier(i64, i64) + +declare void @__quantum__rt__qubit_release(%Qubit*) + +declare void @__quantum__rt__qubit_release_array(%Array*) + +define void @Microsoft__Quantum__Testing__Tracer__TestMeasurements__body() { +entry: + %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 6) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) + %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %1 = bitcast i8* %0 to %Qubit** + %qb = load %Qubit*, %Qubit** %1, align 8 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) + %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) + %3 = bitcast i8* %2 to %Qubit** + %qb__2 = load %Qubit*, %Qubit** %3, align 8 + %r0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__2) + %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %5 = bitcast i8* %4 to %Qubit** + %qb__4 = load %Qubit*, %Qubit** %5, align 8 + call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__4) + %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %7 = bitcast i8* %6 to %Qubit** + %8 = load %Qubit*, %Qubit** %7, align 8 + %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %10 = bitcast i8* %9 to %Qubit** + %11 = load %Qubit*, %Qubit** %10, align 8 + call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %8, %Qubit* %11) + %qs12 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 2) + %12 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) + %13 = bitcast i8* %12 to %Qubit** + %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 1) + %15 = bitcast i8* %14 to %Qubit** + %16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) + %17 = bitcast i8* %16 to %Qubit** + %18 = load %Qubit*, %Qubit** %17, align 8 + %19 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) + %20 = bitcast i8* %19 to %Qubit** + %21 = load %Qubit*, %Qubit** %20, align 8 + store %Qubit* %18, %Qubit** %13, align 8 + store %Qubit* %21, %Qubit** %15, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) + %paulis = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) + %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %23 = bitcast i8* %22 to i2* + %24 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %25 = bitcast i8* %24 to i2* + %26 = load i2, i2* @PauliY, align 1 + %27 = load i2, i2* @PauliX, align 1 + store i2 %26, i2* %23, align 1 + store i2 %27, i2* %25, align 1 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) + %28 = call %Result* @__quantum__rt__result_get_one() + %res = alloca %Result*, align 8 + store %Result* %28, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %28, i32 1) + %haveY = alloca i1, align 1 + store i1 false, i1* %haveY, align 1 + br label %header__1 + +header__1: ; preds = %exiting__1, %entry + %i = phi i64 [ 0, %entry ], [ %41, %exiting__1 ] + %29 = icmp sle i64 %i, 1 + br i1 %29, label %body__1, label %exit__1 + +body__1: ; preds = %header__1 + %30 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %31 = bitcast i8* %30 to i2* + %32 = load i2, i2* %31, align 1 + %33 = load i2, i2* @PauliY, align 1 + %34 = icmp eq i2 %32, %33 + br i1 %34, label %condContinue__1, label %condFalse__1 + +condFalse__1: ; preds = %body__1 + %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) + %36 = bitcast i8* %35 to i2* + %37 = load i2, i2* %36, align 1 + %38 = load i2, i2* @PauliI, align 1 + %39 = icmp eq i2 %37, %38 + br label %condContinue__1 + +condContinue__1: ; preds = %condFalse__1, %body__1 + %40 = phi i1 [ %34, %body__1 ], [ %39, %condFalse__1 ] + br i1 %40, label %then0__1, label %continue__1 + +then0__1: ; preds = %condContinue__1 + store i1 true, i1* %haveY, align 1 + br label %continue__1 + +continue__1: ; preds = %then0__1, %condContinue__1 + br label %exiting__1 + +exiting__1: ; preds = %continue__1 + %41 = add i64 %i, 1 + br label %header__1 + +exit__1: ; preds = %header__1 + %42 = load i1, i1* %haveY, align 1 + br i1 %42, label %then0__2, label %test1__1 + +then0__2: ; preds = %exit__1 + %43 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qs12) + call void @__quantum__rt__result_update_reference_count(%Result* %43, i32 1) + store %Result* %43, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %43, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %28, i32 -1) + br label %continue__2 + +test1__1: ; preds = %exit__1 + br i1 false, label %then1__1, label %test2__1 + +then1__1: ; preds = %test1__1 + %44 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qs12) + call void @__quantum__rt__result_update_reference_count(%Result* %44, i32 1) + %45 = load %Result*, %Result** %res, align 8 + store %Result* %44, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %44, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %45, i32 -1) + br label %continue__2 + +test2__1: ; preds = %test1__1 + br i1 false, label %then2__1, label %test3__1 + +then2__1: ; preds = %test2__1 + %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %47 = bitcast i8* %46 to i2* + %48 = load i2, i2* %47, align 1 + %49 = load i2, i2* @PauliX, align 1 + %50 = icmp eq i2 %48, %49 + br i1 %50, label %then0__3, label %else__1 + +then0__3: ; preds = %then2__1 + %51 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) + %52 = bitcast i8* %51 to %Qubit** + %qb__6 = load %Qubit*, %Qubit** %52, align 8 + %53 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb__6) + call void @__quantum__rt__result_update_reference_count(%Result* %53, i32 1) + %54 = load %Result*, %Result** %res, align 8 + store %Result* %53, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %53, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %54, i32 -1) + br label %continue__3 + +else__1: ; preds = %then2__1 + %55 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) + %56 = bitcast i8* %55 to %Qubit** + %qb__7 = load %Qubit*, %Qubit** %56, align 8 + %57 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__7) + call void @__quantum__rt__result_update_reference_count(%Result* %57, i32 1) + %58 = load %Result*, %Result** %res, align 8 + store %Result* %57, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %57, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %58, i32 -1) + br label %continue__3 + +continue__3: ; preds = %else__1, %then0__3 + br label %continue__2 + +test3__1: ; preds = %test2__1 + %59 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %60 = bitcast i8* %59 to i2* + %61 = load i2, i2* %60, align 1 + %62 = load i2, i2* @PauliX, align 1 + %63 = icmp eq i2 %61, %62 + br i1 %63, label %condTrue__1, label %condContinue__2 + +condTrue__1: ; preds = %test3__1 + %64 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %65 = bitcast i8* %64 to i2* + %66 = load i2, i2* %65, align 1 + %67 = load i2, i2* @PauliX, align 1 + %68 = icmp eq i2 %66, %67 + br label %condContinue__2 + +condContinue__2: ; preds = %condTrue__1, %test3__1 + %69 = phi i1 [ %68, %condTrue__1 ], [ %63, %test3__1 ] + br i1 %69, label %then3__1, label %test4__1 + +then3__1: ; preds = %condContinue__2 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) + %70 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %70, i32 1) + %71 = load %Result*, %Result** %res, align 8 + store %Result* %70, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %70, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %71, i32 -1) + br label %continue__2 + +test4__1: ; preds = %condContinue__2 + %72 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %73 = bitcast i8* %72 to i2* + %74 = load i2, i2* %73, align 1 + %75 = load i2, i2* @PauliX, align 1 + %76 = icmp eq i2 %74, %75 + br i1 %76, label %condTrue__2, label %condContinue__3 + +condTrue__2: ; preds = %test4__1 + %77 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %78 = bitcast i8* %77 to i2* + %79 = load i2, i2* %78, align 1 + %80 = load i2, i2* @PauliZ, align 1 + %81 = icmp eq i2 %79, %80 + br label %condContinue__3 + +condContinue__3: ; preds = %condTrue__2, %test4__1 + %82 = phi i1 [ %81, %condTrue__2 ], [ %76, %test4__1 ] + br i1 %82, label %then4__1, label %test5__1 + +then4__1: ; preds = %condContinue__3 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) + %83 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %83, i32 1) + %84 = load %Result*, %Result** %res, align 8 + store %Result* %83, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %83, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %84, i32 -1) + br label %continue__2 + +test5__1: ; preds = %condContinue__3 + %85 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %86 = bitcast i8* %85 to i2* + %87 = load i2, i2* %86, align 1 + %88 = load i2, i2* @PauliZ, align 1 + %89 = icmp eq i2 %87, %88 + br i1 %89, label %condTrue__3, label %condContinue__4 + +condTrue__3: ; preds = %test5__1 + %90 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %91 = bitcast i8* %90 to i2* + %92 = load i2, i2* %91, align 1 + %93 = load i2, i2* @PauliX, align 1 + %94 = icmp eq i2 %92, %93 + br label %condContinue__4 + +condContinue__4: ; preds = %condTrue__3, %test5__1 + %95 = phi i1 [ %94, %condTrue__3 ], [ %89, %test5__1 ] + br i1 %95, label %then5__1, label %test6__1 + +then5__1: ; preds = %condContinue__4 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) + %96 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %96, i32 1) + %97 = load %Result*, %Result** %res, align 8 + store %Result* %96, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %96, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %97, i32 -1) + br label %continue__2 + +test6__1: ; preds = %condContinue__4 + %98 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) + %99 = bitcast i8* %98 to i2* + %100 = load i2, i2* %99, align 1 + %101 = load i2, i2* @PauliZ, align 1 + %102 = icmp eq i2 %100, %101 + br i1 %102, label %condTrue__4, label %condContinue__5 + +condTrue__4: ; preds = %test6__1 + %103 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) + %104 = bitcast i8* %103 to i2* + %105 = load i2, i2* %104, align 1 + %106 = load i2, i2* @PauliZ, align 1 + %107 = icmp eq i2 %105, %106 + br label %condContinue__5 + +condContinue__5: ; preds = %condTrue__4, %test6__1 + %108 = phi i1 [ %107, %condTrue__4 ], [ %102, %test6__1 ] + br i1 %108, label %then6__1, label %continue__2 + +then6__1: ; preds = %condContinue__5 + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) + %109 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qs12) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %109, i32 1) + %110 = load %Result*, %Result** %res, align 8 + store %Result* %109, %Result** %res, align 8 + call void @__quantum__rt__result_update_reference_count(%Result* %109, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %110, i32 -1) + br label %continue__2 + +continue__2: ; preds = %then6__1, %condContinue__5, %then5__1, %then4__1, %then3__1, %continue__3, %then1__1, %then0__2 + %r12 = load %Result*, %Result** %res, align 8 + call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %paulis, i32 -1) + %111 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %112 = bitcast %Tuple* %111 to { %Callable*, %Callable*, %Qubit* }* + %113 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 0 + %114 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 1 + %115 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 2 + %116 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %117 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__X, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %118 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 3) + %119 = bitcast i8* %118 to %Qubit** + %120 = load %Qubit*, %Qubit** %119, align 8 + store %Callable* %116, %Callable** %113, align 8 + store %Callable* %117, %Callable** %114, align 8 + store %Qubit* %120, %Qubit** %115, align 8 + %121 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__1, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %111) + %122 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %123 = bitcast %Tuple* %122 to { %Callable*, %Callable*, %Qubit* }* + %124 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 0 + %125 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 1 + %126 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 2 + %127 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %128 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Y, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %129 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 3) + %130 = bitcast i8* %129 to %Qubit** + %131 = load %Qubit*, %Qubit** %130, align 8 + store %Callable* %127, %Callable** %124, align 8 + store %Callable* %128, %Callable** %125, align 8 + store %Qubit* %131, %Qubit** %126, align 8 + %132 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__2, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %122) + call void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %r0, %Callable* %121, %Callable* %132) + %133 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %134 = bitcast %Tuple* %133 to { %Callable*, %Callable*, %Qubit* }* + %135 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 0 + %136 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 1 + %137 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 2 + %138 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %139 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Z, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %140 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 4) + %141 = bitcast i8* %140 to %Qubit** + %142 = load %Qubit*, %Qubit** %141, align 8 + store %Callable* %138, %Callable** %135, align 8 + store %Callable* %139, %Callable** %136, align 8 + store %Qubit* %142, %Qubit** %137, align 8 + %143 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__3, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %133) + %144 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %145 = bitcast %Tuple* %144 to { %Callable*, %Callable*, %Qubit* }* + %146 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 0 + %147 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 1 + %148 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 2 + %149 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %150 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__S, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) + %151 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 4) + %152 = bitcast i8* %151 to %Qubit** + %153 = load %Qubit*, %Qubit** %152, align 8 + store %Callable* %149, %Callable** %146, align 8 + store %Callable* %150, %Callable** %147, align 8 + store %Qubit* %153, %Qubit** %148, align 8 + %154 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__4, [2 x void (%Tuple*, i32)*]* @MemoryManagement__2, %Tuple* %144) + call void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %r12, %Callable* %143, %Callable* %154) + %155 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 5) + %156 = bitcast i8* %155 to %Qubit** + %qb__8 = load %Qubit*, %Qubit** %156, align 8 + call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__8) + call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) + call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %r0, i32 -1) + call void @__quantum__rt__array_update_reference_count(%Array* %qs12, i32 -1) + call void @__quantum__rt__result_update_reference_count(%Result* %r12, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %121, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %121, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %132, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %132, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %143, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %143, i32 -1) + call void @__quantum__rt__capture_update_reference_count(%Callable* %154, i32 -1) + call void @__quantum__rt__callable_update_reference_count(%Callable* %154, i32 -1) + call void @__quantum__rt__qubit_release_array(%Array* %qs) + ret void +} + +define void @Microsoft__Quantum__Testing__Tracer__Delay__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Callable*, %Qubit*, %Tuple* }* + %1 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 1 + %3 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 2 + %4 = load %Callable*, %Callable** %1, align 8 + %5 = load %Qubit*, %Qubit** %2, align 8 + %6 = load %Tuple*, %Tuple** %3, align 8 + call void @Microsoft__Quantum__Testing__Tracer__Delay__body(%Callable* %4, %Qubit* %5, %Tuple* %6) + ret void +} + +declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i32)*]*, %Tuple*) + +define void @Microsoft__Quantum__Intrinsic__X__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Lifted__PartialApplication__1__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1, align 8 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3, align 8 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6, align 8 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10, align 8 + store %Qubit* %4, %Qubit** %11, align 8 + store %Tuple* %7, %Tuple** %12, align 8 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) + ret void +} + +define void @MemoryManagement__1__RefCount(%Tuple* %capture-tuple, i32 %count-change) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1, align 8 + call void @__quantum__rt__capture_update_reference_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i32 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3, align 8 + call void @__quantum__rt__capture_update_reference_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i32 %count-change) + ret void +} + +define void @MemoryManagement__1__AliasCount(%Tuple* %capture-tuple, i32 %count-change) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1, align 8 + call void @__quantum__rt__capture_update_alias_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i32 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3, align 8 + call void @__quantum__rt__capture_update_alias_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i32 %count-change) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Lifted__PartialApplication__2__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1, align 8 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3, align 8 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6, align 8 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10, align 8 + store %Qubit* %4, %Qubit** %11, align 8 + store %Tuple* %7, %Tuple** %12, align 8 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Lifted__PartialApplication__3__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1, align 8 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3, align 8 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6, align 8 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10, align 8 + store %Qubit* %4, %Qubit** %11, align 8 + store %Tuple* %7, %Tuple** %12, align 8 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* + %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 + %2 = load %Qubit*, %Qubit** %1, align 8 + call void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %2) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %3, %Qubit* %4) + ret void +} + +define void @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* + %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 + %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 + %3 = load %Array*, %Array** %1, align 8 + %4 = load %Qubit*, %Qubit** %2, align 8 + call void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %3, %Qubit* %4) + ret void +} + +define void @Lifted__PartialApplication__4__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %2 = load %Callable*, %Callable** %1, align 8 + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 + %4 = load %Qubit*, %Qubit** %3, align 8 + %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* + %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 + %7 = load %Tuple*, %Tuple** %6, align 8 + %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) + %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* + %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 + %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 + %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 + store %Callable* %2, %Callable** %10, align 8 + store %Qubit* %4, %Qubit** %11, align 8 + store %Tuple* %7, %Tuple** %12, align 8 + %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %14 = load %Callable*, %Callable** %13, align 8 + call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) + ret void +} + +define void @MemoryManagement__2__RefCount(%Tuple* %capture-tuple, i32 %count-change) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1, align 8 + call void @__quantum__rt__capture_update_reference_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i32 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3, align 8 + call void @__quantum__rt__capture_update_reference_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__callable_update_reference_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i32 %count-change) + ret void +} + +define void @MemoryManagement__2__AliasCount(%Tuple* %capture-tuple, i32 %count-change) { +entry: + %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* + %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 + %2 = load %Callable*, %Callable** %1, align 8 + call void @__quantum__rt__capture_update_alias_count(%Callable* %2, i32 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i32 %count-change) + %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 + %4 = load %Callable*, %Callable** %3, align 8 + call void @__quantum__rt__capture_update_alias_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__callable_update_alias_count(%Callable* %4, i32 %count-change) + call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i32 %count-change) + ret void +} + +declare void @__quantum__rt__capture_update_reference_count(%Callable*, i32) + +declare void @__quantum__rt__callable_update_reference_count(%Callable*, i32) + +define { %String* }* @Microsoft__Quantum__Targeting__TargetInstruction__body(%String* %__Item1__) { +entry: + %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) + %1 = bitcast %Tuple* %0 to { %String* }* + %2 = getelementptr inbounds { %String* }, { %String* }* %1, i32 0, i32 0 + store %String* %__Item1__, %String** %2, align 8 + call void @__quantum__rt__string_update_reference_count(%String* %__Item1__, i32 1) + ret { %String* }* %1 +} + +declare void @__quantum__rt__string_update_reference_count(%String*, i32) + +declare void @__quantum__rt__tuple_update_alias_count(%Tuple*, i32) From ddf30c8ddf3cbec17544081d0ae1fde1318f8e38 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Wed, 7 Apr 2021 16:14:12 -0700 Subject: [PATCH 005/145] Remove generated qir --- .../qir/qir-standalone-input-reference.ll | 1427 ----------- .../qsharp/qir/qir-test-simulator.ll | 1387 ----------- .../QIR-dynamic/qsharp/qir/qir-test-random.ll | 159 -- .../test/QIR-tracer/qsharp/qir/tracer-qir.ll | 2080 ----------------- 4 files changed, 5053 deletions(-) delete mode 100644 src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll delete mode 100644 src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll delete mode 100644 src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll delete mode 100644 src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll diff --git a/src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll b/src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll deleted file mode 100644 index 3b75c0034f7..00000000000 --- a/src/QirRuntime/samples/StandaloneInputReference/qsharp/qir/qir-standalone-input-reference.ll +++ /dev/null @@ -1,1427 +0,0 @@ - -%Range = type { i64, i64, i64 } -%Tuple = type opaque -%Result = type opaque -%Array = type opaque -%String = type opaque -%Callable = type opaque - -@PauliI = constant i2 0 -@PauliX = constant i2 1 -@PauliY = constant i2 -1 -@PauliZ = constant i2 -2 -@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } -@0 = internal constant [36 x i8] c"Exercise Supported Inputs Reference\00" -@1 = internal constant [11 x i8] c"intValue: \00" -@Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@2 = internal constant [11 x i8] c"intArray: \00" -@3 = internal constant [3 x i8] c" (\00" -@4 = internal constant [2 x i8] c")\00" -@5 = internal constant [14 x i8] c"doubleValue: \00" -@Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@6 = internal constant [14 x i8] c"doubleArray: \00" -@7 = internal constant [3 x i8] c" (\00" -@8 = internal constant [2 x i8] c")\00" -@9 = internal constant [12 x i8] c"boolValue: \00" -@Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@10 = internal constant [12 x i8] c"boolArray: \00" -@11 = internal constant [3 x i8] c" (\00" -@12 = internal constant [2 x i8] c")\00" -@13 = internal constant [13 x i8] c"pauliValue: \00" -@Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@14 = internal constant [13 x i8] c"pauliArray: \00" -@15 = internal constant [3 x i8] c" (\00" -@16 = internal constant [2 x i8] c")\00" -@17 = internal constant [13 x i8] c"rangeValue: \00" -@18 = internal constant [14 x i8] c"resultValue: \00" -@Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@19 = internal constant [14 x i8] c"resultArray: \00" -@20 = internal constant [3 x i8] c" (\00" -@21 = internal constant [2 x i8] c")\00" -@22 = internal constant [14 x i8] c"stringValue: \00" -@23 = internal constant [2 x i8] c"[\00" -@24 = internal constant [3 x i8] c", \00" -@25 = internal constant [2 x i8] c"]\00" -@26 = internal constant [2 x i8] c"[\00" -@27 = internal constant [3 x i8] c", \00" -@28 = internal constant [2 x i8] c"]\00" -@29 = internal constant [2 x i8] c"[\00" -@30 = internal constant [3 x i8] c", \00" -@31 = internal constant [2 x i8] c"]\00" -@32 = internal constant [2 x i8] c"[\00" -@33 = internal constant [3 x i8] c", \00" -@34 = internal constant [2 x i8] c"]\00" -@35 = internal constant [2 x i8] c"[\00" -@36 = internal constant [3 x i8] c", \00" -@37 = internal constant [2 x i8] c"]\00" -@38 = internal constant [3 x i8] c"()\00" - -define void @Quantum__StandaloneSupportedInputs__ExerciseInputs__body(i64 %intValue, %Array* %intArray, double %doubleValue, %Array* %doubleArray, i1 %boolValue, %Array* %boolArray, i2 %pauliValue, %Array* %pauliArray, %Range %rangeValue, %Result* %resultValue, %Array* %resultArray, %String* %stringValue) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %intArray, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %doubleArray, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %boolArray, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %pauliArray, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %resultArray, i32 1) - %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @0, i32 0, i32 0)) - call void @__quantum__rt__message(%String* %0) - %1 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @1, i32 0, i32 0)) - %2 = call %String* @__quantum__rt__int_to_string(i64 %intValue) - %3 = call %String* @__quantum__rt__string_concatenate(%String* %1, %String* %2) - call void @__quantum__rt__string_update_reference_count(%String* %1, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %2, i32 -1) - call void @__quantum__rt__message(%String* %3) - %4 = call %String* @Quantum__StandaloneSupportedInputs___58b06fb8838645aba850713a715678d6_ArrayToString__body(%Array* %intArray) - %5 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %6 = call i64 @Microsoft__Quantum__Arrays___8487a9df7d0d4ac5a6694fb1d077b2b4_Count__body(%Callable* %5, %Array* %intArray) - %7 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @2, i32 0, i32 0)) - call void @__quantum__rt__string_update_reference_count(%String* %4, i32 1) - %8 = call %String* @__quantum__rt__string_concatenate(%String* %7, %String* %4) - call void @__quantum__rt__string_update_reference_count(%String* %7, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %4, i32 -1) - %9 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @3, i32 0, i32 0)) - %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) - call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) - %11 = call %String* @__quantum__rt__int_to_string(i64 %6) - %12 = call %String* @__quantum__rt__string_concatenate(%String* %10, %String* %11) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) - %13 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @4, i32 0, i32 0)) - %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) - call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) - call void @__quantum__rt__message(%String* %14) - %15 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @5, i32 0, i32 0)) - %16 = call %String* @__quantum__rt__double_to_string(double %doubleValue) - %17 = call %String* @__quantum__rt__string_concatenate(%String* %15, %String* %16) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %16, i32 -1) - call void @__quantum__rt__message(%String* %17) - %18 = call %String* @Quantum__StandaloneSupportedInputs___651cdf0b91af440a8c52eefc05d57b06_ArrayToString__body(%Array* %doubleArray) - %19 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %20 = call i64 @Microsoft__Quantum__Arrays___1575e931e75b478d9338ff1c1ba98161_Count__body(%Callable* %19, %Array* %doubleArray) - %21 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @6, i32 0, i32 0)) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 1) - %22 = call %String* @__quantum__rt__string_concatenate(%String* %21, %String* %18) - call void @__quantum__rt__string_update_reference_count(%String* %21, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) - %23 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @7, i32 0, i32 0)) - %24 = call %String* @__quantum__rt__string_concatenate(%String* %22, %String* %23) - call void @__quantum__rt__string_update_reference_count(%String* %22, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %23, i32 -1) - %25 = call %String* @__quantum__rt__int_to_string(i64 %20) - %26 = call %String* @__quantum__rt__string_concatenate(%String* %24, %String* %25) - call void @__quantum__rt__string_update_reference_count(%String* %24, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %25, i32 -1) - %27 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @8, i32 0, i32 0)) - %28 = call %String* @__quantum__rt__string_concatenate(%String* %26, %String* %27) - call void @__quantum__rt__string_update_reference_count(%String* %26, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %27, i32 -1) - call void @__quantum__rt__message(%String* %28) - %29 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @9, i32 0, i32 0)) - %30 = call %String* @__quantum__rt__bool_to_string(i1 %boolValue) - %31 = call %String* @__quantum__rt__string_concatenate(%String* %29, %String* %30) - call void @__quantum__rt__string_update_reference_count(%String* %29, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %30, i32 -1) - call void @__quantum__rt__message(%String* %31) - %32 = call %String* @Quantum__StandaloneSupportedInputs___f5a60aadd6b1405d8efce41485ff4d80_ArrayToString__body(%Array* %boolArray) - %33 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %34 = call i64 @Microsoft__Quantum__Arrays___67c459c137a0446995c133a29250678d_Count__body(%Callable* %33, %Array* %boolArray) - %35 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @10, i32 0, i32 0)) - call void @__quantum__rt__string_update_reference_count(%String* %32, i32 1) - %36 = call %String* @__quantum__rt__string_concatenate(%String* %35, %String* %32) - call void @__quantum__rt__string_update_reference_count(%String* %35, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %32, i32 -1) - %37 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @11, i32 0, i32 0)) - %38 = call %String* @__quantum__rt__string_concatenate(%String* %36, %String* %37) - call void @__quantum__rt__string_update_reference_count(%String* %36, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %37, i32 -1) - %39 = call %String* @__quantum__rt__int_to_string(i64 %34) - %40 = call %String* @__quantum__rt__string_concatenate(%String* %38, %String* %39) - call void @__quantum__rt__string_update_reference_count(%String* %38, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %39, i32 -1) - %41 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @12, i32 0, i32 0)) - %42 = call %String* @__quantum__rt__string_concatenate(%String* %40, %String* %41) - call void @__quantum__rt__string_update_reference_count(%String* %40, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %41, i32 -1) - call void @__quantum__rt__message(%String* %42) - %43 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @13, i32 0, i32 0)) - %44 = call %String* @__quantum__rt__pauli_to_string(i2 %pauliValue) - %45 = call %String* @__quantum__rt__string_concatenate(%String* %43, %String* %44) - call void @__quantum__rt__string_update_reference_count(%String* %43, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %44, i32 -1) - call void @__quantum__rt__message(%String* %45) - %46 = call %String* @Quantum__StandaloneSupportedInputs___ec0b3349aeaf419f9d7d96decefd1869_ArrayToString__body(%Array* %pauliArray) - %47 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %48 = call i64 @Microsoft__Quantum__Arrays___c71932228c1b4b6fb8c3c63c9d8e35e4_Count__body(%Callable* %47, %Array* %pauliArray) - %49 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @14, i32 0, i32 0)) - call void @__quantum__rt__string_update_reference_count(%String* %46, i32 1) - %50 = call %String* @__quantum__rt__string_concatenate(%String* %49, %String* %46) - call void @__quantum__rt__string_update_reference_count(%String* %49, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %46, i32 -1) - %51 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @15, i32 0, i32 0)) - %52 = call %String* @__quantum__rt__string_concatenate(%String* %50, %String* %51) - call void @__quantum__rt__string_update_reference_count(%String* %50, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %51, i32 -1) - %53 = call %String* @__quantum__rt__int_to_string(i64 %48) - %54 = call %String* @__quantum__rt__string_concatenate(%String* %52, %String* %53) - call void @__quantum__rt__string_update_reference_count(%String* %52, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %53, i32 -1) - %55 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @16, i32 0, i32 0)) - %56 = call %String* @__quantum__rt__string_concatenate(%String* %54, %String* %55) - call void @__quantum__rt__string_update_reference_count(%String* %54, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %55, i32 -1) - call void @__quantum__rt__message(%String* %56) - %57 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @17, i32 0, i32 0)) - %58 = call %String* @__quantum__rt__range_to_string(%Range %rangeValue) - %59 = call %String* @__quantum__rt__string_concatenate(%String* %57, %String* %58) - call void @__quantum__rt__string_update_reference_count(%String* %57, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %58, i32 -1) - call void @__quantum__rt__message(%String* %59) - %60 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @18, i32 0, i32 0)) - %61 = call %String* @__quantum__rt__result_to_string(%Result* %resultValue) - %62 = call %String* @__quantum__rt__string_concatenate(%String* %60, %String* %61) - call void @__quantum__rt__string_update_reference_count(%String* %60, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %61, i32 -1) - call void @__quantum__rt__message(%String* %62) - %63 = call %String* @Quantum__StandaloneSupportedInputs___c22db911562e4518b3ec04b3a395976a_ArrayToString__body(%Array* %resultArray) - %64 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %65 = call i64 @Microsoft__Quantum__Arrays___aa464afb2404486a86d7d9b45b4e8d2c_Count__body(%Callable* %64, %Array* %resultArray) - %66 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @19, i32 0, i32 0)) - call void @__quantum__rt__string_update_reference_count(%String* %63, i32 1) - %67 = call %String* @__quantum__rt__string_concatenate(%String* %66, %String* %63) - call void @__quantum__rt__string_update_reference_count(%String* %66, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %63, i32 -1) - %68 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @20, i32 0, i32 0)) - %69 = call %String* @__quantum__rt__string_concatenate(%String* %67, %String* %68) - call void @__quantum__rt__string_update_reference_count(%String* %67, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %68, i32 -1) - %70 = call %String* @__quantum__rt__int_to_string(i64 %65) - %71 = call %String* @__quantum__rt__string_concatenate(%String* %69, %String* %70) - call void @__quantum__rt__string_update_reference_count(%String* %69, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %70, i32 -1) - %72 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @21, i32 0, i32 0)) - %73 = call %String* @__quantum__rt__string_concatenate(%String* %71, %String* %72) - call void @__quantum__rt__string_update_reference_count(%String* %71, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %72, i32 -1) - call void @__quantum__rt__message(%String* %73) - %74 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @22, i32 0, i32 0)) - call void @__quantum__rt__string_update_reference_count(%String* %stringValue, i32 1) - %75 = call %String* @__quantum__rt__string_concatenate(%String* %74, %String* %stringValue) - call void @__quantum__rt__string_update_reference_count(%String* %74, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %stringValue, i32 -1) - call void @__quantum__rt__message(%String* %75) - call void @__quantum__rt__array_update_alias_count(%Array* %intArray, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %doubleArray, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %boolArray, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %pauliArray, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %resultArray, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %3, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %4, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %5, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %5, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %28, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %31, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %32, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %33, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %33, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %42, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %45, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %46, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %47, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %47, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %56, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %59, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %62, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %63, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %64, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %64, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %73, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %75, i32 -1) - ret void -} - -declare void @__quantum__rt__array_update_alias_count(%Array*, i32) - -declare %String* @__quantum__rt__string_create(i8*) - -declare void @__quantum__rt__message(%String*) - -declare void @__quantum__rt__string_update_reference_count(%String*, i32) - -declare %String* @__quantum__rt__int_to_string(i64) - -declare %String* @__quantum__rt__string_concatenate(%String*, %String*) - -define %String* @Quantum__StandaloneSupportedInputs___58b06fb8838645aba850713a715678d6_ArrayToString__body(%Array* %array) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %first = alloca i1, align 1 - store i1 true, i1* %first, align 1 - %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @23, i32 0, i32 0)) - %itemsString = alloca %String*, align 8 - store %String* %0, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) - %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %2 = sub i64 %1, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] - %4 = icmp sle i64 %3, %2 - br i1 %4, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) - %6 = bitcast i8* %5 to i64* - %item = load i64, i64* %6, align 4 - %7 = load i1, i1* %first, align 1 - br i1 %7, label %then0__1, label %else__1 - -then0__1: ; preds = %body__1 - store i1 false, i1* %first, align 1 - %8 = load %String*, %String** %itemsString, align 8 - %9 = call %String* @__quantum__rt__int_to_string(i64 %item) - %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) - store %String* %10, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) - br label %continue__1 - -else__1: ; preds = %body__1 - %11 = load %String*, %String** %itemsString, align 8 - %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @24, i32 0, i32 0)) - %13 = call %String* @__quantum__rt__int_to_string(i64 %item) - %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) - call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) - %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) - store %String* %15, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %16 = add i64 %3, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %17 = load %String*, %String** %itemsString, align 8 - %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @25, i32 0, i32 0)) - %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) - store %String* %19, %String** %itemsString, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) - ret %String* %19 -} - -define i64 @Microsoft__Quantum__Arrays___8487a9df7d0d4ac5a6694fb1d077b2b4_Count__body(%Callable* %predicate, %Array* %array) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %totalFound = alloca i64, align 8 - store i64 0, i64* %totalFound, align 4 - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %1 = sub i64 %0, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %3 = icmp sle i64 %2, %1 - br i1 %3, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) - %5 = bitcast i8* %4 to i64* - %element = load i64, i64* %5, align 4 - %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i64* getelementptr (i64, i64* null, i32 1) to i64)) - %7 = bitcast %Tuple* %6 to { i64 }* - %8 = getelementptr inbounds { i64 }, { i64 }* %7, i32 0, i32 0 - store i64 %element, i64* %8, align 4 - %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) - call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) - %10 = bitcast %Tuple* %9 to { i1 }* - %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 - %12 = load i1, i1* %11, align 1 - br i1 %12, label %then0__1, label %continue__1 - -then0__1: ; preds = %body__1 - %13 = load i64, i64* %totalFound, align 4 - %14 = add i64 %13, 1 - store i64 %14, i64* %totalFound, align 4 - br label %continue__1 - -continue__1: ; preds = %then0__1, %body__1 - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %15 = add i64 %2, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = load i64, i64* %totalFound, align 4 - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - ret i64 %16 -} - -define void @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { i64 }* - %1 = getelementptr inbounds { i64 }, { i64 }* %0, i32 0, i32 0 - %2 = load i64, i64* %1, align 4 - %3 = call i1 @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body(i64 %2) - %4 = bitcast %Tuple* %result-tuple to { i1 }* - %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 - store i1 %3, i1* %5, align 1 - ret void -} - -declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i32)*]*, %Tuple*) - -declare %String* @__quantum__rt__double_to_string(double) - -define %String* @Quantum__StandaloneSupportedInputs___651cdf0b91af440a8c52eefc05d57b06_ArrayToString__body(%Array* %array) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %first = alloca i1, align 1 - store i1 true, i1* %first, align 1 - %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @26, i32 0, i32 0)) - %itemsString = alloca %String*, align 8 - store %String* %0, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) - %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %2 = sub i64 %1, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] - %4 = icmp sle i64 %3, %2 - br i1 %4, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) - %6 = bitcast i8* %5 to double* - %item = load double, double* %6, align 8 - %7 = load i1, i1* %first, align 1 - br i1 %7, label %then0__1, label %else__1 - -then0__1: ; preds = %body__1 - store i1 false, i1* %first, align 1 - %8 = load %String*, %String** %itemsString, align 8 - %9 = call %String* @__quantum__rt__double_to_string(double %item) - %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) - store %String* %10, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) - br label %continue__1 - -else__1: ; preds = %body__1 - %11 = load %String*, %String** %itemsString, align 8 - %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @27, i32 0, i32 0)) - %13 = call %String* @__quantum__rt__double_to_string(double %item) - %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) - call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) - %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) - store %String* %15, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %16 = add i64 %3, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %17 = load %String*, %String** %itemsString, align 8 - %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @28, i32 0, i32 0)) - %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) - store %String* %19, %String** %itemsString, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) - ret %String* %19 -} - -define i64 @Microsoft__Quantum__Arrays___1575e931e75b478d9338ff1c1ba98161_Count__body(%Callable* %predicate, %Array* %array) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %totalFound = alloca i64, align 8 - store i64 0, i64* %totalFound, align 4 - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %1 = sub i64 %0, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %3 = icmp sle i64 %2, %1 - br i1 %3, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) - %5 = bitcast i8* %4 to double* - %element = load double, double* %5, align 8 - %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64)) - %7 = bitcast %Tuple* %6 to { double }* - %8 = getelementptr inbounds { double }, { double }* %7, i32 0, i32 0 - store double %element, double* %8, align 8 - %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) - call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) - %10 = bitcast %Tuple* %9 to { i1 }* - %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 - %12 = load i1, i1* %11, align 1 - br i1 %12, label %then0__1, label %continue__1 - -then0__1: ; preds = %body__1 - %13 = load i64, i64* %totalFound, align 4 - %14 = add i64 %13, 1 - store i64 %14, i64* %totalFound, align 4 - br label %continue__1 - -continue__1: ; preds = %then0__1, %body__1 - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %15 = add i64 %2, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = load i64, i64* %totalFound, align 4 - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - ret i64 %16 -} - -define void @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { double }* - %1 = getelementptr inbounds { double }, { double }* %0, i32 0, i32 0 - %2 = load double, double* %1, align 8 - %3 = call i1 @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body(double %2) - %4 = bitcast %Tuple* %result-tuple to { i1 }* - %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 - store i1 %3, i1* %5, align 1 - ret void -} - -declare %String* @__quantum__rt__bool_to_string(i1) - -define %String* @Quantum__StandaloneSupportedInputs___f5a60aadd6b1405d8efce41485ff4d80_ArrayToString__body(%Array* %array) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %first = alloca i1, align 1 - store i1 true, i1* %first, align 1 - %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @29, i32 0, i32 0)) - %itemsString = alloca %String*, align 8 - store %String* %0, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) - %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %2 = sub i64 %1, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] - %4 = icmp sle i64 %3, %2 - br i1 %4, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) - %6 = bitcast i8* %5 to i1* - %item = load i1, i1* %6, align 1 - %7 = load i1, i1* %first, align 1 - br i1 %7, label %then0__1, label %else__1 - -then0__1: ; preds = %body__1 - store i1 false, i1* %first, align 1 - %8 = load %String*, %String** %itemsString, align 8 - %9 = call %String* @__quantum__rt__bool_to_string(i1 %item) - %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) - store %String* %10, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) - br label %continue__1 - -else__1: ; preds = %body__1 - %11 = load %String*, %String** %itemsString, align 8 - %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @30, i32 0, i32 0)) - %13 = call %String* @__quantum__rt__bool_to_string(i1 %item) - %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) - call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) - %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) - store %String* %15, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %16 = add i64 %3, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %17 = load %String*, %String** %itemsString, align 8 - %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @31, i32 0, i32 0)) - %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) - store %String* %19, %String** %itemsString, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) - ret %String* %19 -} - -define i64 @Microsoft__Quantum__Arrays___67c459c137a0446995c133a29250678d_Count__body(%Callable* %predicate, %Array* %array) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %totalFound = alloca i64, align 8 - store i64 0, i64* %totalFound, align 4 - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %1 = sub i64 %0, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %3 = icmp sle i64 %2, %1 - br i1 %3, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) - %5 = bitcast i8* %4 to i1* - %element = load i1, i1* %5, align 1 - %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) - %7 = bitcast %Tuple* %6 to { i1 }* - %8 = getelementptr inbounds { i1 }, { i1 }* %7, i32 0, i32 0 - store i1 %element, i1* %8, align 1 - %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) - call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) - %10 = bitcast %Tuple* %9 to { i1 }* - %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 - %12 = load i1, i1* %11, align 1 - br i1 %12, label %then0__1, label %continue__1 - -then0__1: ; preds = %body__1 - %13 = load i64, i64* %totalFound, align 4 - %14 = add i64 %13, 1 - store i64 %14, i64* %totalFound, align 4 - br label %continue__1 - -continue__1: ; preds = %then0__1, %body__1 - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %15 = add i64 %2, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = load i64, i64* %totalFound, align 4 - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - ret i64 %16 -} - -define void @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { i1 }* - %1 = getelementptr inbounds { i1 }, { i1 }* %0, i32 0, i32 0 - %2 = load i1, i1* %1, align 1 - %3 = call i1 @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body(i1 %2) - %4 = bitcast %Tuple* %result-tuple to { i1 }* - %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 - store i1 %3, i1* %5, align 1 - ret void -} - -declare %String* @__quantum__rt__pauli_to_string(i2) - -define %String* @Quantum__StandaloneSupportedInputs___ec0b3349aeaf419f9d7d96decefd1869_ArrayToString__body(%Array* %array) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %first = alloca i1, align 1 - store i1 true, i1* %first, align 1 - %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @32, i32 0, i32 0)) - %itemsString = alloca %String*, align 8 - store %String* %0, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) - %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %2 = sub i64 %1, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] - %4 = icmp sle i64 %3, %2 - br i1 %4, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) - %6 = bitcast i8* %5 to i2* - %item = load i2, i2* %6, align 1 - %7 = load i1, i1* %first, align 1 - br i1 %7, label %then0__1, label %else__1 - -then0__1: ; preds = %body__1 - store i1 false, i1* %first, align 1 - %8 = load %String*, %String** %itemsString, align 8 - %9 = call %String* @__quantum__rt__pauli_to_string(i2 %item) - %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) - store %String* %10, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) - br label %continue__1 - -else__1: ; preds = %body__1 - %11 = load %String*, %String** %itemsString, align 8 - %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @33, i32 0, i32 0)) - %13 = call %String* @__quantum__rt__pauli_to_string(i2 %item) - %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) - call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) - %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) - store %String* %15, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %16 = add i64 %3, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %17 = load %String*, %String** %itemsString, align 8 - %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @34, i32 0, i32 0)) - %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) - store %String* %19, %String** %itemsString, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) - ret %String* %19 -} - -define i64 @Microsoft__Quantum__Arrays___c71932228c1b4b6fb8c3c63c9d8e35e4_Count__body(%Callable* %predicate, %Array* %array) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %totalFound = alloca i64, align 8 - store i64 0, i64* %totalFound, align 4 - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %1 = sub i64 %0, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %3 = icmp sle i64 %2, %1 - br i1 %3, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) - %5 = bitcast i8* %4 to i2* - %element = load i2, i2* %5, align 1 - %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i2* getelementptr (i2, i2* null, i32 1) to i64)) - %7 = bitcast %Tuple* %6 to { i2 }* - %8 = getelementptr inbounds { i2 }, { i2 }* %7, i32 0, i32 0 - store i2 %element, i2* %8, align 1 - %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) - call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) - %10 = bitcast %Tuple* %9 to { i1 }* - %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 - %12 = load i1, i1* %11, align 1 - br i1 %12, label %then0__1, label %continue__1 - -then0__1: ; preds = %body__1 - %13 = load i64, i64* %totalFound, align 4 - %14 = add i64 %13, 1 - store i64 %14, i64* %totalFound, align 4 - br label %continue__1 - -continue__1: ; preds = %then0__1, %body__1 - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %15 = add i64 %2, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = load i64, i64* %totalFound, align 4 - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - ret i64 %16 -} - -define void @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { i2 }* - %1 = getelementptr inbounds { i2 }, { i2 }* %0, i32 0, i32 0 - %2 = load i2, i2* %1, align 1 - %3 = call i1 @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body(i2 %2) - %4 = bitcast %Tuple* %result-tuple to { i1 }* - %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 - store i1 %3, i1* %5, align 1 - ret void -} - -declare %String* @__quantum__rt__range_to_string(%Range) - -declare %String* @__quantum__rt__result_to_string(%Result*) - -define %String* @Quantum__StandaloneSupportedInputs___c22db911562e4518b3ec04b3a395976a_ArrayToString__body(%Array* %array) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %first = alloca i1, align 1 - store i1 true, i1* %first, align 1 - %0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @35, i32 0, i32 0)) - %itemsString = alloca %String*, align 8 - store %String* %0, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 1) - %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %2 = sub i64 %1, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %3 = phi i64 [ 0, %entry ], [ %16, %exiting__1 ] - %4 = icmp sle i64 %3, %2 - br i1 %4, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %5 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %3) - %6 = bitcast i8* %5 to %Result** - %item = load %Result*, %Result** %6, align 8 - %7 = load i1, i1* %first, align 1 - br i1 %7, label %then0__1, label %else__1 - -then0__1: ; preds = %body__1 - store i1 false, i1* %first, align 1 - %8 = load %String*, %String** %itemsString, align 8 - %9 = call %String* @__quantum__rt__result_to_string(%Result* %item) - %10 = call %String* @__quantum__rt__string_concatenate(%String* %8, %String* %9) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 1) - store %String* %10, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %9, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %10, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %8, i32 -1) - br label %continue__1 - -else__1: ; preds = %body__1 - %11 = load %String*, %String** %itemsString, align 8 - %12 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @36, i32 0, i32 0)) - %13 = call %String* @__quantum__rt__result_to_string(%Result* %item) - %14 = call %String* @__quantum__rt__string_concatenate(%String* %12, %String* %13) - call void @__quantum__rt__string_update_reference_count(%String* %12, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %13, i32 -1) - %15 = call %String* @__quantum__rt__string_concatenate(%String* %11, %String* %14) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 1) - store %String* %15, %String** %itemsString, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %14, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %15, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %11, i32 -1) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %16 = add i64 %3, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %17 = load %String*, %String** %itemsString, align 8 - %18 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @37, i32 0, i32 0)) - %19 = call %String* @__quantum__rt__string_concatenate(%String* %17, %String* %18) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 1) - store %String* %19, %String** %itemsString, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %18, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %17, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %19, i32 -1) - ret %String* %19 -} - -define i64 @Microsoft__Quantum__Arrays___aa464afb2404486a86d7d9b45b4e8d2c_Count__body(%Callable* %predicate, %Array* %array) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 1) - %totalFound = alloca i64, align 8 - store i64 0, i64* %totalFound, align 4 - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %array) - %1 = sub i64 %0, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %2 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %3 = icmp sle i64 %2, %1 - br i1 %3, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %array, i64 %2) - %5 = bitcast i8* %4 to %Result** - %element = load %Result*, %Result** %5, align 8 - %6 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) - %7 = bitcast %Tuple* %6 to { %Result* }* - %8 = getelementptr inbounds { %Result* }, { %Result* }* %7, i32 0, i32 0 - store %Result* %element, %Result** %8, align 8 - %9 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1* getelementptr (i1, i1* null, i32 1) to i64)) - call void @__quantum__rt__callable_invoke(%Callable* %predicate, %Tuple* %6, %Tuple* %9) - %10 = bitcast %Tuple* %9 to { i1 }* - %11 = getelementptr inbounds { i1 }, { i1 }* %10, i32 0, i32 0 - %12 = load i1, i1* %11, align 1 - br i1 %12, label %then0__1, label %continue__1 - -then0__1: ; preds = %body__1 - %13 = load i64, i64* %totalFound, align 4 - %14 = add i64 %13, 1 - store i64 %14, i64* %totalFound, align 4 - br label %continue__1 - -continue__1: ; preds = %then0__1, %body__1 - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %9, i32 -1) - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %15 = add i64 %2, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = load i64, i64* %totalFound, align 4 - call void @__quantum__rt__capture_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %predicate, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %array, i32 -1) - ret i64 %16 -} - -define void @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Result* }* - %1 = getelementptr inbounds { %Result* }, { %Result* }* %0, i32 0, i32 0 - %2 = load %Result*, %Result** %1, align 8 - %3 = call i1 @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body(%Result* %2) - %4 = bitcast %Tuple* %result-tuple to { i1 }* - %5 = getelementptr inbounds { i1 }, { i1 }* %4, i32 0, i32 0 - store i1 %3, i1* %5, align 1 - ret void -} - -declare void @__quantum__rt__capture_update_reference_count(%Callable*, i32) - -declare void @__quantum__rt__callable_update_reference_count(%Callable*, i32) - -declare i64 @__quantum__rt__array_get_size_1d(%Array*) - -declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) - -define i1 @Quantum__StandaloneSupportedInputs___ebb122eaf9244a3ca8f07f274c8368b4_TautologyPredicate__body(i64 %input) { -entry: - ret i1 true -} - -define i1 @Quantum__StandaloneSupportedInputs___8723f095507647b0aef15b4b24f7fa0c_TautologyPredicate__body(double %input) { -entry: - ret i1 true -} - -define i1 @Quantum__StandaloneSupportedInputs___d127770a63ce4b8b924428e84b62936a_TautologyPredicate__body(i1 %input) { -entry: - ret i1 true -} - -define i1 @Quantum__StandaloneSupportedInputs___92bcc13ad4b7481581e7813da34f42ed_TautologyPredicate__body(i2 %input) { -entry: - ret i1 true -} - -define i1 @Quantum__StandaloneSupportedInputs___34109cb82da642eabac2d5c8cf2751a5_TautologyPredicate__body(%Result* %input) { -entry: - ret i1 true -} - -declare void @__quantum__rt__capture_update_alias_count(%Callable*, i32) - -declare void @__quantum__rt__callable_update_alias_count(%Callable*, i32) - -declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*) - -declare %Tuple* @__quantum__rt__tuple_create(i64) - -declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i32) - -define void @Quantum__StandaloneSupportedInputs__ExerciseInputs__Interop(i64 %intValue, { i64, i8* }* %intArray, double %doubleValue, { i64, i8* }* %doubleArray, i8 %boolValue, { i64, i8* }* %boolArray, i8 %pauliValue, { i64, i8* }* %pauliArray, { i64, i64, i64 }* %rangeValue, i8 %resultValue, { i64, i8* }* %resultArray, i8* %stringValue) #0 { -entry: - %0 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 0 - %1 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 1 - %2 = load i64, i64* %0, align 4 - %3 = load i8*, i8** %1, align 8 - %4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %2) - %5 = ptrtoint i8* %3 to i64 - %6 = sub i64 %2, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %7 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %8 = icmp sle i64 %7, %6 - br i1 %8, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %9 = mul i64 %7, 8 - %10 = add i64 %5, %9 - %11 = inttoptr i64 %10 to i64* - %12 = load i64, i64* %11, align 4 - %13 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %4, i64 %7) - %14 = bitcast i8* %13 to i64* - store i64 %12, i64* %14, align 4 - br label %exiting__1 - -exiting__1: ; preds = %body__1 - %15 = add i64 %7, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 0 - %17 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 1 - %18 = load i64, i64* %16, align 4 - %19 = load i8*, i8** %17, align 8 - %20 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %18) - %21 = ptrtoint i8* %19 to i64 - %22 = sub i64 %18, 1 - br label %header__2 - -header__2: ; preds = %exiting__2, %exit__1 - %23 = phi i64 [ 0, %exit__1 ], [ %31, %exiting__2 ] - %24 = icmp sle i64 %23, %22 - br i1 %24, label %body__2, label %exit__2 - -body__2: ; preds = %header__2 - %25 = mul i64 %23, 8 - %26 = add i64 %21, %25 - %27 = inttoptr i64 %26 to double* - %28 = load double, double* %27, align 8 - %29 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %20, i64 %23) - %30 = bitcast i8* %29 to double* - store double %28, double* %30, align 8 - br label %exiting__2 - -exiting__2: ; preds = %body__2 - %31 = add i64 %23, 1 - br label %header__2 - -exit__2: ; preds = %header__2 - %32 = trunc i8 %boolValue to i1 - %33 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 0 - %34 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 1 - %35 = load i64, i64* %33, align 4 - %36 = load i8*, i8** %34, align 8 - %37 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %35) - %38 = ptrtoint i8* %36 to i64 - %39 = sub i64 %35, 1 - br label %header__3 - -header__3: ; preds = %exiting__3, %exit__2 - %40 = phi i64 [ 0, %exit__2 ], [ %49, %exiting__3 ] - %41 = icmp sle i64 %40, %39 - br i1 %41, label %body__3, label %exit__3 - -body__3: ; preds = %header__3 - %42 = mul i64 %40, 1 - %43 = add i64 %38, %42 - %44 = inttoptr i64 %43 to i8* - %45 = load i8, i8* %44, align 1 - %46 = trunc i8 %45 to i1 - %47 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %37, i64 %40) - %48 = bitcast i8* %47 to i1* - store i1 %46, i1* %48, align 1 - br label %exiting__3 - -exiting__3: ; preds = %body__3 - %49 = add i64 %40, 1 - br label %header__3 - -exit__3: ; preds = %header__3 - %50 = trunc i8 %pauliValue to i2 - %51 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 0 - %52 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 1 - %53 = load i64, i64* %51, align 4 - %54 = load i8*, i8** %52, align 8 - %55 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %53) - %56 = ptrtoint i8* %54 to i64 - %57 = sub i64 %53, 1 - br label %header__4 - -header__4: ; preds = %exiting__4, %exit__3 - %58 = phi i64 [ 0, %exit__3 ], [ %67, %exiting__4 ] - %59 = icmp sle i64 %58, %57 - br i1 %59, label %body__4, label %exit__4 - -body__4: ; preds = %header__4 - %60 = mul i64 %58, 1 - %61 = add i64 %56, %60 - %62 = inttoptr i64 %61 to i8* - %63 = load i8, i8* %62, align 1 - %64 = trunc i8 %63 to i2 - %65 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %55, i64 %58) - %66 = bitcast i8* %65 to i2* - store i2 %64, i2* %66, align 1 - br label %exiting__4 - -exiting__4: ; preds = %body__4 - %67 = add i64 %58, 1 - br label %header__4 - -exit__4: ; preds = %header__4 - %68 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 0 - %69 = load i64, i64* %68, align 4 - %70 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 1 - %71 = load i64, i64* %70, align 4 - %72 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 2 - %73 = load i64, i64* %72, align 4 - %74 = load %Range, %Range* @EmptyRange, align 4 - %75 = insertvalue %Range %74, i64 %69, 0 - %76 = insertvalue %Range %75, i64 %71, 1 - %77 = insertvalue %Range %76, i64 %73, 2 - %78 = icmp eq i8 %resultValue, 0 - %79 = call %Result* @__quantum__rt__result_get_zero() - %80 = call %Result* @__quantum__rt__result_get_one() - %81 = select i1 %78, %Result* %79, %Result* %80 - %82 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 0 - %83 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 1 - %84 = load i64, i64* %82, align 4 - %85 = load i8*, i8** %83, align 8 - %86 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %84) - %87 = ptrtoint i8* %85 to i64 - %88 = sub i64 %84, 1 - br label %header__5 - -header__5: ; preds = %exiting__5, %exit__4 - %89 = phi i64 [ 0, %exit__4 ], [ %101, %exiting__5 ] - %90 = icmp sle i64 %89, %88 - br i1 %90, label %body__5, label %exit__5 - -body__5: ; preds = %header__5 - %91 = mul i64 %89, 1 - %92 = add i64 %87, %91 - %93 = inttoptr i64 %92 to i8* - %94 = load i8, i8* %93, align 1 - %95 = icmp eq i8 %94, 0 - %96 = call %Result* @__quantum__rt__result_get_zero() - %97 = call %Result* @__quantum__rt__result_get_one() - %98 = select i1 %95, %Result* %96, %Result* %97 - %99 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %89) - %100 = bitcast i8* %99 to %Result** - store %Result* %98, %Result** %100, align 8 - br label %exiting__5 - -exiting__5: ; preds = %body__5 - %101 = add i64 %89, 1 - br label %header__5 - -exit__5: ; preds = %header__5 - %102 = call %String* @__quantum__rt__string_create(i8* %stringValue) - call void @Quantum__StandaloneSupportedInputs__ExerciseInputs__body(i64 %intValue, %Array* %4, double %doubleValue, %Array* %20, i1 %32, %Array* %37, i2 %50, %Array* %55, %Range %77, %Result* %81, %Array* %86, %String* %102) - call void @__quantum__rt__array_update_reference_count(%Array* %4, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %20, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %37, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %55, i32 -1) - %103 = sub i64 %84, 1 - br label %header__6 - -header__6: ; preds = %exiting__6, %exit__5 - %104 = phi i64 [ 0, %exit__5 ], [ %109, %exiting__6 ] - %105 = icmp sle i64 %104, %103 - br i1 %105, label %body__6, label %exit__6 - -body__6: ; preds = %header__6 - %106 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %104) - %107 = bitcast i8* %106 to %Result** - %108 = load %Result*, %Result** %107, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %108, i32 -1) - br label %exiting__6 - -exiting__6: ; preds = %body__6 - %109 = add i64 %104, 1 - br label %header__6 - -exit__6: ; preds = %header__6 - call void @__quantum__rt__array_update_reference_count(%Array* %86, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %102, i32 -1) - ret void -} - -declare %Array* @__quantum__rt__array_create_1d(i32, i64) - -declare %Result* @__quantum__rt__result_get_zero() - -declare %Result* @__quantum__rt__result_get_one() - -declare void @__quantum__rt__array_update_reference_count(%Array*, i32) - -declare void @__quantum__rt__result_update_reference_count(%Result*, i32) - -define void @Quantum__StandaloneSupportedInputs__ExerciseInputs(i64 %intValue, { i64, i8* }* %intArray, double %doubleValue, { i64, i8* }* %doubleArray, i8 %boolValue, { i64, i8* }* %boolArray, i8 %pauliValue, { i64, i8* }* %pauliArray, { i64, i64, i64 }* %rangeValue, i8 %resultValue, { i64, i8* }* %resultArray, i8* %stringValue) #1 { -entry: - %0 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 0 - %1 = getelementptr { i64, i8* }, { i64, i8* }* %intArray, i64 0, i32 1 - %2 = load i64, i64* %0, align 4 - %3 = load i8*, i8** %1, align 8 - %4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %2) - %5 = ptrtoint i8* %3 to i64 - %6 = sub i64 %2, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %7 = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %8 = icmp sle i64 %7, %6 - br i1 %8, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %9 = mul i64 %7, 8 - %10 = add i64 %5, %9 - %11 = inttoptr i64 %10 to i64* - %12 = load i64, i64* %11, align 4 - %13 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %4, i64 %7) - %14 = bitcast i8* %13 to i64* - store i64 %12, i64* %14, align 4 - br label %exiting__1 - -exiting__1: ; preds = %body__1 - %15 = add i64 %7, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 0 - %17 = getelementptr { i64, i8* }, { i64, i8* }* %doubleArray, i64 0, i32 1 - %18 = load i64, i64* %16, align 4 - %19 = load i8*, i8** %17, align 8 - %20 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %18) - %21 = ptrtoint i8* %19 to i64 - %22 = sub i64 %18, 1 - br label %header__2 - -header__2: ; preds = %exiting__2, %exit__1 - %23 = phi i64 [ 0, %exit__1 ], [ %31, %exiting__2 ] - %24 = icmp sle i64 %23, %22 - br i1 %24, label %body__2, label %exit__2 - -body__2: ; preds = %header__2 - %25 = mul i64 %23, 8 - %26 = add i64 %21, %25 - %27 = inttoptr i64 %26 to double* - %28 = load double, double* %27, align 8 - %29 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %20, i64 %23) - %30 = bitcast i8* %29 to double* - store double %28, double* %30, align 8 - br label %exiting__2 - -exiting__2: ; preds = %body__2 - %31 = add i64 %23, 1 - br label %header__2 - -exit__2: ; preds = %header__2 - %32 = trunc i8 %boolValue to i1 - %33 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 0 - %34 = getelementptr { i64, i8* }, { i64, i8* }* %boolArray, i64 0, i32 1 - %35 = load i64, i64* %33, align 4 - %36 = load i8*, i8** %34, align 8 - %37 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %35) - %38 = ptrtoint i8* %36 to i64 - %39 = sub i64 %35, 1 - br label %header__3 - -header__3: ; preds = %exiting__3, %exit__2 - %40 = phi i64 [ 0, %exit__2 ], [ %49, %exiting__3 ] - %41 = icmp sle i64 %40, %39 - br i1 %41, label %body__3, label %exit__3 - -body__3: ; preds = %header__3 - %42 = mul i64 %40, 1 - %43 = add i64 %38, %42 - %44 = inttoptr i64 %43 to i8* - %45 = load i8, i8* %44, align 1 - %46 = trunc i8 %45 to i1 - %47 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %37, i64 %40) - %48 = bitcast i8* %47 to i1* - store i1 %46, i1* %48, align 1 - br label %exiting__3 - -exiting__3: ; preds = %body__3 - %49 = add i64 %40, 1 - br label %header__3 - -exit__3: ; preds = %header__3 - %50 = trunc i8 %pauliValue to i2 - %51 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 0 - %52 = getelementptr { i64, i8* }, { i64, i8* }* %pauliArray, i64 0, i32 1 - %53 = load i64, i64* %51, align 4 - %54 = load i8*, i8** %52, align 8 - %55 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 %53) - %56 = ptrtoint i8* %54 to i64 - %57 = sub i64 %53, 1 - br label %header__4 - -header__4: ; preds = %exiting__4, %exit__3 - %58 = phi i64 [ 0, %exit__3 ], [ %67, %exiting__4 ] - %59 = icmp sle i64 %58, %57 - br i1 %59, label %body__4, label %exit__4 - -body__4: ; preds = %header__4 - %60 = mul i64 %58, 1 - %61 = add i64 %56, %60 - %62 = inttoptr i64 %61 to i8* - %63 = load i8, i8* %62, align 1 - %64 = trunc i8 %63 to i2 - %65 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %55, i64 %58) - %66 = bitcast i8* %65 to i2* - store i2 %64, i2* %66, align 1 - br label %exiting__4 - -exiting__4: ; preds = %body__4 - %67 = add i64 %58, 1 - br label %header__4 - -exit__4: ; preds = %header__4 - %68 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 0 - %69 = load i64, i64* %68, align 4 - %70 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 1 - %71 = load i64, i64* %70, align 4 - %72 = getelementptr { i64, i64, i64 }, { i64, i64, i64 }* %rangeValue, i64 0, i32 2 - %73 = load i64, i64* %72, align 4 - %74 = load %Range, %Range* @EmptyRange, align 4 - %75 = insertvalue %Range %74, i64 %69, 0 - %76 = insertvalue %Range %75, i64 %71, 1 - %77 = insertvalue %Range %76, i64 %73, 2 - %78 = icmp eq i8 %resultValue, 0 - %79 = call %Result* @__quantum__rt__result_get_zero() - %80 = call %Result* @__quantum__rt__result_get_one() - %81 = select i1 %78, %Result* %79, %Result* %80 - %82 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 0 - %83 = getelementptr { i64, i8* }, { i64, i8* }* %resultArray, i64 0, i32 1 - %84 = load i64, i64* %82, align 4 - %85 = load i8*, i8** %83, align 8 - %86 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 %84) - %87 = ptrtoint i8* %85 to i64 - %88 = sub i64 %84, 1 - br label %header__5 - -header__5: ; preds = %exiting__5, %exit__4 - %89 = phi i64 [ 0, %exit__4 ], [ %101, %exiting__5 ] - %90 = icmp sle i64 %89, %88 - br i1 %90, label %body__5, label %exit__5 - -body__5: ; preds = %header__5 - %91 = mul i64 %89, 1 - %92 = add i64 %87, %91 - %93 = inttoptr i64 %92 to i8* - %94 = load i8, i8* %93, align 1 - %95 = icmp eq i8 %94, 0 - %96 = call %Result* @__quantum__rt__result_get_zero() - %97 = call %Result* @__quantum__rt__result_get_one() - %98 = select i1 %95, %Result* %96, %Result* %97 - %99 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %89) - %100 = bitcast i8* %99 to %Result** - store %Result* %98, %Result** %100, align 8 - br label %exiting__5 - -exiting__5: ; preds = %body__5 - %101 = add i64 %89, 1 - br label %header__5 - -exit__5: ; preds = %header__5 - %102 = call %String* @__quantum__rt__string_create(i8* %stringValue) - call void @Quantum__StandaloneSupportedInputs__ExerciseInputs__body(i64 %intValue, %Array* %4, double %doubleValue, %Array* %20, i1 %32, %Array* %37, i2 %50, %Array* %55, %Range %77, %Result* %81, %Array* %86, %String* %102) - %103 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @38, i32 0, i32 0)) - call void @__quantum__rt__message(%String* %103) - call void @__quantum__rt__array_update_reference_count(%Array* %4, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %20, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %37, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %55, i32 -1) - %104 = sub i64 %84, 1 - br label %header__6 - -header__6: ; preds = %exiting__6, %exit__5 - %105 = phi i64 [ 0, %exit__5 ], [ %110, %exiting__6 ] - %106 = icmp sle i64 %105, %104 - br i1 %106, label %body__6, label %exit__6 - -body__6: ; preds = %header__6 - %107 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %86, i64 %105) - %108 = bitcast i8* %107 to %Result** - %109 = load %Result*, %Result** %108, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %109, i32 -1) - br label %exiting__6 - -exiting__6: ; preds = %body__6 - %110 = add i64 %105, 1 - br label %header__6 - -exit__6: ; preds = %header__6 - call void @__quantum__rt__array_update_reference_count(%Array* %86, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %102, i32 -1) - call void @__quantum__rt__string_update_reference_count(%String* %103, i32 -1) - ret void -} - -attributes #0 = { "InteropFriendly" } -attributes #1 = { "EntryPoint" } diff --git a/src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll b/src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll deleted file mode 100644 index a86f7f54e43..00000000000 --- a/src/QirRuntime/test/FullstateSimulator/qsharp/qir/qir-test-simulator.ll +++ /dev/null @@ -1,1387 +0,0 @@ - -%Range = type { i64, i64, i64 } -%Tuple = type opaque -%Callable = type opaque -%Array = type opaque -%Qubit = type opaque -%Result = type opaque -%String = type opaque - -@PauliI = constant i2 0 -@PauliX = constant i2 1 -@PauliY = constant i2 -1 -@PauliZ = constant i2 -2 -@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } -@Microsoft__Quantum__Intrinsic__X = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper] -@Microsoft__Quantum__Intrinsic__Y = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper] -@Microsoft__Quantum__Intrinsic__Z = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper] -@Microsoft__Quantum__Intrinsic__H = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__H__ctladj__wrapper] -@Microsoft__Quantum__Intrinsic__S = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper] -@Microsoft__Quantum__Intrinsic__T = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__T__ctladj__wrapper] -@Microsoft__Quantum__Intrinsic__R = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__R__ctladj__wrapper] -@PartialApplication__1 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__ctladj__wrapper] -@MemoryManagement__1 = constant [2 x void (%Tuple*, i32)*] [void (%Tuple*, i32)* @MemoryManagement__1__RefCount, void (%Tuple*, i32)* @MemoryManagement__1__AliasCount] - -@Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__Interop = alias i64 (), i64 ()* @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__body - -define i64 @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__body() #0 { -entry: - %res = alloca i64, align 8 - store i64 0, i64* %res, align 4 - %0 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__X, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %1 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %0) - store i64 %1, i64* %res, align 4 - %2 = icmp ne i64 %1, 0 - br i1 %2, label %then0__1, label %continue__1 - -then0__1: ; preds = %entry - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - ret i64 %1 - -continue__1: ; preds = %entry - %3 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Y, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %4 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %3) - store i64 %4, i64* %res, align 4 - %5 = icmp ne i64 %4, 0 - br i1 %5, label %then0__2, label %continue__2 - -then0__2: ; preds = %continue__1 - %6 = add i64 10, %4 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - ret i64 %6 - -continue__2: ; preds = %continue__1 - %7 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Z, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %8 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %7) - store i64 %8, i64* %res, align 4 - %9 = icmp ne i64 %8, 0 - br i1 %9, label %then0__3, label %continue__3 - -then0__3: ; preds = %continue__2 - %10 = add i64 20, %8 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) - ret i64 %10 - -continue__3: ; preds = %continue__2 - %11 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__H, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %12 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %11) - store i64 %12, i64* %res, align 4 - %13 = icmp ne i64 %12, 0 - br i1 %13, label %then0__4, label %continue__4 - -then0__4: ; preds = %continue__3 - %14 = add i64 30, %12 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) - ret i64 %14 - -continue__4: ; preds = %continue__3 - %15 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__S, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %16 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %15) - store i64 %16, i64* %res, align 4 - %17 = icmp ne i64 %16, 0 - br i1 %17, label %then0__5, label %continue__5 - -then0__5: ; preds = %continue__4 - %18 = add i64 40, %16 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) - ret i64 %18 - -continue__5: ; preds = %continue__4 - %19 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__T, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %20 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %19) - store i64 %20, i64* %res, align 4 - %21 = icmp ne i64 %20, 0 - br i1 %21, label %then0__6, label %continue__6 - -then0__6: ; preds = %continue__5 - %22 = add i64 50, %20 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) - ret i64 %22 - -continue__6: ; preds = %continue__5 - %23 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Callable*, i2, double }* getelementptr ({ %Callable*, i2, double }, { %Callable*, i2, double }* null, i32 1) to i64)) - %24 = bitcast %Tuple* %23 to { %Callable*, i2, double }* - %25 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %24, i32 0, i32 0 - %26 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %24, i32 0, i32 1 - %27 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %24, i32 0, i32 2 - %28 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__R, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %29 = load i2, i2* @PauliX, align 1 - store %Callable* %28, %Callable** %25, align 8 - store i2 %29, i2* %26, align 1 - store double 4.200000e-01, double* %27, align 8 - %30 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__1, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %23) - %31 = call i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %30) - store i64 %31, i64* %res, align 4 - %32 = icmp ne i64 %31, 0 - br i1 %32, label %then0__7, label %continue__7 - -then0__7: ; preds = %continue__6 - %33 = add i64 60, %31 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %30, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %30, i32 -1) - ret i64 %33 - -continue__7: ; preds = %continue__6 - %targets = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) - %ctls = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %paulis = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) - %34 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %35 = bitcast i8* %34 to i2* - %36 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %37 = bitcast i8* %36 to i2* - %38 = load i2, i2* @PauliX, align 1 - %39 = load i2, i2* @PauliY, align 1 - store i2 %38, i2* %35, align 1 - store i2 %39, i2* %37, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) - call void @__quantum__qis__exp__body(%Array* %paulis, double 4.200000e-01, %Array* %targets) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %paulis, i32 -1) - %paulis__1 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) - %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__1, i64 0) - %41 = bitcast i8* %40 to i2* - %42 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__1, i64 1) - %43 = bitcast i8* %42 to i2* - %44 = load i2, i2* @PauliX, align 1 - %45 = load i2, i2* @PauliY, align 1 - store i2 %44, i2* %41, align 1 - store i2 %45, i2* %43, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis__1, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) - call void @__quantum__qis__exp__adj(%Array* %paulis__1, double 4.200000e-01, %Array* %targets) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis__1, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %paulis__1, i32 -1) - %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %targets, i64 0) - %47 = bitcast i8* %46 to %Qubit** - %48 = load %Qubit*, %Qubit** %47, align 8 - %49 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %48) - %50 = call %Result* @__quantum__rt__result_get_zero() - %51 = call i1 @__quantum__rt__result_equal(%Result* %49, %Result* %50) - %52 = xor i1 %51, true - br i1 %52, label %then0__8, label %continue__8 - -then0__8: ; preds = %continue__7 - store i64 1, i64* %res, align 4 - br label %continue__8 - -continue__8: ; preds = %then0__8, %continue__7 - %53 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %54 = bitcast i8* %53 to %Qubit** - %qubit = load %Qubit*, %Qubit** %54, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit) - %55 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) - %56 = bitcast i8* %55 to %Qubit** - %qubit__1 = load %Qubit*, %Qubit** %56, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %paulis__2 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) - %57 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__2, i64 0) - %58 = bitcast i8* %57 to i2* - %59 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__2, i64 1) - %60 = bitcast i8* %59 to i2* - %61 = load i2, i2* @PauliX, align 1 - %62 = load i2, i2* @PauliY, align 1 - store i2 %61, i2* %58, align 1 - store i2 %62, i2* %60, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis__2, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) - %63 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) - %64 = bitcast %Tuple* %63 to { %Array*, double, %Array* }* - %65 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %64, i32 0, i32 0 - %66 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %64, i32 0, i32 1 - %67 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %64, i32 0, i32 2 - store %Array* %paulis__2, %Array** %65, align 8 - store double 4.200000e-01, double* %66, align 8 - store %Array* %targets, %Array** %67, align 8 - call void @__quantum__qis__exp__ctl(%Array* %ctls, { %Array*, double, %Array* }* %64) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis__2, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %paulis__2, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %63, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %paulis__3 = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) - %68 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__3, i64 0) - %69 = bitcast i8* %68 to i2* - %70 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis__3, i64 1) - %71 = bitcast i8* %70 to i2* - %72 = load i2, i2* @PauliX, align 1 - %73 = load i2, i2* @PauliY, align 1 - store i2 %72, i2* %69, align 1 - store i2 %73, i2* %71, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis__3, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 1) - %74 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) - %75 = bitcast %Tuple* %74 to { %Array*, double, %Array* }* - %76 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %75, i32 0, i32 0 - %77 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %75, i32 0, i32 1 - %78 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %75, i32 0, i32 2 - store %Array* %paulis__3, %Array** %76, align 8 - store double 4.200000e-01, double* %77, align 8 - store %Array* %targets, %Array** %78, align 8 - call void @__quantum__qis__exp__ctladj(%Array* %ctls, { %Array*, double, %Array* }* %75) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis__3, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %paulis__3, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %74, i32 -1) - %79 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %80 = bitcast i8* %79 to %Qubit** - %qubit__2 = load %Qubit*, %Qubit** %80, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__2) - %81 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) - %82 = bitcast i8* %81 to %Qubit** - %qubit__3 = load %Qubit*, %Qubit** %82, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__3) - %83 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %targets, i64 0) - %84 = bitcast i8* %83 to %Qubit** - %85 = load %Qubit*, %Qubit** %84, align 8 - %86 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %85) - %87 = call %Result* @__quantum__rt__result_get_zero() - %88 = call i1 @__quantum__rt__result_equal(%Result* %86, %Result* %87) - %89 = xor i1 %88, true - br i1 %89, label %then0__9, label %continue__9 - -then0__9: ; preds = %continue__8 - store i64 2, i64* %res, align 4 - br label %continue__9 - -continue__9: ; preds = %then0__9, %continue__8 - call void @__quantum__rt__array_update_alias_count(%Array* %targets, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %49, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %86, i32 -1) - call void @__quantum__rt__qubit_release_array(%Array* %targets) - call void @__quantum__rt__qubit_release_array(%Array* %ctls) - %90 = load i64, i64* %res, align 4 - %91 = icmp ne i64 %90, 0 - br i1 %91, label %then0__10, label %continue__10 - -then0__10: ; preds = %continue__9 - %92 = add i64 70, %90 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %30, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %30, i32 -1) - ret i64 %92 - -continue__10: ; preds = %continue__9 - %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 3) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) - %93 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %94 = bitcast i8* %93 to %Qubit** - %qubit__4 = load %Qubit*, %Qubit** %94, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__4) - %95 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %96 = bitcast i8* %95 to %Qubit** - %qubit__5 = load %Qubit*, %Qubit** %96, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__5) - %bases = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 3) - %97 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 0) - %98 = bitcast i8* %97 to i2* - %99 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 1) - %100 = bitcast i8* %99 to i2* - %101 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 2) - %102 = bitcast i8* %101 to i2* - %103 = load i2, i2* @PauliX, align 1 - %104 = load i2, i2* @PauliZ, align 1 - %105 = load i2, i2* @PauliX, align 1 - store i2 %103, i2* %98, align 1 - store i2 %104, i2* %100, align 1 - store i2 %105, i2* %102, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) - %106 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qs) - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %bases, i32 -1) - %107 = call %Result* @__quantum__rt__result_get_zero() - %108 = call i1 @__quantum__rt__result_equal(%Result* %106, %Result* %107) - %109 = xor i1 %108, true - br i1 %109, label %then0__11, label %continue__11 - -then0__11: ; preds = %continue__10 - store i64 80, i64* %res, align 4 - br label %continue__11 - -continue__11: ; preds = %then0__11, %continue__10 - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %106, i32 -1) - call void @__quantum__rt__qubit_release_array(%Array* %qs) - %110 = load i64, i64* %res, align 4 - call void @__quantum__rt__capture_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %7, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %11, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %19, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %30, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %30, i32 -1) - ret i64 %110 -} - -define i64 @Microsoft__Quantum__Testing__QIR__InvokeAllVariants__body(%Callable* %op) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 1) - %res = alloca i64, align 8 - store i64 0, i64* %res, align 4 - %target = call %Qubit* @__quantum__rt__qubit_allocate() - %ctls = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) - %1 = bitcast %Tuple* %0 to { %Qubit* }* - %2 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %1, i32 0, i32 0 - store %Qubit* %target, %Qubit** %2, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %op, %Tuple* %0, %Tuple* null) - %3 = call %Callable* @__quantum__rt__callable_copy(%Callable* %op, i1 false) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 1) - call void @__quantum__rt__callable_make_adjoint(%Callable* %3) - %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) - %5 = bitcast %Tuple* %4 to { %Qubit* }* - %6 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %5, i32 0, i32 0 - store %Qubit* %target, %Qubit** %6, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %3, %Tuple* %4, %Tuple* null) - %7 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %target) - %8 = call %Result* @__quantum__rt__result_get_zero() - %9 = call i1 @__quantum__rt__result_equal(%Result* %7, %Result* %8) - %10 = xor i1 %9, true - br i1 %10, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - store i64 1, i64* %res, align 4 - br label %continue__1 - -else__1: ; preds = %entry - %11 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %12 = bitcast i8* %11 to %Qubit** - %qubit = load %Qubit*, %Qubit** %12, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit) - %13 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) - %14 = bitcast i8* %13 to %Qubit** - %qubit__1 = load %Qubit*, %Qubit** %14, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__1) - %15 = call %Callable* @__quantum__rt__callable_copy(%Callable* %op, i1 false) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 1) - call void @__quantum__rt__callable_make_controlled(%Callable* %15) - %16 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) - %17 = bitcast %Tuple* %16 to { %Array*, %Qubit* }* - %18 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %17, i32 0, i32 0 - %19 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %17, i32 0, i32 1 - store %Array* %ctls, %Array** %18, align 8 - store %Qubit* %target, %Qubit** %19, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %15, %Tuple* %16, %Tuple* null) - %20 = call %Callable* @__quantum__rt__callable_copy(%Callable* %op, i1 false) - call void @__quantum__rt__capture_update_reference_count(%Callable* %20, i32 1) - call void @__quantum__rt__callable_make_controlled(%Callable* %20) - call void @__quantum__rt__callable_make_adjoint(%Callable* %20) - %21 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) - %22 = bitcast %Tuple* %21 to { %Array*, %Qubit* }* - %23 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %22, i32 0, i32 0 - %24 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %22, i32 0, i32 1 - store %Array* %ctls, %Array** %23, align 8 - store %Qubit* %target, %Qubit** %24, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %20, %Tuple* %21, %Tuple* null) - %25 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %target) - %26 = call %Result* @__quantum__rt__result_get_zero() - %27 = call i1 @__quantum__rt__result_equal(%Result* %25, %Result* %26) - %28 = xor i1 %27, true - br i1 %28, label %then0__2, label %else__2 - -then0__2: ; preds = %else__1 - store i64 2, i64* %res, align 4 - br label %continue__2 - -else__2: ; preds = %else__1 - %29 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %30 = bitcast i8* %29 to %Qubit** - %qubit__2 = load %Qubit*, %Qubit** %30, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__2) - %31 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 1) - %32 = bitcast i8* %31 to %Qubit** - %qubit__3 = load %Qubit*, %Qubit** %32, align 8 - call void @__quantum__qis__h__body(%Qubit* %qubit__3) - br label %continue__2 - -continue__2: ; preds = %else__2, %then0__2 - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %16, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %20, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %20, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %21, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %25, i32 -1) - br label %continue__1 - -continue__1: ; preds = %continue__2, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %0, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %3, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %7, i32 -1) - call void @__quantum__rt__qubit_release(%Qubit* %target) - call void @__quantum__rt__qubit_release_array(%Array* %ctls) - %33 = load i64, i64* %res, align 4 - call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 -1) - ret i64 %33 -} - -define void @Microsoft__Quantum__Intrinsic__X__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i32)*]*, %Tuple*) - -declare void @__quantum__rt__capture_update_reference_count(%Callable*, i32) - -declare void @__quantum__rt__callable_update_reference_count(%Callable*, i32) - -define void @Microsoft__Quantum__Intrinsic__Y__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__T__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__T__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__T__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__T__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -declare %Tuple* @__quantum__rt__tuple_create(i64) - -define void @Microsoft__Quantum__Intrinsic__R__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { i2, double, %Qubit* }* - %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 - %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 - %4 = load i2, i2* %1, align 1 - %5 = load double, double* %2, align 8 - %6 = load %Qubit*, %Qubit** %3, align 8 - call void @Microsoft__Quantum__Intrinsic__R__body(i2 %4, double %5, %Qubit* %6) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__R__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { i2, double, %Qubit* }* - %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 - %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 - %4 = load i2, i2* %1, align 1 - %5 = load double, double* %2, align 8 - %6 = load %Qubit*, %Qubit** %3, align 8 - call void @Microsoft__Quantum__Intrinsic__R__adj(i2 %4, double %5, %Qubit* %6) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__R__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, { i2, double, %Qubit* }* }* - %1 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load { i2, double, %Qubit* }*, { i2, double, %Qubit* }** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__R__ctl(%Array* %3, { i2, double, %Qubit* }* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__R__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, { i2, double, %Qubit* }* }* - %1 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load { i2, double, %Qubit* }*, { i2, double, %Qubit* }** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__R__ctladj(%Array* %3, { i2, double, %Qubit* }* %4) - ret void -} - -define void @Lifted__PartialApplication__1__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* - %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 1 - %2 = load i2, i2* %1, align 1 - %3 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 2 - %4 = load double, double* %3, align 8 - %5 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %6 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %5, i32 0, i32 0 - %7 = load %Qubit*, %Qubit** %6, align 8 - %8 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) - %9 = bitcast %Tuple* %8 to { i2, double, %Qubit* }* - %10 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 0 - %11 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 1 - %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 2 - store i2 %2, i2* %10, align 1 - store double %4, double* %11, align 8 - store %Qubit* %7, %Qubit** %12, align 8 - %13 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 - %14 = load %Callable*, %Callable** %13, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) - ret void -} - -define void @Lifted__PartialApplication__1__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* - %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 1 - %2 = load i2, i2* %1, align 1 - %3 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 2 - %4 = load double, double* %3, align 8 - %5 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %6 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %5, i32 0, i32 0 - %7 = load %Qubit*, %Qubit** %6, align 8 - %8 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) - %9 = bitcast %Tuple* %8 to { i2, double, %Qubit* }* - %10 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 0 - %11 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 1 - %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %9, i32 0, i32 2 - store i2 %2, i2* %10, align 1 - store double %4, double* %11, align 8 - store %Qubit* %7, %Qubit** %12, align 8 - %13 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 - %14 = load %Callable*, %Callable** %13, align 8 - %15 = call %Callable* @__quantum__rt__callable_copy(%Callable* %14, i1 false) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 1) - call void @__quantum__rt__callable_make_adjoint(%Callable* %15) - call void @__quantum__rt__callable_invoke(%Callable* %15, %Tuple* %8, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %15, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %15, i32 -1) - ret void -} - -define void @Lifted__PartialApplication__1__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - %5 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* - %6 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 1 - %7 = load i2, i2* %6, align 1 - %8 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 2 - %9 = load double, double* %8, align 8 - %10 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) - %11 = bitcast %Tuple* %10 to { i2, double, %Qubit* }* - %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 0 - %13 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 1 - %14 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 2 - store i2 %7, i2* %12, align 1 - store double %9, double* %13, align 8 - store %Qubit* %4, %Qubit** %14, align 8 - %15 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) - %16 = bitcast %Tuple* %15 to { %Array*, { i2, double, %Qubit* }* }* - %17 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 0 - %18 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 1 - store %Array* %3, %Array** %17, align 8 - store { i2, double, %Qubit* }* %11, { i2, double, %Qubit* }** %18, align 8 - %19 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 0 - %20 = load %Callable*, %Callable** %19, align 8 - %21 = call %Callable* @__quantum__rt__callable_copy(%Callable* %20, i1 false) - call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 1) - call void @__quantum__rt__callable_make_controlled(%Callable* %21) - call void @__quantum__rt__callable_invoke(%Callable* %21, %Tuple* %15, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %10, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %15, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %21, i32 -1) - ret void -} - -define void @Lifted__PartialApplication__1__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - %5 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* - %6 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 1 - %7 = load i2, i2* %6, align 1 - %8 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 2 - %9 = load double, double* %8, align 8 - %10 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) - %11 = bitcast %Tuple* %10 to { i2, double, %Qubit* }* - %12 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 0 - %13 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 1 - %14 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %11, i32 0, i32 2 - store i2 %7, i2* %12, align 1 - store double %9, double* %13, align 8 - store %Qubit* %4, %Qubit** %14, align 8 - %15 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) - %16 = bitcast %Tuple* %15 to { %Array*, { i2, double, %Qubit* }* }* - %17 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 0 - %18 = getelementptr inbounds { %Array*, { i2, double, %Qubit* }* }, { %Array*, { i2, double, %Qubit* }* }* %16, i32 0, i32 1 - store %Array* %3, %Array** %17, align 8 - store { i2, double, %Qubit* }* %11, { i2, double, %Qubit* }** %18, align 8 - %19 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %5, i32 0, i32 0 - %20 = load %Callable*, %Callable** %19, align 8 - %21 = call %Callable* @__quantum__rt__callable_copy(%Callable* %20, i1 false) - call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 1) - call void @__quantum__rt__callable_make_adjoint(%Callable* %21) - call void @__quantum__rt__callable_make_controlled(%Callable* %21) - call void @__quantum__rt__callable_invoke(%Callable* %21, %Tuple* %15, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %10, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %15, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %21, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %21, i32 -1) - ret void -} - -define void @MemoryManagement__1__RefCount(%Tuple* %capture-tuple, i32 %count-change) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* - %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 - %2 = load %Callable*, %Callable** %1, align 8 - call void @__quantum__rt__capture_update_reference_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i32 %count-change) - ret void -} - -define void @MemoryManagement__1__AliasCount(%Tuple* %capture-tuple, i32 %count-change) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, i2, double }* - %1 = getelementptr inbounds { %Callable*, i2, double }, { %Callable*, i2, double }* %0, i32 0, i32 0 - %2 = load %Callable*, %Callable** %1, align 8 - call void @__quantum__rt__capture_update_alias_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i32 %count-change) - ret void -} - -declare %Qubit* @__quantum__rt__qubit_allocate() - -declare %Array* @__quantum__rt__qubit_allocate_array(i64) - -declare void @__quantum__rt__array_update_alias_count(%Array*, i32) - -declare %Array* @__quantum__rt__array_create_1d(i32, i64) - -declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) - -declare void @__quantum__qis__exp__body(%Array*, double, %Array*) - -declare void @__quantum__rt__array_update_reference_count(%Array*, i32) - -declare void @__quantum__qis__exp__adj(%Array*, double, %Array*) - -define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qubit) { -entry: - %bases = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 0) - %1 = bitcast i8* %0 to i2* - %2 = load i2, i2* @PauliZ, align 1 - store i2 %2, i2* %1, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) - %qubits = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %3 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) - %4 = bitcast i8* %3 to %Qubit** - store %Qubit* %qubit, %Qubit** %4, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %5 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %bases, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %qubits, i32 -1) - ret %Result* %5 -} - -declare %Result* @__quantum__rt__result_get_zero() - -declare i1 @__quantum__rt__result_equal(%Result*, %Result*) - -declare void @__quantum__qis__h__body(%Qubit*) - -declare void @__quantum__qis__exp__ctl(%Array*, { %Array*, double, %Array* }*) - -declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i32) - -declare void @__quantum__qis__exp__ctladj(%Array*, { %Array*, double, %Array* }*) - -declare void @__quantum__rt__result_update_reference_count(%Result*, i32) - -declare void @__quantum__rt__qubit_release_array(%Array*) - -declare %Result* @__quantum__qis__measure__body(%Array*, %Array*) - -declare void @__quantum__rt__capture_update_alias_count(%Callable*, i32) - -declare void @__quantum__rt__callable_update_alias_count(%Callable*, i32) - -declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*) - -declare %Callable* @__quantum__rt__callable_copy(%Callable*, i1) - -declare void @__quantum__rt__callable_make_adjoint(%Callable*) - -declare void @__quantum__rt__callable_make_controlled(%Callable*) - -declare void @__quantum__rt__qubit_release(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__Exp__body(%Array* %paulis, double %theta, %Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - call void @__quantum__qis__exp__body(%Array* %paulis, double %theta, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Exp__adj(%Array* %paulis, double %theta, %Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - call void @__quantum__qis__exp__adj(%Array* %paulis, double %theta, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Exp__ctl(%Array* %__controlQubits__, { %Array*, double, %Array* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %1 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 0 - %paulis = load %Array*, %Array** %1, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) - %2 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 1 - %theta = load double, double* %2, align 8 - %3 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 2 - %qubits = load %Array*, %Array** %3, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) - %5 = bitcast %Tuple* %4 to { %Array*, double, %Array* }* - %6 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 0 - %7 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 1 - %8 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 2 - store %Array* %paulis, %Array** %6, align 8 - store double %theta, double* %7, align 8 - store %Array* %qubits, %Array** %8, align 8 - call void @__quantum__qis__exp__ctl(%Array* %__controlQubits__, { %Array*, double, %Array* }* %5) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Exp__ctladj(%Array* %__controlQubits__, { %Array*, double, %Array* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %1 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 0 - %paulis = load %Array*, %Array** %1, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) - %2 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 1 - %theta = load double, double* %2, align 8 - %3 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %0, i32 0, i32 2 - %qubits = load %Array*, %Array** %3, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ %Array*, double, %Array* }* getelementptr ({ %Array*, double, %Array* }, { %Array*, double, %Array* }* null, i32 1) to i64)) - %5 = bitcast %Tuple* %4 to { %Array*, double, %Array* }* - %6 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 0 - %7 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 1 - %8 = getelementptr inbounds { %Array*, double, %Array* }, { %Array*, double, %Array* }* %5, i32 0, i32 2 - store %Array* %paulis, %Array** %6, align 8 - store double %theta, double* %7, align 8 - store %Array* %qubits, %Array** %8, align 8 - call void @__quantum__qis__exp__ctladj(%Array* %__controlQubits__, { %Array*, double, %Array* }* %5) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__body(%Qubit* %qubit) { -entry: - call void @__quantum__qis__t__body(%Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__t__body(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__T__adj(%Qubit* %qubit) { -entry: - call void @__quantum__qis__t__adj(%Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__t__adj(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__T__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__t__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__t__ctl(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__T__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__t__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__t__ctladj(%Array*, %Qubit*) - -define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %bases, %Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %0 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret %Result* %0 -} - -define void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %qubit) { -entry: - call void @__quantum__qis__z__body(%Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__z__body(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %qubit) { -entry: - call void @__quantum__qis__z__body(%Qubit* %qubit) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__z__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__z__ctl(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__z__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %qubit) { -entry: - call void @__quantum__qis__x__body(%Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__x__body(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %qubit) { -entry: - call void @__quantum__qis__x__body(%Qubit* %qubit) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__x__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__x__ctl(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__x__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qubit) { -entry: - call void @__quantum__qis__h__body(%Qubit* %qubit) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qubit) { -entry: - call void @__quantum__qis__h__body(%Qubit* %qubit) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__h__ctl(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %qubit) { -entry: - call void @__quantum__qis__s__body(%Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__s__body(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %qubit) { -entry: - call void @__quantum__qis__s__adj(%Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__s__adj(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__s__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__s__ctl(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__s__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__s__ctladj(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__R__body(i2 %pauli, double %theta, %Qubit* %qubit) { -entry: - call void @__quantum__qis__r__body(i2 %pauli, double %theta, %Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__r__body(i2, double, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__R__adj(i2 %pauli, double %theta, %Qubit* %qubit) { -entry: - call void @__quantum__qis__r__adj(i2 %pauli, double %theta, %Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__r__adj(i2, double, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__R__ctl(%Array* %__controlQubits__, { i2, double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 - %pauli = load i2, i2* %1, align 1 - %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 - %theta = load double, double* %2, align 8 - %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 - %qubit = load %Qubit*, %Qubit** %3, align 8 - %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) - %5 = bitcast %Tuple* %4 to { i2, double, %Qubit* }* - %6 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 0 - %7 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 1 - %8 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 2 - store i2 %pauli, i2* %6, align 1 - store double %theta, double* %7, align 8 - store %Qubit* %qubit, %Qubit** %8, align 8 - call void @__quantum__qis__r__ctl(%Array* %__controlQubits__, { i2, double, %Qubit* }* %5) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) - ret void -} - -declare void @__quantum__qis__r__ctl(%Array*, { i2, double, %Qubit* }*) - -define void @Microsoft__Quantum__Intrinsic__R__ctladj(%Array* %__controlQubits__, { i2, double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %1 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 0 - %pauli = load i2, i2* %1, align 1 - %2 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 1 - %theta = load double, double* %2, align 8 - %3 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %0, i32 0, i32 2 - %qubit = load %Qubit*, %Qubit** %3, align 8 - %4 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint ({ i2, double, %Qubit* }* getelementptr ({ i2, double, %Qubit* }, { i2, double, %Qubit* }* null, i32 1) to i64)) - %5 = bitcast %Tuple* %4 to { i2, double, %Qubit* }* - %6 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 0 - %7 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 1 - %8 = getelementptr inbounds { i2, double, %Qubit* }, { i2, double, %Qubit* }* %5, i32 0, i32 2 - store i2 %pauli, i2* %6, align 1 - store double %theta, double* %7, align 8 - store %Qubit* %qubit, %Qubit** %8, align 8 - call void @__quantum__qis__r__ctladj(%Array* %__controlQubits__, { i2, double, %Qubit* }* %5) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %4, i32 -1) - ret void -} - -declare void @__quantum__qis__r__ctladj(%Array*, { i2, double, %Qubit* }*) - -define void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %qubit) { -entry: - call void @__quantum__qis__y__body(%Qubit* %qubit) - ret void -} - -declare void @__quantum__qis__y__body(%Qubit*) - -define void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %qubit) { -entry: - call void @__quantum__qis__y__body(%Qubit* %qubit) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__y__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__y__ctl(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__y__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS() #1 { -entry: - %0 = call i64 @Microsoft__Quantum__Testing__QIR__Test_Simulator_QIS__body() - %1 = call %String* @__quantum__rt__int_to_string(i64 %0) - call void @__quantum__rt__message(%String* %1) - call void @__quantum__rt__string_update_reference_count(%String* %1, i32 -1) - ret void -} - -declare void @__quantum__rt__message(%String*) - -declare %String* @__quantum__rt__int_to_string(i64) - -declare void @__quantum__rt__string_update_reference_count(%String*, i32) - -declare void @__quantum__rt__tuple_update_alias_count(%Tuple*, i32) - -attributes #0 = { "InteropFriendly" } -attributes #1 = { "EntryPoint" } diff --git a/src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll b/src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll deleted file mode 100644 index 227d27613fc..00000000000 --- a/src/QirRuntime/test/QIR-dynamic/qsharp/qir/qir-test-random.ll +++ /dev/null @@ -1,159 +0,0 @@ - -%Range = type { i64, i64, i64 } -%Qubit = type opaque -%Result = type opaque -%Array = type opaque -%String = type opaque - -@PauliI = constant i2 0 -@PauliX = constant i2 1 -@PauliY = constant i2 -1 -@PauliZ = constant i2 -2 -@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } - -@Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__Interop = alias i64 (), i64 ()* @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__body - -define i64 @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__body() #0 { -entry: - %randomNumber = alloca i64, align 8 - store i64 0, i64* %randomNumber, align 4 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %i = phi i64 [ 1, %entry ], [ %8, %exiting__1 ] - %0 = icmp sle i64 %i, 64 - br i1 %0, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %q = call %Qubit* @__quantum__rt__qubit_allocate() - call void @__quantum__qis__h__body(%Qubit* %q) - %1 = load i64, i64* %randomNumber, align 4 - %2 = shl i64 %1, 1 - store i64 %2, i64* %randomNumber, align 4 - %3 = call %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %q) - %4 = call %Result* @__quantum__rt__result_get_one() - %5 = call i1 @__quantum__rt__result_equal(%Result* %3, %Result* %4) - br i1 %5, label %then0__1, label %continue__1 - -then0__1: ; preds = %body__1 - %6 = load i64, i64* %randomNumber, align 4 - %7 = add i64 %6, 1 - store i64 %7, i64* %randomNumber, align 4 - br label %continue__1 - -continue__1: ; preds = %then0__1, %body__1 - call void @__quantum__rt__result_update_reference_count(%Result* %3, i32 -1) - call void @__quantum__rt__qubit_release(%Qubit* %q) - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %8 = add i64 %i, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %9 = load i64, i64* %randomNumber, align 4 - ret i64 %9 -} - -declare %Qubit* @__quantum__rt__qubit_allocate() - -declare %Array* @__quantum__rt__qubit_allocate_array(i64) - -declare void @__quantum__qis__h__body(%Qubit*) - -define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qubit) { -entry: - %bases = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %bases, i64 0) - %1 = bitcast i8* %0 to i2* - %2 = load i2, i2* @PauliZ, align 1 - store i2 %2, i2* %1, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) - %qubits = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %3 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) - %4 = bitcast i8* %3 to %Qubit** - store %Qubit* %qubit, %Qubit** %4, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %5 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %bases, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %qubits, i32 -1) - ret %Result* %5 -} - -declare %Result* @__quantum__rt__result_get_one() - -declare i1 @__quantum__rt__result_equal(%Result*, %Result*) - -declare void @__quantum__rt__result_update_reference_count(%Result*, i32) - -declare void @__quantum__rt__qubit_release(%Qubit*) - -declare %Array* @__quantum__rt__array_create_1d(i32, i64) - -declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) - -declare void @__quantum__rt__array_update_alias_count(%Array*, i32) - -declare %Result* @__quantum__qis__measure__body(%Array*, %Array*) - -declare void @__quantum__rt__array_update_reference_count(%Array*, i32) - -define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %bases, %Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %0 = call %Result* @__quantum__qis__measure__body(%Array* %bases, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %bases, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret %Result* %0 -} - -define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qubit) { -entry: - call void @__quantum__qis__h__body(%Qubit* %qubit) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qubit) { -entry: - call void @__quantum__qis__h__body(%Qubit* %qubit) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -declare void @__quantum__qis__h__ctl(%Array*, %Qubit*) - -define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qubit) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__h__ctl(%Array* %__controlQubits__, %Qubit* %qubit) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator() #1 { -entry: - %0 = call i64 @Microsoft__Quantum__Testing__QIR__QuantumRandomNumberGenerator__body() - %1 = call %String* @__quantum__rt__int_to_string(i64 %0) - call void @__quantum__rt__message(%String* %1) - call void @__quantum__rt__string_update_reference_count(%String* %1, i32 -1) - ret void -} - -declare void @__quantum__rt__message(%String*) - -declare %String* @__quantum__rt__int_to_string(i64) - -declare void @__quantum__rt__string_update_reference_count(%String*, i32) - -attributes #0 = { "InteropFriendly" } -attributes #1 = { "EntryPoint" } diff --git a/src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll b/src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll deleted file mode 100644 index 31a343b650f..00000000000 --- a/src/QirRuntime/test/QIR-tracer/qsharp/qir/tracer-qir.ll +++ /dev/null @@ -1,2080 +0,0 @@ - -%Range = type { i64, i64, i64 } -%Tuple = type opaque -%Result = type opaque -%Qubit = type opaque -%Array = type opaque -%Callable = type opaque -%String = type opaque - -@PauliI = constant i2 0 -@PauliX = constant i2 1 -@PauliY = constant i2 -1 -@PauliZ = constant i2 -2 -@EmptyRange = internal constant %Range { i64 0, i64 1, i64 -1 } -@Microsoft__Quantum__Testing__Tracer__Delay = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Testing__Tracer__Delay__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@Microsoft__Quantum__Intrinsic__X = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper] -@PartialApplication__1 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__1__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@MemoryManagement__1 = constant [2 x void (%Tuple*, i32)*] [void (%Tuple*, i32)* @MemoryManagement__1__RefCount, void (%Tuple*, i32)* @MemoryManagement__1__AliasCount] -@Microsoft__Quantum__Intrinsic__Y = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper] -@PartialApplication__2 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__2__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@Microsoft__Quantum__Intrinsic__Z = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper] -@PartialApplication__3 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__3__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@Microsoft__Quantum__Intrinsic__S = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__adj__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctl__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper] -@PartialApplication__4 = constant [4 x void (%Tuple*, %Tuple*, %Tuple*)*] [void (%Tuple*, %Tuple*, %Tuple*)* @Lifted__PartialApplication__4__body__wrapper, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null, void (%Tuple*, %Tuple*, %Tuple*)* null] -@MemoryManagement__2 = constant [2 x void (%Tuple*, i32)*] [void (%Tuple*, i32)* @MemoryManagement__2__RefCount, void (%Tuple*, i32)* @MemoryManagement__2__AliasCount] - -define %Result* @Microsoft__Quantum__Instructions__Mx__body(%Qubit* %qb) { -entry: - %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb) - ret %Result* %0 -} - -declare %Result* @__quantum__qis__single_qubit_measure(i64, i64, %Qubit*) - -define %Result* @Microsoft__Quantum__Instructions__Mxx__body(%Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret %Result* %0 -} - -declare void @__quantum__rt__array_update_alias_count(%Array*, i32) - -declare %Result* @__quantum__qis__joint_measure(i64, i64, %Array*) - -define %Result* @Microsoft__Quantum__Instructions__Mxz__body(%Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret %Result* %0 -} - -define %Result* @Microsoft__Quantum__Instructions__Mz__body(%Qubit* %qb) { -entry: - %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) - ret %Result* %0 -} - -define %Result* @Microsoft__Quantum__Instructions__Mzx__body(%Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret %Result* %0 -} - -define %Result* @Microsoft__Quantum__Instructions__Mzz__body(%Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %0 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret %Result* %0 -} - -define void @Microsoft__Quantum__Instructions__Sx__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) - ret void -} - -declare void @__quantum__qis__single_qubit_op(i64, i64, %Qubit*) - -define void @Microsoft__Quantum__Instructions__Sx__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 17, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Instructions__Sx__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -declare void @__quantum__qis__single_qubit_op_ctl(i64, i64, %Array*, %Qubit*) - -define void @Microsoft__Quantum__Instructions__Sx__ctladj(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 18, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Instructions__Sz__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Instructions__Sz__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Instructions__Sz__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Instructions__Sz__ctladj(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tx__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tx__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 13, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tx__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tx__ctladj(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 14, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tz__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tz__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tz__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Instructions__Tz__ctladj(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__ApplyConditionallyIntrinsic__body(%Array* %measurementResults, %Array* %resultsValues, %Callable* %onEqualOp, %Callable* %onNonEqualOp) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %measurementResults, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %resultsValues, i32 1) - call void @__quantum__rt__capture_update_alias_count(%Callable* %onEqualOp, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onEqualOp, i32 1) - call void @__quantum__rt__capture_update_alias_count(%Callable* %onNonEqualOp, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onNonEqualOp, i32 1) - call void @__quantum__qis__apply_conditionally(%Array* %measurementResults, %Array* %resultsValues, %Callable* %onEqualOp, %Callable* %onNonEqualOp) - call void @__quantum__rt__array_update_alias_count(%Array* %measurementResults, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %resultsValues, i32 -1) - call void @__quantum__rt__capture_update_alias_count(%Callable* %onEqualOp, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onEqualOp, i32 -1) - call void @__quantum__rt__capture_update_alias_count(%Callable* %onNonEqualOp, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onNonEqualOp, i32 -1) - ret void -} - -declare void @__quantum__rt__capture_update_alias_count(%Callable*, i32) - -declare void @__quantum__rt__callable_update_alias_count(%Callable*, i32) - -declare void @__quantum__qis__apply_conditionally(%Array*, %Array*, %Callable*, %Callable*) - -define void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %measurementResult, %Callable* %onResultZeroOp, %Callable* %onResultOneOp) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultZeroOp, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultZeroOp, i32 1) - call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultOneOp, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultOneOp, i32 1) - %0 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %1 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 0) - %2 = bitcast i8* %1 to %Result** - store %Result* %measurementResult, %Result** %2, align 8 - %3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 0) - %5 = bitcast i8* %4 to %Result** - %6 = call %Result* @__quantum__rt__result_get_zero() - store %Result* %6, %Result** %5, align 8 - call void @__quantum__qis__apply_conditionally(%Array* %0, %Array* %3, %Callable* %onResultZeroOp, %Callable* %onResultOneOp) - call void @__quantum__rt__result_update_reference_count(%Result* %measurementResult, i32 1) - call void @__quantum__rt__result_update_reference_count(%Result* %6, i32 1) - call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultZeroOp, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultZeroOp, i32 -1) - call void @__quantum__rt__capture_update_alias_count(%Callable* %onResultOneOp, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %onResultOneOp, i32 -1) - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %7 = phi i64 [ 0, %entry ], [ %12, %exiting__1 ] - %8 = icmp sle i64 %7, 0 - br i1 %8, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %0, i64 %7) - %10 = bitcast i8* %9 to %Result** - %11 = load %Result*, %Result** %10, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %11, i32 -1) - br label %exiting__1 - -exiting__1: ; preds = %body__1 - %12 = add i64 %7, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - call void @__quantum__rt__array_update_reference_count(%Array* %0, i32 -1) - br label %header__2 - -header__2: ; preds = %exiting__2, %exit__1 - %13 = phi i64 [ 0, %exit__1 ], [ %18, %exiting__2 ] - %14 = icmp sle i64 %13, 0 - br i1 %14, label %body__2, label %exit__2 - -body__2: ; preds = %header__2 - %15 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 %13) - %16 = bitcast i8* %15 to %Result** - %17 = load %Result*, %Result** %16, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %17, i32 -1) - br label %exiting__2 - -exiting__2: ; preds = %body__2 - %18 = add i64 %13, 1 - br label %header__2 - -exit__2: ; preds = %header__2 - call void @__quantum__rt__array_update_reference_count(%Array* %3, i32 -1) - ret void -} - -declare %Array* @__quantum__rt__array_create_1d(i32, i64) - -declare i8* @__quantum__rt__array_get_element_ptr_1d(%Array*, i64) - -declare %Result* @__quantum__rt__result_get_zero() - -declare void @__quantum__rt__result_update_reference_count(%Result*, i32) - -declare void @__quantum__rt__array_update_reference_count(%Array*, i32) - -define void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) { -entry: - %ctls = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %1 = bitcast i8* %0 to %Qubit** - store %Qubit* %control, %Qubit** %1, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - br i1 true, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %target) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %target) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %control, %Qubit* %target) { -entry: - call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %control, %Qubit* %target) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %ctls, { %Qubit*, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 - %control = load %Qubit*, %Qubit** %1, align 8 - %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 - %target = load %Qubit*, %Qubit** %2, align 8 - %3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %3, i64 0) - %5 = bitcast i8* %4 to %Qubit** - store %Qubit* %control, %Qubit** %5, align 8 - %ctls__1 = call %Array* @__quantum__rt__array_concatenate(%Array* %ctls, %Array* %3) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 1) - %6 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls__1) - %7 = icmp eq i64 %6, 1 - br i1 %7, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls__1, %Qubit* %target) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls__1, %Qubit* %target) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %3, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__1, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -declare %Array* @__quantum__rt__array_concatenate(%Array*, %Array*) - -declare i64 @__quantum__rt__array_get_size_1d(%Array*) - -define void @Microsoft__Quantum__Intrinsic__CNOT__ctladj(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %1 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 0 - %control = load %Qubit*, %Qubit** %1, align 8 - %2 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %0, i32 0, i32 1 - %target = load %Qubit*, %Qubit** %2, align 8 - %3 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 2)) - %4 = bitcast %Tuple* %3 to { %Qubit*, %Qubit* }* - %5 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %4, i32 0, i32 0 - %6 = getelementptr inbounds { %Qubit*, %Qubit* }, { %Qubit*, %Qubit* }* %4, i32 0, i32 1 - store %Qubit* %control, %Qubit** %5, align 8 - store %Qubit* %target, %Qubit** %6, align 8 - call void @Microsoft__Quantum__Intrinsic__CNOT__ctl(%Array* %__controlQubits__, { %Qubit*, %Qubit* }* %4) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %3, i32 -1) - ret void -} - -declare %Tuple* @__quantum__rt__tuple_create(i64) - -declare void @__quantum__rt__tuple_update_reference_count(%Tuple*, i32) - -define void @Microsoft__Quantum__Intrinsic__H__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__H__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define %Result* @Microsoft__Quantum__Intrinsic__M__body(%Qubit* %qb) { -entry: - %0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb) - ret %Result* %0 -} - -define %Result* @Microsoft__Quantum__Intrinsic__Measure__body(%Array* %paulis, %Array* %qubits) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %0 = call %Result* @__quantum__rt__result_get_one() - %res = alloca %Result*, align 8 - store %Result* %0, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %0, i32 1) - %haveY = alloca i1, align 1 - store i1 false, i1* %haveY, align 1 - %1 = call i64 @__quantum__rt__array_get_size_1d(%Array* %paulis) - %2 = sub i64 %1, 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %i = phi i64 [ 0, %entry ], [ %15, %exiting__1 ] - %3 = icmp sle i64 %i, %2 - br i1 %3, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %5 = bitcast i8* %4 to i2* - %6 = load i2, i2* %5, align 1 - %7 = load i2, i2* @PauliY, align 1 - %8 = icmp eq i2 %6, %7 - br i1 %8, label %condContinue__1, label %condFalse__1 - -condFalse__1: ; preds = %body__1 - %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %10 = bitcast i8* %9 to i2* - %11 = load i2, i2* %10, align 1 - %12 = load i2, i2* @PauliI, align 1 - %13 = icmp eq i2 %11, %12 - br label %condContinue__1 - -condContinue__1: ; preds = %condFalse__1, %body__1 - %14 = phi i1 [ %8, %body__1 ], [ %13, %condFalse__1 ] - br i1 %14, label %then0__1, label %continue__1 - -then0__1: ; preds = %condContinue__1 - store i1 true, i1* %haveY, align 1 - br label %continue__1 - -continue__1: ; preds = %then0__1, %condContinue__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %15 = add i64 %i, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %16 = load i1, i1* %haveY, align 1 - br i1 %16, label %then0__2, label %test1__1 - -then0__2: ; preds = %exit__1 - %17 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qubits) - call void @__quantum__rt__result_update_reference_count(%Result* %17, i32 1) - store %Result* %17, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %17, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %0, i32 -1) - br label %continue__2 - -test1__1: ; preds = %exit__1 - %18 = icmp sgt i64 %1, 2 - br i1 %18, label %then1__1, label %test2__1 - -then1__1: ; preds = %test1__1 - %19 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qubits) - call void @__quantum__rt__result_update_reference_count(%Result* %19, i32 1) - %20 = load %Result*, %Result** %res, align 8 - store %Result* %19, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %19, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %20, i32 -1) - br label %continue__2 - -test2__1: ; preds = %test1__1 - %21 = icmp eq i64 %1, 1 - br i1 %21, label %then2__1, label %test3__1 - -then2__1: ; preds = %test2__1 - %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %23 = bitcast i8* %22 to i2* - %24 = load i2, i2* %23, align 1 - %25 = load i2, i2* @PauliX, align 1 - %26 = icmp eq i2 %24, %25 - br i1 %26, label %then0__3, label %else__1 - -then0__3: ; preds = %then2__1 - %27 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) - %28 = bitcast i8* %27 to %Qubit** - %qb = load %Qubit*, %Qubit** %28, align 8 - %29 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb) - call void @__quantum__rt__result_update_reference_count(%Result* %29, i32 1) - %30 = load %Result*, %Result** %res, align 8 - store %Result* %29, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %29, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %30, i32 -1) - br label %continue__3 - -else__1: ; preds = %then2__1 - %31 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qubits, i64 0) - %32 = bitcast i8* %31 to %Qubit** - %qb__1 = load %Qubit*, %Qubit** %32, align 8 - %33 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__1) - call void @__quantum__rt__result_update_reference_count(%Result* %33, i32 1) - %34 = load %Result*, %Result** %res, align 8 - store %Result* %33, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %33, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %34, i32 -1) - br label %continue__3 - -continue__3: ; preds = %else__1, %then0__3 - br label %continue__2 - -test3__1: ; preds = %test2__1 - %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %36 = bitcast i8* %35 to i2* - %37 = load i2, i2* %36, align 1 - %38 = load i2, i2* @PauliX, align 1 - %39 = icmp eq i2 %37, %38 - br i1 %39, label %condTrue__1, label %condContinue__2 - -condTrue__1: ; preds = %test3__1 - %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %41 = bitcast i8* %40 to i2* - %42 = load i2, i2* %41, align 1 - %43 = load i2, i2* @PauliX, align 1 - %44 = icmp eq i2 %42, %43 - br label %condContinue__2 - -condContinue__2: ; preds = %condTrue__1, %test3__1 - %45 = phi i1 [ %44, %condTrue__1 ], [ %39, %test3__1 ] - br i1 %45, label %then3__1, label %test4__1 - -then3__1: ; preds = %condContinue__2 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %46 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %46, i32 1) - %47 = load %Result*, %Result** %res, align 8 - store %Result* %46, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %46, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %47, i32 -1) - br label %continue__2 - -test4__1: ; preds = %condContinue__2 - %48 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %49 = bitcast i8* %48 to i2* - %50 = load i2, i2* %49, align 1 - %51 = load i2, i2* @PauliX, align 1 - %52 = icmp eq i2 %50, %51 - br i1 %52, label %condTrue__2, label %condContinue__3 - -condTrue__2: ; preds = %test4__1 - %53 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %54 = bitcast i8* %53 to i2* - %55 = load i2, i2* %54, align 1 - %56 = load i2, i2* @PauliZ, align 1 - %57 = icmp eq i2 %55, %56 - br label %condContinue__3 - -condContinue__3: ; preds = %condTrue__2, %test4__1 - %58 = phi i1 [ %57, %condTrue__2 ], [ %52, %test4__1 ] - br i1 %58, label %then4__1, label %test5__1 - -then4__1: ; preds = %condContinue__3 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %59 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %59, i32 1) - %60 = load %Result*, %Result** %res, align 8 - store %Result* %59, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %59, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %60, i32 -1) - br label %continue__2 - -test5__1: ; preds = %condContinue__3 - %61 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %62 = bitcast i8* %61 to i2* - %63 = load i2, i2* %62, align 1 - %64 = load i2, i2* @PauliZ, align 1 - %65 = icmp eq i2 %63, %64 - br i1 %65, label %condTrue__3, label %condContinue__4 - -condTrue__3: ; preds = %test5__1 - %66 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %67 = bitcast i8* %66 to i2* - %68 = load i2, i2* %67, align 1 - %69 = load i2, i2* @PauliX, align 1 - %70 = icmp eq i2 %68, %69 - br label %condContinue__4 - -condContinue__4: ; preds = %condTrue__3, %test5__1 - %71 = phi i1 [ %70, %condTrue__3 ], [ %65, %test5__1 ] - br i1 %71, label %then5__1, label %test6__1 - -then5__1: ; preds = %condContinue__4 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %72 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %72, i32 1) - %73 = load %Result*, %Result** %res, align 8 - store %Result* %72, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %72, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %73, i32 -1) - br label %continue__2 - -test6__1: ; preds = %condContinue__4 - %74 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %75 = bitcast i8* %74 to i2* - %76 = load i2, i2* %75, align 1 - %77 = load i2, i2* @PauliZ, align 1 - %78 = icmp eq i2 %76, %77 - br i1 %78, label %condTrue__4, label %condContinue__5 - -condTrue__4: ; preds = %test6__1 - %79 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %80 = bitcast i8* %79 to i2* - %81 = load i2, i2* %80, align 1 - %82 = load i2, i2* @PauliZ, align 1 - %83 = icmp eq i2 %81, %82 - br label %condContinue__5 - -condContinue__5: ; preds = %condTrue__4, %test6__1 - %84 = phi i1 [ %83, %condTrue__4 ], [ %78, %test6__1 ] - br i1 %84, label %then6__1, label %continue__2 - -then6__1: ; preds = %condContinue__5 - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 1) - %85 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qubits) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %85, i32 1) - %86 = load %Result*, %Result** %res, align 8 - store %Result* %85, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %85, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %86, i32 -1) - br label %continue__2 - -continue__2: ; preds = %then6__1, %condContinue__5, %then5__1, %then4__1, %then3__1, %continue__3, %then1__1, %then0__2 - %87 = load %Result*, %Result** %res, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qubits, i32 -1) - ret %Result* %87 -} - -declare %Result* @__quantum__rt__result_get_one() - -define void @Microsoft__Quantum__Intrinsic__Rx__body(double %theta, %Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Rx__adj(double %theta, %Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Rx__ctl(%Array* %ctls, { double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 - %theta = load double, double* %1, align 8 - %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 - %qb = load %Qubit*, %Qubit** %2, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Rx__ctladj(%Array* %ctls, { double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 - %theta = load double, double* %1, align 8 - %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 - %qb = load %Qubit*, %Qubit** %2, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Ry__body(double %theta, %Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Ry__adj(double %theta, %Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Ry__ctl(%Array* %ctls, { double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 - %theta = load double, double* %1, align 8 - %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 - %qb = load %Qubit*, %Qubit** %2, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Ry__ctladj(%Array* %ctls, { double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 - %theta = load double, double* %1, align 8 - %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 - %qb = load %Qubit*, %Qubit** %2, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Rz__body(double %theta, %Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Rz__adj(double %theta, %Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Rz__ctl(%Array* %ctls, { double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 - %theta = load double, double* %1, align 8 - %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 - %qb = load %Qubit*, %Qubit** %2, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Rz__ctladj(%Array* %ctls, { double, %Qubit* }* %0) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %1 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 0 - %theta = load double, double* %1, align 8 - %2 = getelementptr inbounds { double, %Qubit* }, { double, %Qubit* }* %0, i32 0, i32 1 - %qb = load %Qubit*, %Qubit** %2, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__T__ctladj(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls, %Qubit* %qb) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %qb) { -entry: - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %ctls, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %ctls) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls, %Qubit* %qb) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %__controlQubits__, %Qubit* %qb) { -entry: - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 1) - %0 = call i64 @__quantum__rt__array_get_size_1d(%Array* %__controlQubits__) - %1 = icmp eq i64 %0, 1 - br i1 %1, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %__controlQubits__, %Qubit* %qb) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %__controlQubits__, i32 -1) - ret void -} - -define %Tuple* @Microsoft__Quantum__Core__Attribute__body() { -entry: - ret %Tuple* null -} - -define %Tuple* @Microsoft__Quantum__Core__EntryPoint__body() { -entry: - ret %Tuple* null -} - -define %Tuple* @Microsoft__Quantum__Core__Inline__body() { -entry: - ret %Tuple* null -} - -define void @Microsoft__Quantum__Testing__Tracer__Delay__body(%Callable* %op, %Qubit* %arg, %Tuple* %aux) { -entry: - call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 1) - %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) - %1 = bitcast %Tuple* %0 to { %Qubit* }* - %2 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %1, i32 0, i32 0 - store %Qubit* %arg, %Qubit** %2, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %op, %Tuple* %0, %Tuple* null) - call void @__quantum__rt__capture_update_alias_count(%Callable* %op, i32 -1) - call void @__quantum__rt__callable_update_alias_count(%Callable* %op, i32 -1) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %0, i32 -1) - ret void -} - -declare void @__quantum__rt__callable_invoke(%Callable*, %Tuple*, %Tuple*) - -define void @Microsoft__Quantum__Testing__Tracer__TestCoreIntrinsics__body() { -entry: - %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 3) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %1 = bitcast i8* %0 to %Qubit** - %qb = load %Qubit*, %Qubit** %1, align 8 - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb) - %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %3 = bitcast i8* %2 to %Qubit** - %qb__1 = load %Qubit*, %Qubit** %3, align 8 - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__1) - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %5 = bitcast i8* %4 to %Qubit** - %qb__2 = load %Qubit*, %Qubit** %5, align 8 - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__2) - %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %7 = bitcast i8* %6 to %Qubit** - %qb__3 = load %Qubit*, %Qubit** %7, align 8 - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__3) - %8 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %9 = bitcast i8* %8 to %Qubit** - %10 = load %Qubit*, %Qubit** %9, align 8 - %11 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %12 = bitcast i8* %11 to %Qubit** - %13 = load %Qubit*, %Qubit** %12, align 8 - call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %10, %Qubit* %13) - %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %15 = bitcast i8* %14 to %Qubit** - %qb__4 = load %Qubit*, %Qubit** %15, align 8 - call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__4) - %16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %17 = bitcast i8* %16 to %Qubit** - %qb__5 = load %Qubit*, %Qubit** %17, align 8 - call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__5) - %18 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %19 = bitcast i8* %18 to %Qubit** - %qb__6 = load %Qubit*, %Qubit** %19, align 8 - call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb__6) - %20 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %21 = bitcast i8* %20 to %Qubit** - %qb__7 = load %Qubit*, %Qubit** %21, align 8 - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__7) - %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %23 = bitcast i8* %22 to %Qubit** - %qb__9 = load %Qubit*, %Qubit** %23, align 8 - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__9) - call void @__quantum__qis__inject_barrier(i64 42, i64 0) - %24 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %25 = bitcast i8* %24 to %Qubit** - %qb__11 = load %Qubit*, %Qubit** %25, align 8 - call void @__quantum__qis__single_qubit_op(i64 0, i64 1, %Qubit* %qb__11) - %26 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %27 = bitcast i8* %26 to %Qubit** - %qb__13 = load %Qubit*, %Qubit** %27, align 8 - call void @__quantum__qis__single_qubit_op(i64 3, i64 1, %Qubit* %qb__13) - %28 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %29 = bitcast i8* %28 to %Qubit** - %qb__15 = load %Qubit*, %Qubit** %29, align 8 - call void @__quantum__qis__single_qubit_op(i64 6, i64 1, %Qubit* %qb__15) - %30 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %31 = bitcast i8* %30 to %Qubit** - %qb__17 = load %Qubit*, %Qubit** %31, align 8 - call void @__quantum__qis__single_qubit_op(i64 9, i64 1, %Qubit* %qb__17) - %32 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %33 = bitcast i8* %32 to %Qubit** - %34 = load %Qubit*, %Qubit** %33, align 8 - %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %36 = bitcast i8* %35 to %Qubit** - %37 = load %Qubit*, %Qubit** %36, align 8 - call void @Microsoft__Quantum__Intrinsic__CNOT__adj(%Qubit* %34, %Qubit* %37) - %38 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %39 = bitcast i8* %38 to %Qubit** - %qb__19 = load %Qubit*, %Qubit** %39, align 8 - call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__19) - %40 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %41 = bitcast i8* %40 to %Qubit** - %qb__20 = load %Qubit*, %Qubit** %41, align 8 - call void @__quantum__qis__single_qubit_op(i64 21, i64 1, %Qubit* %qb__20) - %42 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %43 = bitcast i8* %42 to %Qubit** - %qb__21 = load %Qubit*, %Qubit** %43, align 8 - call void @__quantum__qis__single_qubit_op(i64 23, i64 1, %Qubit* %qb__21) - %44 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %45 = bitcast i8* %44 to %Qubit** - %qb__22 = load %Qubit*, %Qubit** %45, align 8 - call void @__quantum__qis__single_qubit_op(i64 15, i64 1, %Qubit* %qb__22) - %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %47 = bitcast i8* %46 to %Qubit** - %qb__24 = load %Qubit*, %Qubit** %47, align 8 - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__24) - %c = call %Qubit* @__quantum__rt__qubit_allocate() - %ctls = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %48 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls, i64 0) - %49 = bitcast i8* %48 to %Qubit** - store %Qubit* %c, %Qubit** %49, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 1) - %50 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %51 = bitcast i8* %50 to %Qubit** - %qb__26 = load %Qubit*, %Qubit** %51, align 8 - br i1 true, label %then0__1, label %else__1 - -then0__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %ctls, %Qubit* %qb__26) - br label %continue__1 - -else__1: ; preds = %entry - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %ctls, %Qubit* %qb__26) - br label %continue__1 - -continue__1: ; preds = %else__1, %then0__1 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls, i32 -1) - %ctls__1 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %52 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__1, i64 0) - %53 = bitcast i8* %52 to %Qubit** - store %Qubit* %c, %Qubit** %53, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 1) - %54 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %55 = bitcast i8* %54 to %Qubit** - %qb__27 = load %Qubit*, %Qubit** %55, align 8 - br i1 true, label %then0__2, label %else__2 - -then0__2: ; preds = %continue__1 - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %ctls__1, %Qubit* %qb__27) - br label %continue__2 - -else__2: ; preds = %continue__1 - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %ctls__1, %Qubit* %qb__27) - br label %continue__2 - -continue__2: ; preds = %else__2, %then0__2 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__1, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__1, i32 -1) - %ctls__2 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %56 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__2, i64 0) - %57 = bitcast i8* %56 to %Qubit** - store %Qubit* %c, %Qubit** %57, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i32 1) - %58 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %59 = bitcast i8* %58 to %Qubit** - %qb__28 = load %Qubit*, %Qubit** %59, align 8 - br i1 true, label %then0__3, label %else__3 - -then0__3: ; preds = %continue__2 - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %ctls__2, %Qubit* %qb__28) - br label %continue__3 - -else__3: ; preds = %continue__2 - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %ctls__2, %Qubit* %qb__28) - br label %continue__3 - -continue__3: ; preds = %else__3, %then0__3 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__2, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__2, i32 -1) - %ctls__3 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %60 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__3, i64 0) - %61 = bitcast i8* %60 to %Qubit** - store %Qubit* %c, %Qubit** %61, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i32 1) - %62 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %63 = bitcast i8* %62 to %Qubit** - %qb__29 = load %Qubit*, %Qubit** %63, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %ctls__3, %Qubit* %qb__29) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__3, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__3, i32 -1) - %ctls__4 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %64 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__4, i64 0) - %65 = bitcast i8* %64 to %Qubit** - store %Qubit* %c, %Qubit** %65, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i32 1) - %66 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %67 = bitcast i8* %66 to %Qubit** - %qb__30 = load %Qubit*, %Qubit** %67, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %ctls__4, %Qubit* %qb__30) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__4, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__4, i32 -1) - %ctls__5 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %68 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__5, i64 0) - %69 = bitcast i8* %68 to %Qubit** - store %Qubit* %c, %Qubit** %69, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i32 1) - %70 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %71 = bitcast i8* %70 to %Qubit** - %qb__31 = load %Qubit*, %Qubit** %71, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %ctls__5, %Qubit* %qb__31) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__5, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__5, i32 -1) - %ctls__6 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %72 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__6, i64 0) - %73 = bitcast i8* %72 to %Qubit** - store %Qubit* %c, %Qubit** %73, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i32 1) - %74 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %75 = bitcast i8* %74 to %Qubit** - %qb__32 = load %Qubit*, %Qubit** %75, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %ctls__6, %Qubit* %qb__32) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__6, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__6, i32 -1) - %ctls__7 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %76 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__7, i64 0) - %77 = bitcast i8* %76 to %Qubit** - store %Qubit* %c, %Qubit** %77, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 1) - %78 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %79 = bitcast i8* %78 to %Qubit** - %qb__33 = load %Qubit*, %Qubit** %79, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %ctls__7, %Qubit* %qb__33) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__7, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__7, i32 -1) - %ctls__9 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1) - %80 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %ctls__9, i64 0) - %81 = bitcast i8* %80 to %Qubit** - store %Qubit* %c, %Qubit** %81, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 1) - %82 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %83 = bitcast i8* %82 to %Qubit** - %qb__35 = load %Qubit*, %Qubit** %83, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %ctls__9, %Qubit* %qb__35) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %ctls__9, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %ctls__9, i32 -1) - call void @__quantum__rt__qubit_release(%Qubit* %c) - %cc = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %84 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %85 = bitcast i8* %84 to %Qubit** - %qb__37 = load %Qubit*, %Qubit** %85, align 8 - %86 = call i64 @__quantum__rt__array_get_size_1d(%Array* %cc) - %87 = icmp eq i64 %86, 1 - br i1 %87, label %then0__4, label %else__4 - -then0__4: ; preds = %continue__3 - call void @__quantum__qis__single_qubit_op_ctl(i64 1, i64 1, %Array* %cc, %Qubit* %qb__37) - br label %continue__4 - -else__4: ; preds = %continue__3 - call void @__quantum__qis__single_qubit_op_ctl(i64 2, i64 1, %Array* %cc, %Qubit* %qb__37) - br label %continue__4 - -continue__4: ; preds = %else__4, %then0__4 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %88 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %89 = bitcast i8* %88 to %Qubit** - %qb__38 = load %Qubit*, %Qubit** %89, align 8 - %90 = icmp eq i64 %86, 1 - br i1 %90, label %then0__5, label %else__5 - -then0__5: ; preds = %continue__4 - call void @__quantum__qis__single_qubit_op_ctl(i64 4, i64 1, %Array* %cc, %Qubit* %qb__38) - br label %continue__5 - -else__5: ; preds = %continue__4 - call void @__quantum__qis__single_qubit_op_ctl(i64 5, i64 1, %Array* %cc, %Qubit* %qb__38) - br label %continue__5 - -continue__5: ; preds = %else__5, %then0__5 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %91 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %92 = bitcast i8* %91 to %Qubit** - %qb__39 = load %Qubit*, %Qubit** %92, align 8 - %93 = icmp eq i64 %86, 1 - br i1 %93, label %then0__6, label %else__6 - -then0__6: ; preds = %continue__5 - call void @__quantum__qis__single_qubit_op_ctl(i64 7, i64 1, %Array* %cc, %Qubit* %qb__39) - br label %continue__6 - -else__6: ; preds = %continue__5 - call void @__quantum__qis__single_qubit_op_ctl(i64 8, i64 1, %Array* %cc, %Qubit* %qb__39) - br label %continue__6 - -continue__6: ; preds = %else__6, %then0__6 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %94 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %95 = bitcast i8* %94 to %Qubit** - %qb__40 = load %Qubit*, %Qubit** %95, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 10, i64 1, %Array* %cc, %Qubit* %qb__40) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %96 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %97 = bitcast i8* %96 to %Qubit** - %qb__41 = load %Qubit*, %Qubit** %97, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 20, i64 1, %Array* %cc, %Qubit* %qb__41) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %98 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %99 = bitcast i8* %98 to %Qubit** - %qb__42 = load %Qubit*, %Qubit** %99, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 22, i64 1, %Array* %cc, %Qubit* %qb__42) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %100 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %101 = bitcast i8* %100 to %Qubit** - %qb__43 = load %Qubit*, %Qubit** %101, align 8 - call void @__quantum__qis__single_qubit_op_ctl(i64 24, i64 1, %Array* %cc, %Qubit* %qb__43) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %102 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %103 = bitcast i8* %102 to %Qubit** - %qb__44 = load %Qubit*, %Qubit** %103, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 16, i64 1, %Array* %cc, %Qubit* %qb__44) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - %104 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %105 = bitcast i8* %104 to %Qubit** - %qb__46 = load %Qubit*, %Qubit** %105, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 1) - call void @__quantum__qis__single_qubit_op_ctl(i64 12, i64 1, %Array* %cc, %Qubit* %qb__46) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %cc, i32 -1) - call void @__quantum__rt__qubit_release_array(%Array* %cc) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) - call void @__quantum__rt__qubit_release_array(%Array* %qs) - ret void -} - -declare %Qubit* @__quantum__rt__qubit_allocate() - -declare %Array* @__quantum__rt__qubit_allocate_array(i64) - -declare void @__quantum__qis__inject_barrier(i64, i64) - -declare void @__quantum__rt__qubit_release(%Qubit*) - -declare void @__quantum__rt__qubit_release_array(%Array*) - -define void @Microsoft__Quantum__Testing__Tracer__TestMeasurements__body() { -entry: - %qs = call %Array* @__quantum__rt__qubit_allocate_array(i64 6) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 1) - %0 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %1 = bitcast i8* %0 to %Qubit** - %qb = load %Qubit*, %Qubit** %1, align 8 - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb) - %2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 0) - %3 = bitcast i8* %2 to %Qubit** - %qb__2 = load %Qubit*, %Qubit** %3, align 8 - %r0 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__2) - %4 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %5 = bitcast i8* %4 to %Qubit** - %qb__4 = load %Qubit*, %Qubit** %5, align 8 - call void @__quantum__qis__single_qubit_op(i64 11, i64 1, %Qubit* %qb__4) - %6 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %7 = bitcast i8* %6 to %Qubit** - %8 = load %Qubit*, %Qubit** %7, align 8 - %9 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %10 = bitcast i8* %9 to %Qubit** - %11 = load %Qubit*, %Qubit** %10, align 8 - call void @Microsoft__Quantum__Intrinsic__CNOT__body(%Qubit* %8, %Qubit* %11) - %qs12 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 2) - %12 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) - %13 = bitcast i8* %12 to %Qubit** - %14 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 1) - %15 = bitcast i8* %14 to %Qubit** - %16 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 1) - %17 = bitcast i8* %16 to %Qubit** - %18 = load %Qubit*, %Qubit** %17, align 8 - %19 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 2) - %20 = bitcast i8* %19 to %Qubit** - %21 = load %Qubit*, %Qubit** %20, align 8 - store %Qubit* %18, %Qubit** %13, align 8 - store %Qubit* %21, %Qubit** %15, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) - %paulis = call %Array* @__quantum__rt__array_create_1d(i32 1, i64 2) - %22 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %23 = bitcast i8* %22 to i2* - %24 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %25 = bitcast i8* %24 to i2* - %26 = load i2, i2* @PauliY, align 1 - %27 = load i2, i2* @PauliX, align 1 - store i2 %26, i2* %23, align 1 - store i2 %27, i2* %25, align 1 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) - %28 = call %Result* @__quantum__rt__result_get_one() - %res = alloca %Result*, align 8 - store %Result* %28, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %28, i32 1) - %haveY = alloca i1, align 1 - store i1 false, i1* %haveY, align 1 - br label %header__1 - -header__1: ; preds = %exiting__1, %entry - %i = phi i64 [ 0, %entry ], [ %41, %exiting__1 ] - %29 = icmp sle i64 %i, 1 - br i1 %29, label %body__1, label %exit__1 - -body__1: ; preds = %header__1 - %30 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %31 = bitcast i8* %30 to i2* - %32 = load i2, i2* %31, align 1 - %33 = load i2, i2* @PauliY, align 1 - %34 = icmp eq i2 %32, %33 - br i1 %34, label %condContinue__1, label %condFalse__1 - -condFalse__1: ; preds = %body__1 - %35 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 %i) - %36 = bitcast i8* %35 to i2* - %37 = load i2, i2* %36, align 1 - %38 = load i2, i2* @PauliI, align 1 - %39 = icmp eq i2 %37, %38 - br label %condContinue__1 - -condContinue__1: ; preds = %condFalse__1, %body__1 - %40 = phi i1 [ %34, %body__1 ], [ %39, %condFalse__1 ] - br i1 %40, label %then0__1, label %continue__1 - -then0__1: ; preds = %condContinue__1 - store i1 true, i1* %haveY, align 1 - br label %continue__1 - -continue__1: ; preds = %then0__1, %condContinue__1 - br label %exiting__1 - -exiting__1: ; preds = %continue__1 - %41 = add i64 %i, 1 - br label %header__1 - -exit__1: ; preds = %header__1 - %42 = load i1, i1* %haveY, align 1 - br i1 %42, label %then0__2, label %test1__1 - -then0__2: ; preds = %exit__1 - %43 = call %Result* @__quantum__qis__joint_measure(i64 106, i64 1, %Array* %qs12) - call void @__quantum__rt__result_update_reference_count(%Result* %43, i32 1) - store %Result* %43, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %43, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %28, i32 -1) - br label %continue__2 - -test1__1: ; preds = %exit__1 - br i1 false, label %then1__1, label %test2__1 - -then1__1: ; preds = %test1__1 - %44 = call %Result* @__quantum__qis__joint_measure(i64 107, i64 1, %Array* %qs12) - call void @__quantum__rt__result_update_reference_count(%Result* %44, i32 1) - %45 = load %Result*, %Result** %res, align 8 - store %Result* %44, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %44, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %45, i32 -1) - br label %continue__2 - -test2__1: ; preds = %test1__1 - br i1 false, label %then2__1, label %test3__1 - -then2__1: ; preds = %test2__1 - %46 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %47 = bitcast i8* %46 to i2* - %48 = load i2, i2* %47, align 1 - %49 = load i2, i2* @PauliX, align 1 - %50 = icmp eq i2 %48, %49 - br i1 %50, label %then0__3, label %else__1 - -then0__3: ; preds = %then2__1 - %51 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) - %52 = bitcast i8* %51 to %Qubit** - %qb__6 = load %Qubit*, %Qubit** %52, align 8 - %53 = call %Result* @__quantum__qis__single_qubit_measure(i64 101, i64 1, %Qubit* %qb__6) - call void @__quantum__rt__result_update_reference_count(%Result* %53, i32 1) - %54 = load %Result*, %Result** %res, align 8 - store %Result* %53, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %53, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %54, i32 -1) - br label %continue__3 - -else__1: ; preds = %then2__1 - %55 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs12, i64 0) - %56 = bitcast i8* %55 to %Qubit** - %qb__7 = load %Qubit*, %Qubit** %56, align 8 - %57 = call %Result* @__quantum__qis__single_qubit_measure(i64 100, i64 1, %Qubit* %qb__7) - call void @__quantum__rt__result_update_reference_count(%Result* %57, i32 1) - %58 = load %Result*, %Result** %res, align 8 - store %Result* %57, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %57, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %58, i32 -1) - br label %continue__3 - -continue__3: ; preds = %else__1, %then0__3 - br label %continue__2 - -test3__1: ; preds = %test2__1 - %59 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %60 = bitcast i8* %59 to i2* - %61 = load i2, i2* %60, align 1 - %62 = load i2, i2* @PauliX, align 1 - %63 = icmp eq i2 %61, %62 - br i1 %63, label %condTrue__1, label %condContinue__2 - -condTrue__1: ; preds = %test3__1 - %64 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %65 = bitcast i8* %64 to i2* - %66 = load i2, i2* %65, align 1 - %67 = load i2, i2* @PauliX, align 1 - %68 = icmp eq i2 %66, %67 - br label %condContinue__2 - -condContinue__2: ; preds = %condTrue__1, %test3__1 - %69 = phi i1 [ %68, %condTrue__1 ], [ %63, %test3__1 ] - br i1 %69, label %then3__1, label %test4__1 - -then3__1: ; preds = %condContinue__2 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) - %70 = call %Result* @__quantum__qis__joint_measure(i64 105, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %70, i32 1) - %71 = load %Result*, %Result** %res, align 8 - store %Result* %70, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %70, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %71, i32 -1) - br label %continue__2 - -test4__1: ; preds = %condContinue__2 - %72 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %73 = bitcast i8* %72 to i2* - %74 = load i2, i2* %73, align 1 - %75 = load i2, i2* @PauliX, align 1 - %76 = icmp eq i2 %74, %75 - br i1 %76, label %condTrue__2, label %condContinue__3 - -condTrue__2: ; preds = %test4__1 - %77 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %78 = bitcast i8* %77 to i2* - %79 = load i2, i2* %78, align 1 - %80 = load i2, i2* @PauliZ, align 1 - %81 = icmp eq i2 %79, %80 - br label %condContinue__3 - -condContinue__3: ; preds = %condTrue__2, %test4__1 - %82 = phi i1 [ %81, %condTrue__2 ], [ %76, %test4__1 ] - br i1 %82, label %then4__1, label %test5__1 - -then4__1: ; preds = %condContinue__3 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) - %83 = call %Result* @__quantum__qis__joint_measure(i64 103, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %83, i32 1) - %84 = load %Result*, %Result** %res, align 8 - store %Result* %83, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %83, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %84, i32 -1) - br label %continue__2 - -test5__1: ; preds = %condContinue__3 - %85 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %86 = bitcast i8* %85 to i2* - %87 = load i2, i2* %86, align 1 - %88 = load i2, i2* @PauliZ, align 1 - %89 = icmp eq i2 %87, %88 - br i1 %89, label %condTrue__3, label %condContinue__4 - -condTrue__3: ; preds = %test5__1 - %90 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %91 = bitcast i8* %90 to i2* - %92 = load i2, i2* %91, align 1 - %93 = load i2, i2* @PauliX, align 1 - %94 = icmp eq i2 %92, %93 - br label %condContinue__4 - -condContinue__4: ; preds = %condTrue__3, %test5__1 - %95 = phi i1 [ %94, %condTrue__3 ], [ %89, %test5__1 ] - br i1 %95, label %then5__1, label %test6__1 - -then5__1: ; preds = %condContinue__4 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) - %96 = call %Result* @__quantum__qis__joint_measure(i64 104, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %96, i32 1) - %97 = load %Result*, %Result** %res, align 8 - store %Result* %96, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %96, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %97, i32 -1) - br label %continue__2 - -test6__1: ; preds = %condContinue__4 - %98 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 0) - %99 = bitcast i8* %98 to i2* - %100 = load i2, i2* %99, align 1 - %101 = load i2, i2* @PauliZ, align 1 - %102 = icmp eq i2 %100, %101 - br i1 %102, label %condTrue__4, label %condContinue__5 - -condTrue__4: ; preds = %test6__1 - %103 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %paulis, i64 1) - %104 = bitcast i8* %103 to i2* - %105 = load i2, i2* %104, align 1 - %106 = load i2, i2* @PauliZ, align 1 - %107 = icmp eq i2 %105, %106 - br label %condContinue__5 - -condContinue__5: ; preds = %condTrue__4, %test6__1 - %108 = phi i1 [ %107, %condTrue__4 ], [ %102, %test6__1 ] - br i1 %108, label %then6__1, label %continue__2 - -then6__1: ; preds = %condContinue__5 - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 1) - %109 = call %Result* @__quantum__qis__joint_measure(i64 102, i64 1, %Array* %qs12) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %109, i32 1) - %110 = load %Result*, %Result** %res, align 8 - store %Result* %109, %Result** %res, align 8 - call void @__quantum__rt__result_update_reference_count(%Result* %109, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %110, i32 -1) - br label %continue__2 - -continue__2: ; preds = %then6__1, %condContinue__5, %then5__1, %then4__1, %then3__1, %continue__3, %then1__1, %then0__2 - %r12 = load %Result*, %Result** %res, align 8 - call void @__quantum__rt__array_update_alias_count(%Array* %paulis, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %paulis, i32 -1) - %111 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %112 = bitcast %Tuple* %111 to { %Callable*, %Callable*, %Qubit* }* - %113 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 0 - %114 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 1 - %115 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %112, i32 0, i32 2 - %116 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %117 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__X, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %118 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 3) - %119 = bitcast i8* %118 to %Qubit** - %120 = load %Qubit*, %Qubit** %119, align 8 - store %Callable* %116, %Callable** %113, align 8 - store %Callable* %117, %Callable** %114, align 8 - store %Qubit* %120, %Qubit** %115, align 8 - %121 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__1, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %111) - %122 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %123 = bitcast %Tuple* %122 to { %Callable*, %Callable*, %Qubit* }* - %124 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 0 - %125 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 1 - %126 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %123, i32 0, i32 2 - %127 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %128 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Y, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %129 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 3) - %130 = bitcast i8* %129 to %Qubit** - %131 = load %Qubit*, %Qubit** %130, align 8 - store %Callable* %127, %Callable** %124, align 8 - store %Callable* %128, %Callable** %125, align 8 - store %Qubit* %131, %Qubit** %126, align 8 - %132 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__2, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %122) - call void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %r0, %Callable* %121, %Callable* %132) - %133 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %134 = bitcast %Tuple* %133 to { %Callable*, %Callable*, %Qubit* }* - %135 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 0 - %136 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 1 - %137 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %134, i32 0, i32 2 - %138 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %139 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__Z, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %140 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 4) - %141 = bitcast i8* %140 to %Qubit** - %142 = load %Qubit*, %Qubit** %141, align 8 - store %Callable* %138, %Callable** %135, align 8 - store %Callable* %139, %Callable** %136, align 8 - store %Qubit* %142, %Qubit** %137, align 8 - %143 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__3, [2 x void (%Tuple*, i32)*]* @MemoryManagement__1, %Tuple* %133) - %144 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %145 = bitcast %Tuple* %144 to { %Callable*, %Callable*, %Qubit* }* - %146 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 0 - %147 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 1 - %148 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %145, i32 0, i32 2 - %149 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Testing__Tracer__Delay, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %150 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @Microsoft__Quantum__Intrinsic__S, [2 x void (%Tuple*, i32)*]* null, %Tuple* null) - %151 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 4) - %152 = bitcast i8* %151 to %Qubit** - %153 = load %Qubit*, %Qubit** %152, align 8 - store %Callable* %149, %Callable** %146, align 8 - store %Callable* %150, %Callable** %147, align 8 - store %Qubit* %153, %Qubit** %148, align 8 - %154 = call %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]* @PartialApplication__4, [2 x void (%Tuple*, i32)*]* @MemoryManagement__2, %Tuple* %144) - call void @Microsoft__Quantum__Intrinsic__ApplyIfElseIntrinsic__body(%Result* %r12, %Callable* %143, %Callable* %154) - %155 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %qs, i64 5) - %156 = bitcast i8* %155 to %Qubit** - %qb__8 = load %Qubit*, %Qubit** %156, align 8 - call void @__quantum__qis__single_qubit_op(i64 19, i64 1, %Qubit* %qb__8) - call void @__quantum__rt__array_update_alias_count(%Array* %qs, i32 -1) - call void @__quantum__rt__array_update_alias_count(%Array* %qs12, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %r0, i32 -1) - call void @__quantum__rt__array_update_reference_count(%Array* %qs12, i32 -1) - call void @__quantum__rt__result_update_reference_count(%Result* %r12, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %121, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %121, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %132, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %132, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %143, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %143, i32 -1) - call void @__quantum__rt__capture_update_reference_count(%Callable* %154, i32 -1) - call void @__quantum__rt__callable_update_reference_count(%Callable* %154, i32 -1) - call void @__quantum__rt__qubit_release_array(%Array* %qs) - ret void -} - -define void @Microsoft__Quantum__Testing__Tracer__Delay__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Callable*, %Qubit*, %Tuple* }* - %1 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 1 - %3 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %0, i32 0, i32 2 - %4 = load %Callable*, %Callable** %1, align 8 - %5 = load %Qubit*, %Qubit** %2, align 8 - %6 = load %Tuple*, %Tuple** %3, align 8 - call void @Microsoft__Quantum__Testing__Tracer__Delay__body(%Callable* %4, %Qubit* %5, %Tuple* %6) - ret void -} - -declare %Callable* @__quantum__rt__callable_create([4 x void (%Tuple*, %Tuple*, %Tuple*)*]*, [2 x void (%Tuple*, i32)*]*, %Tuple*) - -define void @Microsoft__Quantum__Intrinsic__X__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__X__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__X__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__X__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__X__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__X__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Lifted__PartialApplication__1__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %2 = load %Callable*, %Callable** %1, align 8 - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 - %4 = load %Qubit*, %Qubit** %3, align 8 - %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* - %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 - %7 = load %Tuple*, %Tuple** %6, align 8 - %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* - %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 - %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 - %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 - store %Callable* %2, %Callable** %10, align 8 - store %Qubit* %4, %Qubit** %11, align 8 - store %Tuple* %7, %Tuple** %12, align 8 - %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %14 = load %Callable*, %Callable** %13, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) - ret void -} - -define void @MemoryManagement__1__RefCount(%Tuple* %capture-tuple, i32 %count-change) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %2 = load %Callable*, %Callable** %1, align 8 - call void @__quantum__rt__capture_update_reference_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i32 %count-change) - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %4 = load %Callable*, %Callable** %3, align 8 - call void @__quantum__rt__capture_update_reference_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__callable_update_reference_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i32 %count-change) - ret void -} - -define void @MemoryManagement__1__AliasCount(%Tuple* %capture-tuple, i32 %count-change) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %2 = load %Callable*, %Callable** %1, align 8 - call void @__quantum__rt__capture_update_alias_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i32 %count-change) - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %4 = load %Callable*, %Callable** %3, align 8 - call void @__quantum__rt__capture_update_alias_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__callable_update_alias_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i32 %count-change) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Y__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Y__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Lifted__PartialApplication__2__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %2 = load %Callable*, %Callable** %1, align 8 - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 - %4 = load %Qubit*, %Qubit** %3, align 8 - %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* - %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 - %7 = load %Tuple*, %Tuple** %6, align 8 - %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* - %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 - %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 - %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 - store %Callable* %2, %Callable** %10, align 8 - store %Qubit* %4, %Qubit** %11, align 8 - store %Tuple* %7, %Tuple** %12, align 8 - %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %14 = load %Callable*, %Callable** %13, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__Z__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__Z__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Lifted__PartialApplication__3__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %2 = load %Callable*, %Callable** %1, align 8 - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 - %4 = load %Qubit*, %Qubit** %3, align 8 - %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* - %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 - %7 = load %Tuple*, %Tuple** %6, align 8 - %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* - %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 - %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 - %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 - store %Callable* %2, %Callable** %10, align 8 - store %Qubit* %4, %Qubit** %11, align 8 - store %Tuple* %7, %Tuple** %12, align 8 - %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %14 = load %Callable*, %Callable** %13, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__S__body(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__adj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Qubit* }* - %1 = getelementptr inbounds { %Qubit* }, { %Qubit* }* %0, i32 0, i32 0 - %2 = load %Qubit*, %Qubit** %1, align 8 - call void @Microsoft__Quantum__Intrinsic__S__adj(%Qubit* %2) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__ctl__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__S__ctl(%Array* %3, %Qubit* %4) - ret void -} - -define void @Microsoft__Quantum__Intrinsic__S__ctladj__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %arg-tuple to { %Array*, %Qubit* }* - %1 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 0 - %2 = getelementptr inbounds { %Array*, %Qubit* }, { %Array*, %Qubit* }* %0, i32 0, i32 1 - %3 = load %Array*, %Array** %1, align 8 - %4 = load %Qubit*, %Qubit** %2, align 8 - call void @Microsoft__Quantum__Intrinsic__S__ctladj(%Array* %3, %Qubit* %4) - ret void -} - -define void @Lifted__PartialApplication__4__body__wrapper(%Tuple* %capture-tuple, %Tuple* %arg-tuple, %Tuple* %result-tuple) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %2 = load %Callable*, %Callable** %1, align 8 - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 2 - %4 = load %Qubit*, %Qubit** %3, align 8 - %5 = bitcast %Tuple* %arg-tuple to { %Tuple* }* - %6 = getelementptr inbounds { %Tuple* }, { %Tuple* }* %5, i32 0, i32 0 - %7 = load %Tuple*, %Tuple** %6, align 8 - %8 = call %Tuple* @__quantum__rt__tuple_create(i64 mul nuw (i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64 3)) - %9 = bitcast %Tuple* %8 to { %Callable*, %Qubit*, %Tuple* }* - %10 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 0 - %11 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 1 - %12 = getelementptr inbounds { %Callable*, %Qubit*, %Tuple* }, { %Callable*, %Qubit*, %Tuple* }* %9, i32 0, i32 2 - store %Callable* %2, %Callable** %10, align 8 - store %Qubit* %4, %Qubit** %11, align 8 - store %Tuple* %7, %Tuple** %12, align 8 - %13 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %14 = load %Callable*, %Callable** %13, align 8 - call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* %8, %Tuple* %result-tuple) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %8, i32 -1) - ret void -} - -define void @MemoryManagement__2__RefCount(%Tuple* %capture-tuple, i32 %count-change) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %2 = load %Callable*, %Callable** %1, align 8 - call void @__quantum__rt__capture_update_reference_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__callable_update_reference_count(%Callable* %2, i32 %count-change) - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %4 = load %Callable*, %Callable** %3, align 8 - call void @__quantum__rt__capture_update_reference_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__callable_update_reference_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__tuple_update_reference_count(%Tuple* %capture-tuple, i32 %count-change) - ret void -} - -define void @MemoryManagement__2__AliasCount(%Tuple* %capture-tuple, i32 %count-change) { -entry: - %0 = bitcast %Tuple* %capture-tuple to { %Callable*, %Callable*, %Qubit* }* - %1 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 0 - %2 = load %Callable*, %Callable** %1, align 8 - call void @__quantum__rt__capture_update_alias_count(%Callable* %2, i32 %count-change) - call void @__quantum__rt__callable_update_alias_count(%Callable* %2, i32 %count-change) - %3 = getelementptr inbounds { %Callable*, %Callable*, %Qubit* }, { %Callable*, %Callable*, %Qubit* }* %0, i32 0, i32 1 - %4 = load %Callable*, %Callable** %3, align 8 - call void @__quantum__rt__capture_update_alias_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__callable_update_alias_count(%Callable* %4, i32 %count-change) - call void @__quantum__rt__tuple_update_alias_count(%Tuple* %capture-tuple, i32 %count-change) - ret void -} - -declare void @__quantum__rt__capture_update_reference_count(%Callable*, i32) - -declare void @__quantum__rt__callable_update_reference_count(%Callable*, i32) - -define { %String* }* @Microsoft__Quantum__Targeting__TargetInstruction__body(%String* %__Item1__) { -entry: - %0 = call %Tuple* @__quantum__rt__tuple_create(i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)) - %1 = bitcast %Tuple* %0 to { %String* }* - %2 = getelementptr inbounds { %String* }, { %String* }* %1, i32 0, i32 0 - store %String* %__Item1__, %String** %2, align 8 - call void @__quantum__rt__string_update_reference_count(%String* %__Item1__, i32 1) - ret { %String* }* %1 -} - -declare void @__quantum__rt__string_update_reference_count(%String*, i32) - -declare void @__quantum__rt__tuple_update_alias_count(%Tuple*, i32) From dca7fbb785d3e3ecb25f0624467cfe76c3ab599f Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Wed, 7 Apr 2021 17:19:17 -0700 Subject: [PATCH 006/145] Remove placeholder tests --- src/Qir/Controller/test-cases/01.err | 1 - src/Qir/Controller/test-cases/01.in | 1 - src/Qir/Controller/test-cases/01.out | 1 - 3 files changed, 3 deletions(-) delete mode 100644 src/Qir/Controller/test-cases/01.err delete mode 100644 src/Qir/Controller/test-cases/01.in delete mode 100644 src/Qir/Controller/test-cases/01.out diff --git a/src/Qir/Controller/test-cases/01.err b/src/Qir/Controller/test-cases/01.err deleted file mode 100644 index 760589cb5d6..00000000000 --- a/src/Qir/Controller/test-cases/01.err +++ /dev/null @@ -1 +0,0 @@ -error \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/01.in b/src/Qir/Controller/test-cases/01.in deleted file mode 100644 index 770eab4480b..00000000000 --- a/src/Qir/Controller/test-cases/01.in +++ /dev/null @@ -1 +0,0 @@ -input \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/01.out b/src/Qir/Controller/test-cases/01.out deleted file mode 100644 index 6caf68aff42..00000000000 --- a/src/Qir/Controller/test-cases/01.out +++ /dev/null @@ -1 +0,0 @@ -output \ No newline at end of file From 2c8ca9f550974aa7203acba9a73ecde32c9bade7 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 8 Apr 2021 11:23:06 -0700 Subject: [PATCH 007/145] Allow test cases folder not to exist --- src/Qir/Controller/test-qir-controller.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index 876626b703a..bddb55ff62c 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -8,6 +8,10 @@ Write-Host "##[info]Test QIR Controller" $controllerProject = (Join-Path $PSScriptRoot QirController.csproj) $testCasesFolder = (Join-Path $PSScriptRoot "test-cases") $testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") +if (!(Test-Path $testCasesFolder)) { + Write-Host "No tests found. Returning." + return +} if (!(Test-Path $testArtifactsFolder -PathType Container)) { New-Item -ItemType Directory -Force -Path $testArtifactsFolder } From 7558e4644db6355aa0dc61526971e969e1ece633 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 8 Apr 2021 13:10:10 -0700 Subject: [PATCH 008/145] Add default error handling --- .gitignore | 3 + src/Qir/Controller/Constant.cs | 6 + src/Qir/Controller/Controller.cs | 75 ++++++++--- src/Qir/Controller/ControllerException.cs | 21 +++ src/Qir/Controller/ErrorMessages.Designer.cs | 72 ++++++++++ src/Qir/Controller/ErrorMessages.resx | 123 ++++++++++++++++++ src/Qir/Controller/Model/Error.cs | 16 +++ src/Qir/Controller/QirController.csproj | 15 +++ .../Tests.QirController/ControllerTests.cs | 114 ++++++++++++++++ .../test-cases/internal-error-test.err | 4 + .../test-cases/internal-error-test.in | 1 + src/Qir/Controller/test-qir-controller.ps1 | 58 ++++++--- 12 files changed, 474 insertions(+), 34 deletions(-) create mode 100644 src/Qir/Controller/ControllerException.cs create mode 100644 src/Qir/Controller/ErrorMessages.Designer.cs create mode 100644 src/Qir/Controller/ErrorMessages.resx create mode 100644 src/Qir/Controller/Model/Error.cs create mode 100644 src/Qir/Controller/test-cases/internal-error-test.err create mode 100644 src/Qir/Controller/test-cases/internal-error-test.in diff --git a/.gitignore b/.gitignore index 5b33b48524e..7127ca52075 100644 --- a/.gitignore +++ b/.gitignore @@ -339,3 +339,6 @@ ASALocalRun/ /src/Simulation/Simulators.Tests/TestProjects/QSharpExe/built /src/Simulation/Simulators.Tests/TestProjects/TargetedExe/built dbw_test + +# Controller test artifacts +/src/Qir/Controller/test-artifacts/ \ No newline at end of file diff --git a/src/Qir/Controller/Constant.cs b/src/Qir/Controller/Constant.cs index 42475cb494b..13cb9b2cef1 100644 --- a/src/Qir/Controller/Constant.cs +++ b/src/Qir/Controller/Constant.cs @@ -12,5 +12,11 @@ public static class FilePath public const string DriverFilePath = "/home/driver.cpp"; public const string ExecutableFilePath = "/home/simulation.exe"; } + + // TODO: errors will be added as dependencies are implemented. + public static class ErrorCode + { + public const string InternalError = "InternalError"; + } } } diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 5d43815a7b4..a44ebbcdb14 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -1,10 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; using System.IO; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Driver; using Microsoft.Quantum.Qir.Executable; +using Microsoft.Quantum.Qir.Model; using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; namespace Microsoft.Quantum.Qir @@ -21,29 +24,69 @@ public static async Task ExecuteAsync( IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner executableRunner) { - // TODO: Error handling. // TODO: Logging. - // Step 1: Parse input. - using var inputFileStream = inputFile.OpenRead(); - var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); + try + { + // Step 1: Parse input. + using var inputFileStream = inputFile.OpenRead(); + var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); + + // Step 2: Create bytecode file. + using (var bytecodeFileStream = bytecodeFile.OpenWrite()) + { + await bytecodeFileStream.WriteAsync(input.QirBytecode.Array, input.QirBytecode.Offset, input.QirBytecode.Count); + } + + // Step 3: Create the driver file. + var driverFile = new FileInfo(Constant.FilePath.DriverFilePath); + await driverGenerator.GenerateQirDriverCppAsync(input.EntryPoint, driverFile); - // Step 2: Create bytecode file. - using (var bytecodeFileStream = bytecodeFile.OpenWrite()) + // Step 4: Create the executable. + var executableFile = new FileInfo(Constant.FilePath.ExecutableFilePath); + await executableGenerator.GenerateExecutableAsync(driverFile, bytecodeFile, libraryDirectory, executableFile); + + // Step 5: Run the executable. + using var outputFileStream = outputFile.OpenWrite(); + await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); + } + catch (Exception e) { - await bytecodeFileStream.WriteAsync(input.QirBytecode.Array, input.QirBytecode.Offset, input.QirBytecode.Count); + await WriteExceptionToFileAsync(e, errorFile); + outputFile.Delete(); } + } - // Step 3: Create the driver file. - var driverFile = new FileInfo(Constant.FilePath.DriverFilePath); - await driverGenerator.GenerateQirDriverCppAsync(input.EntryPoint, driverFile); + private static async Task WriteExceptionToFileAsync(Exception e, FileInfo errorFile) + { + // Create the error object. + Error error; + if (e is ControllerException controllerException) + { + error = new Error + { + Code = controllerException.Code, + Message = controllerException.Message, + }; + } + else + { + error = new Error + { + Code = Constant.ErrorCode.InternalError, + Message = ErrorMessages.InternalError, + }; + } - // Step 4: Create the executable. - var executableFile = new FileInfo(Constant.FilePath.ExecutableFilePath); - await executableGenerator.GenerateExecutableAsync(driverFile, bytecodeFile, libraryDirectory, executableFile); + // Serialize the error to JSON. + var errorJson = JsonSerializer.Serialize(error, new JsonSerializerOptions + { + WriteIndented = true, + }); - // Step 5: Run the executable. - using var outputFileStream = outputFile.Exists ? outputFile.OpenWrite() : outputFile.Create(); - await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); + // Write the error to the error file. + using var errorFileStream = errorFile.OpenWrite(); + using var streamWriter = new StreamWriter(errorFileStream); + await streamWriter.WriteAsync(errorJson); } } } diff --git a/src/Qir/Controller/ControllerException.cs b/src/Qir/Controller/ControllerException.cs new file mode 100644 index 00000000000..05cbd872cf9 --- /dev/null +++ b/src/Qir/Controller/ControllerException.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Quantum.Qir +{ + /// + /// Exception that represents an error that can be written to an error file. + /// + public class ControllerException : Exception + { + public ControllerException(string message, string code) + : base(message) + { + Code = code; + } + + public string Code { get; } + } +} diff --git a/src/Qir/Controller/ErrorMessages.Designer.cs b/src/Qir/Controller/ErrorMessages.Designer.cs new file mode 100644 index 00000000000..dbd8ce8ba5e --- /dev/null +++ b/src/Qir/Controller/ErrorMessages.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Quantum.Qir { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ErrorMessages { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ErrorMessages() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Quantum.Qir.ErrorMessages", typeof(ErrorMessages).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to An internal error occurred.. + /// + public static string InternalError { + get { + return ResourceManager.GetString("InternalError", resourceCulture); + } + } + } +} diff --git a/src/Qir/Controller/ErrorMessages.resx b/src/Qir/Controller/ErrorMessages.resx new file mode 100644 index 00000000000..6cfb82bccc5 --- /dev/null +++ b/src/Qir/Controller/ErrorMessages.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + An internal error occurred. + + \ No newline at end of file diff --git a/src/Qir/Controller/Model/Error.cs b/src/Qir/Controller/Model/Error.cs new file mode 100644 index 00000000000..ee96bff5348 --- /dev/null +++ b/src/Qir/Controller/Model/Error.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Text.Json.Serialization; + +namespace Microsoft.Quantum.Qir.Model +{ + public class Error + { + [JsonPropertyName("code")] + public string Code { get; set; } + + [JsonPropertyName("message")] + public string Message { get; set; } + } +} diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index e6f5c6fa3fc..b00c550f212 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -22,4 +22,19 @@ + + + True + True + ErrorMessages.resx + + + + + + PublicResXFileCodeGenerator + ErrorMessages.Designer.cs + + + diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 83c6b17c2b7..5c60c270cb1 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -5,10 +5,12 @@ using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Quantum.Qir; using Microsoft.Quantum.Qir.Driver; using Microsoft.Quantum.Qir.Executable; +using Microsoft.Quantum.Qir.Model; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; using Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper; using Moq; @@ -114,6 +116,118 @@ await Controller.ExecuteAsync( It.Is(actualOutputFile => actualOutputFile.FullName == outputFile.FullName))); } + [Fact] + public async Task TestExecuteEncountersGenericExceptionWithOutputFileAlreadyCreated() + { + var libraryDirectory = new DirectoryInfo("libraries"); + var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); + var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("exception message")); + + // Create output file to ensure that it will be deleted unconditionally. + using (var outputFileStream = outputFile.OpenWrite()) + using (var streamWriter = new StreamWriter(outputFileStream)) + { + await streamWriter.WriteAsync("program output"); + } + + // Execute controller. + await Controller.ExecuteAsync( + inputFile, + outputFile, + libraryDirectory, + errorFile, + bytecodeFile, + driverGeneratorMock.Object, + executableGeneratorMock.Object, + executableRunnerMock.Object); + + // Verify error file was created and contains the error. + Assert.True(errorFile.Exists); + using var errorFileStream = errorFile.OpenRead(); + using var streamReader = new StreamReader(errorFileStream); + var errorFileContents = await streamReader.ReadToEndAsync(); + var error = JsonSerializer.Deserialize(errorFileContents); + Assert.Equal(ErrorMessages.InternalError, error.Message); + Assert.Equal(Constant.ErrorCode.InternalError, error.Code); + + // Verify output file was deleted. + Assert.False(outputFile.Exists); + } + + [Fact] + public async Task TestExecuteEncountersGenericExceptionWithOutputFileNeverCreated() + { + var libraryDirectory = new DirectoryInfo("libraries"); + var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); + var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("exception message")); + + // Execute controller. + await Controller.ExecuteAsync( + inputFile, + outputFile, + libraryDirectory, + errorFile, + bytecodeFile, + driverGeneratorMock.Object, + executableGeneratorMock.Object, + executableRunnerMock.Object); + + // Verify error file was created and contains the error. + Assert.True(errorFile.Exists); + using var errorFileStream = errorFile.OpenRead(); + using var streamReader = new StreamReader(errorFileStream); + var errorFileContents = await streamReader.ReadToEndAsync(); + var error = JsonSerializer.Deserialize(errorFileContents); + Assert.Equal(ErrorMessages.InternalError, error.Message); + Assert.Equal(Constant.ErrorCode.InternalError, error.Code); + } + + [Fact] + public async Task TestExecuteEncountersControllerException() + { + var exceptionMessage = "exception message"; + var errorCode = "error code"; + var libraryDirectory = new DirectoryInfo("libraries"); + var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); + var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new ControllerException(exceptionMessage, errorCode)); + + // Create output file to ensure that it will be deleted unconditionally. + using (var outputFileStream = outputFile.OpenWrite()) + using (var streamWriter = new StreamWriter(outputFileStream)) + { + await streamWriter.WriteAsync("program output"); + } + + // Execute controller. + await Controller.ExecuteAsync( + inputFile, + outputFile, + libraryDirectory, + errorFile, + bytecodeFile, + driverGeneratorMock.Object, + executableGeneratorMock.Object, + executableRunnerMock.Object); + + // Verify error file was created and contains the error. + Assert.True(errorFile.Exists); + using var errorFileStream = errorFile.OpenRead(); + using var streamReader = new StreamReader(errorFileStream); + var errorFileContents = await streamReader.ReadToEndAsync(); + var error = JsonSerializer.Deserialize(errorFileContents); + Assert.Equal(exceptionMessage, error.Message); + Assert.Equal(errorCode, error.Code); + + // Verify output file was deleted. + Assert.False(outputFile.Exists); + } + private bool EntryPointsAreEqual(EntryPointOperation entryPointA, EntryPointOperation entryPointB) { var method = typeof(Extensions) diff --git a/src/Qir/Controller/test-cases/internal-error-test.err b/src/Qir/Controller/test-cases/internal-error-test.err new file mode 100644 index 00000000000..cc5c5a256f3 --- /dev/null +++ b/src/Qir/Controller/test-cases/internal-error-test.err @@ -0,0 +1,4 @@ +{ + "code": "InternalError", + "message": "An internal error occurred." +} \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/internal-error-test.in b/src/Qir/Controller/test-cases/internal-error-test.in new file mode 100644 index 00000000000..37fc5162678 --- /dev/null +++ b/src/Qir/Controller/test-cases/internal-error-test.in @@ -0,0 +1 @@ +any input will do for now, but as errors become more specific, the corresponding test will need to change. \ No newline at end of file diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index bddb55ff62c..5b96a520b96 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -8,10 +8,7 @@ Write-Host "##[info]Test QIR Controller" $controllerProject = (Join-Path $PSScriptRoot QirController.csproj) $testCasesFolder = (Join-Path $PSScriptRoot "test-cases") $testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") -if (!(Test-Path $testCasesFolder)) { - Write-Host "No tests found. Returning." - return -} + if (!(Test-Path $testArtifactsFolder -PathType Container)) { New-Item -ItemType Directory -Force -Path $testArtifactsFolder } @@ -23,23 +20,38 @@ Foreach-Object { # Get the paths to the output and error files to pass to the QIR controller. $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) - dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile + dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile --libraryDirectory "placeholder for now" # Compare the expected content of the output and error files vs the actual content. $expectedOutputFile = (Join-Path $testCasesFolder ($_.BaseName + ".out")) - $expectedOutput = Get-Content -Path $expectedOutputFile -Raw - $actualOutput = Get-Content -Path $outputFile -Raw - if (-not ($expectedOutput -ceq $actualOutput)) { - Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" - Write-Host "##[info]Expected output:" - Write-Host $expectedOutput - Write-Host "##[info]Actual output:" - Write-Host $actualOutput - $script:all_ok = $False - break + $expectedErrorFile = (Join-Path $testCasesFolder ($_.BaseName + ".err")) + + if ((Test-Path $expectedOutputFile)) { + $expectedOutput = Get-Content -Path $expectedOutputFile -Raw + $actualOutput = Get-Content -Path $outputFile -Raw + if (-not ($expectedOutput -ceq $actualOutput)) { + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Expected output:" + Write-Host $expectedOutput + Write-Host "##[info]Actual output:" + Write-Host $actualOutput + $script:all_ok = $False + } + elseif ((Test-Path $errorFile)) { + $actualError = Get-Content -Path $errorFile -Raw + + # An error file should not have been generated, so fail test if one was found. + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Unexpected error file was found:" + Write-Host $actualError + $script:all_ok = $False + } + else { + Write-Host "##[info]Test case '$($_.BaseName)' passed" + } + continue; } - $expectedErrorFile = (Join-Path $testCasesFolder ($_.BaseName + ".err")) $expectedError = Get-Content -Path $expectedErrorFile -Raw $actualError = Get-Content -Path $errorFile -Raw if (-not ($expectedError -ceq $actualError)) { @@ -49,10 +61,20 @@ Foreach-Object { Write-Host "##[info]Actual error:" Write-Host $actualError $script:all_ok = $False - break + continue } + elseif ((Test-Path $outputFile)) { + $actualOutput = Get-Content -Path $outputFile -Raw - Write-Host "##[info]Test case '$($_.BaseName)' passed" + # An error file should not have been generated, so fail test if one was found. + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Unexpected output file was found:" + Write-Host $actualOutput + $script:all_ok = $False + } + else { + Write-Host "##[info]Test case '$($_.BaseName)' passed" + } } if (-not $all_ok) { From d1924152fca873568e2330674565dda857c39f23 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 8 Apr 2021 13:56:35 -0700 Subject: [PATCH 009/145] Remove test artifacts from solution --- src/Qir/Controller/QirController.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index b00c550f212..3c7e124c26a 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -11,9 +11,13 @@ + + + + From 84725d33c2a6976b7e88db7c9c75b04acb8eaa24 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 8 Apr 2021 14:56:10 -0700 Subject: [PATCH 010/145] Create logger and tests --- src/Qir/Controller/Controller.cs | 16 ++- src/Qir/Controller/Program.cs | 4 +- .../Tests.QirController/ControllerTests.cs | 14 ++- .../Tests.QirController/LoggerTests.cs | 100 ++++++++++++++++++ src/Qir/Controller/Utility/Clock.cs | 12 +++ src/Qir/Controller/Utility/IClock.cs | 15 +++ src/Qir/Controller/Utility/ILogger.cs | 24 +++++ src/Qir/Controller/Utility/Logger.cs | 41 +++++++ 8 files changed, 216 insertions(+), 10 deletions(-) create mode 100644 src/Qir/Controller/Tests.QirController/LoggerTests.cs create mode 100644 src/Qir/Controller/Utility/Clock.cs create mode 100644 src/Qir/Controller/Utility/IClock.cs create mode 100644 src/Qir/Controller/Utility/ILogger.cs create mode 100644 src/Qir/Controller/Utility/Logger.cs diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index a44ebbcdb14..e0c8f5dfa4c 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -8,6 +8,7 @@ using Microsoft.Quantum.Qir.Driver; using Microsoft.Quantum.Qir.Executable; using Microsoft.Quantum.Qir.Model; +using Microsoft.Quantum.Qir.Utility; using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; namespace Microsoft.Quantum.Qir @@ -22,30 +23,35 @@ public static async Task ExecuteAsync( FileInfo bytecodeFile, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, - IQuantumExecutableRunner executableRunner) + IQuantumExecutableRunner executableRunner, + ILogger logger) { - // TODO: Logging. try { // Step 1: Parse input. + logger.LogInfo("Parsing input."); using var inputFileStream = inputFile.OpenRead(); var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); // Step 2: Create bytecode file. + logger.LogInfo("Creating bytecode file."); using (var bytecodeFileStream = bytecodeFile.OpenWrite()) { await bytecodeFileStream.WriteAsync(input.QirBytecode.Array, input.QirBytecode.Offset, input.QirBytecode.Count); } - // Step 3: Create the driver file. + // Step 3: Create driver file. + logger.LogInfo("Creating driver file."); var driverFile = new FileInfo(Constant.FilePath.DriverFilePath); await driverGenerator.GenerateQirDriverCppAsync(input.EntryPoint, driverFile); - // Step 4: Create the executable. + // Step 4: Create executable. + logger.LogInfo("Compiling and linking executable."); var executableFile = new FileInfo(Constant.FilePath.ExecutableFilePath); await executableGenerator.GenerateExecutableAsync(driverFile, bytecodeFile, libraryDirectory, executableFile); - // Step 5: Run the executable. + // Step 5: Run executable. + logger.LogInfo("Running executable."); using var outputFileStream = outputFile.OpenWrite(); await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); } diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 20a5791de12..1fb847b567d 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -6,6 +6,7 @@ using System.IO; using Microsoft.Quantum.Qir.Driver; using Microsoft.Quantum.Qir.Executable; +using Microsoft.Quantum.Qir.Utility; namespace Microsoft.Quantum.Qir { @@ -54,6 +55,7 @@ static void Main(string[] args) var execGenerator = new QirExecutableGenerator(new ClangClient()); var driverGenerator = new QirDriverGenerator(); var execRunner = new QuantumExecutableRunner(); + var logger = new Logger(new Clock()); // The bytecode file is not needed as an input to the program, but we provide the path as an argument to the controller so it can be configured by tests. var bytecodeFile = new FileInfo(Constant.FilePath.BytecodeFilePath); @@ -61,7 +63,7 @@ static void Main(string[] args) // Bind to a handler and invoke. rootCommand.Handler = CommandHandler.Create( async (input, output, libraryDirectory, error) => - await Controller.ExecuteAsync(input, output, libraryDirectory, error, bytecodeFile, driverGenerator, execGenerator, execRunner)); + await Controller.ExecuteAsync(input, output, libraryDirectory, error, bytecodeFile, driverGenerator, execGenerator, execRunner, logger)); rootCommand.Invoke(args); } } diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 5c60c270cb1..52345d233a0 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -11,6 +11,7 @@ using Microsoft.Quantum.Qir.Driver; using Microsoft.Quantum.Qir.Executable; using Microsoft.Quantum.Qir.Model; +using Microsoft.Quantum.Qir.Utility; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; using Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper; using Moq; @@ -24,6 +25,7 @@ public class ControllerTests : IDisposable private Mock driverGeneratorMock; private Mock executableGeneratorMock; private Mock executableRunnerMock; + private Mock loggerMock; private FileInfo inputFile; private FileInfo bytecodeFile; private FileInfo errorFile; @@ -95,7 +97,8 @@ await Controller.ExecuteAsync( bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, - executableRunnerMock.Object); + executableRunnerMock.Object, + loggerMock.Object); // Verify driver was created. driverGeneratorMock.Verify(obj => obj.GenerateQirDriverCppAsync( @@ -141,7 +144,8 @@ await Controller.ExecuteAsync( bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, - executableRunnerMock.Object); + executableRunnerMock.Object, + loggerMock.Object); // Verify error file was created and contains the error. Assert.True(errorFile.Exists); @@ -174,7 +178,8 @@ await Controller.ExecuteAsync( bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, - executableRunnerMock.Object); + executableRunnerMock.Object, + loggerMock.Object); // Verify error file was created and contains the error. Assert.True(errorFile.Exists); @@ -213,7 +218,8 @@ await Controller.ExecuteAsync( bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, - executableRunnerMock.Object); + executableRunnerMock.Object, + loggerMock.Object); // Verify error file was created and contains the error. Assert.True(errorFile.Exists); diff --git a/src/Qir/Controller/Tests.QirController/LoggerTests.cs b/src/Qir/Controller/Tests.QirController/LoggerTests.cs new file mode 100644 index 00000000000..eb180e7fecc --- /dev/null +++ b/src/Qir/Controller/Tests.QirController/LoggerTests.cs @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir; +using Microsoft.Quantum.Qir.Driver; +using Microsoft.Quantum.Qir.Executable; +using Microsoft.Quantum.Qir.Model; +using Microsoft.Quantum.Qir.Utility; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper; +using Moq; +using Xunit; +using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; + +namespace Tests.QirController +{ + public class LoggerTests + { + private readonly Mock clockMock; + private readonly Logger logger; + + public LoggerTests() + { + clockMock = new Mock(); + logger = new Logger(clockMock.Object); + } + + [Fact] + public void TestLogInfo() + { + using var consoleOutput = new StringWriter(); + var message = "some message"; + clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); + var expectedLog = "1/1/0001 12:00:00 AM +00:00 [INFO]: some message" + Environment.NewLine; + Console.SetOut(consoleOutput); + logger.LogInfo(message); + var actualLog = consoleOutput.ToString(); + Assert.Equal(expectedLog, actualLog); + } + + [Fact] + public void TestLogError() + { + using var consoleOutput = new StringWriter(); + var message = "some message"; + clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); + var expectedLog = "1/1/0001 12:00:00 AM +00:00 [ERROR]: some message" + Environment.NewLine; + Console.SetOut(consoleOutput); + logger.LogError(message); + var actualLog = consoleOutput.ToString(); + Assert.Equal(expectedLog, actualLog); + } + + [Fact] + public void TestLogExceptionWithoutStackTrace() + { + using var consoleOutput = new StringWriter(); + clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); + var exception = new InvalidOperationException(); + var expectedLog = "1/1/0001 12:00:00 AM +00:00 [ERROR]: " + + "Exception encountered: System.InvalidOperationException: " + + exception.Message + Environment.NewLine + exception.StackTrace + Environment.NewLine; + Console.SetOut(consoleOutput); + logger.LogException(exception); + var actualLog = consoleOutput.ToString(); + Assert.Equal(expectedLog, actualLog); + } + + [Fact] + public void TestLogExceptionWithStackTrace() + { + using var consoleOutput = new StringWriter(); + clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); + Exception exception; + try + { + throw new InvalidOperationException(); + } + // Throw exception to generate stack trace. + catch (Exception thrownException) + { + exception = thrownException; + } + + var expectedLog = "1/1/0001 12:00:00 AM +00:00 [ERROR]: " + + "Exception encountered: System.InvalidOperationException: " + + exception.Message + Environment.NewLine + exception.StackTrace + Environment.NewLine; + Console.SetOut(consoleOutput); + logger.LogException(exception); + var actualLog = consoleOutput.ToString(); + Assert.Equal(expectedLog, actualLog); + } + } +} diff --git a/src/Qir/Controller/Utility/Clock.cs b/src/Qir/Controller/Utility/Clock.cs new file mode 100644 index 00000000000..7f1fdc8c78e --- /dev/null +++ b/src/Qir/Controller/Utility/Clock.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Quantum.Qir.Utility +{ + public class Clock : IClock + { + public DateTimeOffset Now => DateTimeOffset.Now; + } +} diff --git a/src/Qir/Controller/Utility/IClock.cs b/src/Qir/Controller/Utility/IClock.cs new file mode 100644 index 00000000000..da69204b74a --- /dev/null +++ b/src/Qir/Controller/Utility/IClock.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Quantum.Qir.Utility +{ + /// + /// Mockable clock interface. + /// + public interface IClock + { + public DateTimeOffset Now { get; } + } +} diff --git a/src/Qir/Controller/Utility/ILogger.cs b/src/Qir/Controller/Utility/ILogger.cs new file mode 100644 index 00000000000..83a0bb86452 --- /dev/null +++ b/src/Qir/Controller/Utility/ILogger.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Qir.Utility +{ + /// + /// Logger for internal traces and errors. + /// + /// For now, this thinly wraps console logging. In the future, this might be extended to log to files or other systems. + public interface ILogger + { + /// + /// Logs a message at the "information" level. + /// + /// Message to log. + void LogInfo(string message); + + /// + /// Logs a message at the "error" level. + /// + /// Message to log. + void LogError(string message); + } +} diff --git a/src/Qir/Controller/Utility/Logger.cs b/src/Qir/Controller/Utility/Logger.cs new file mode 100644 index 00000000000..4aa2074a760 --- /dev/null +++ b/src/Qir/Controller/Utility/Logger.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Quantum.Qir.Utility +{ + public class Logger : ILogger + { + private readonly IClock clock; + + public Logger(IClock clock) + { + this.clock = clock; + } + + // {timestamp} [{log level}]: {message}. + private const string LogFormat = "{0} [{1}]: {2}"; + + // ...{exception type}: {exception message}{Environment.NewLine}{stack trace}. + private const string ExceptionMessageFormat = "Exception encountered: {0}: {1}{2}{3}"; + private const string InfoLevel = "INFO"; + private const string ErrorLevel = "ERROR"; + + public void LogInfo(string message) + { + Console.WriteLine(LogFormat, clock.Now, InfoLevel, message); + } + + public void LogError(string message) + { + Console.WriteLine(LogFormat, clock.Now, ErrorLevel, message); + } + + public void LogException(Exception e) + { + var message = string.Format(ExceptionMessageFormat, e.GetType(), e.Message, Environment.NewLine, e.StackTrace); + LogError(message); + } + } +} From 52cca9f25596b304bb9194005dab7d3a8d15318e Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 8 Apr 2021 15:08:46 -0700 Subject: [PATCH 011/145] Add logs --- src/Qir/Controller/Controller.cs | 2 ++ src/Qir/Controller/Driver/QirDriverGenerator.cs | 8 ++++++++ src/Qir/Controller/Executable/ClangClient.cs | 15 +++++++++++++-- .../Executable/QirExecutableGenerator.cs | 5 ++++- .../Executable/QuantumExecutableRunner.cs | 8 ++++++++ src/Qir/Controller/Program.cs | 11 ++++++----- .../Tests.QirController/ControllerTests.cs | 1 + src/Qir/Controller/Utility/ILogger.cs | 8 ++++++++ 8 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index e0c8f5dfa4c..5849fa99d33 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -57,6 +57,8 @@ public static async Task ExecuteAsync( } catch (Exception e) { + logger.LogError("An error has been encountered. Will write an error to the error file and delete any output that has been generated."); + logger.LogException(e); await WriteExceptionToFileAsync(e, errorFile); outputFile.Delete(); } diff --git a/src/Qir/Controller/Driver/QirDriverGenerator.cs b/src/Qir/Controller/Driver/QirDriverGenerator.cs index 34caeb01f59..75711d7a056 100644 --- a/src/Qir/Controller/Driver/QirDriverGenerator.cs +++ b/src/Qir/Controller/Driver/QirDriverGenerator.cs @@ -3,12 +3,20 @@ using System.IO; using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Utility; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; namespace Microsoft.Quantum.Qir.Driver { public class QirDriverGenerator : IQirDriverGenerator { + private readonly ILogger logger; + + public QirDriverGenerator(ILogger logger) + { + this.logger = logger; + } + public Task GenerateQirDriverCppAsync(EntryPointOperation entryPointOperation, FileInfo driverFile) { throw new System.NotImplementedException(); diff --git a/src/Qir/Controller/Executable/ClangClient.cs b/src/Qir/Controller/Executable/ClangClient.cs index 4a6c993dd86..59693fafdf4 100644 --- a/src/Qir/Controller/Executable/ClangClient.cs +++ b/src/Qir/Controller/Executable/ClangClient.cs @@ -1,22 +1,33 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.CommandLine.Invocation; using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Utility; namespace Microsoft.Quantum.Qir.Executable { public class ClangClient : IClangClient { private const string LinkFlag = " -l "; + private readonly ILogger logger; + + public ClangClient(ILogger logger) + { + this.logger = logger; + } public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string outputPath) { var inputsArg = string.Join(' ', inputFiles); var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; var arguments = $"{inputsArg} -L {libraryPath} {librariesArg} -o {outputPath}"; - var result = await Process.ExecuteAsync("clang", arguments, stdOut: s => { Console.WriteLine(s); }, stdErr: s => { Console.WriteLine(s); }); + logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); + var result = await Process.ExecuteAsync( + "clang", + arguments, + stdOut: s => { logger.LogInfo("clang: " + s); }, + stdErr: s => { logger.LogError("clang: " + s); }); } } } diff --git a/src/Qir/Controller/Executable/QirExecutableGenerator.cs b/src/Qir/Controller/Executable/QirExecutableGenerator.cs index 1b521c6f762..46daf7ebb8a 100644 --- a/src/Qir/Controller/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Controller/Executable/QirExecutableGenerator.cs @@ -3,16 +3,19 @@ using System.IO; using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Utility; namespace Microsoft.Quantum.Qir.Executable { public class QirExecutableGenerator : IQirExecutableGenerator { private readonly IClangClient clangClient; + private readonly ILogger logger; - public QirExecutableGenerator(IClangClient clangClient) + public QirExecutableGenerator(IClangClient clangClient, ILogger logger) { this.clangClient = clangClient; + this.logger = logger; } public Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, FileInfo executableFile) diff --git a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs index 14a35fc8659..774aa0cf517 100644 --- a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs +++ b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs @@ -3,12 +3,20 @@ using System.IO; using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Utility; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; namespace Microsoft.Quantum.Qir.Executable { public class QuantumExecutableRunner : IQuantumExecutableRunner { + private readonly ILogger logger; + + public QuantumExecutableRunner(ILogger logger) + { + this.logger = logger; + } + public Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile) { throw new System.NotImplementedException(); diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 1fb847b567d..92d0041fca1 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -14,6 +14,12 @@ class Program { static void Main(string[] args) { + var logger = new Logger(new Clock()); + var execGenerator = new QirExecutableGenerator(new ClangClient(logger), logger); + var driverGenerator = new QirDriverGenerator(logger); + var execRunner = new QuantumExecutableRunner(logger); + logger.LogInfo("QIR controller beginning."); + var rootCommand = new RootCommand( description: "Builds and runs QIR executable."); @@ -52,11 +58,6 @@ static void Main(string[] args) rootCommand.AddOption(errorOption); - var execGenerator = new QirExecutableGenerator(new ClangClient()); - var driverGenerator = new QirDriverGenerator(); - var execRunner = new QuantumExecutableRunner(); - var logger = new Logger(new Clock()); - // The bytecode file is not needed as an input to the program, but we provide the path as an argument to the controller so it can be configured by tests. var bytecodeFile = new FileInfo(Constant.FilePath.BytecodeFilePath); diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 52345d233a0..2298026d4d6 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -41,6 +41,7 @@ public ControllerTests() bytecodeFile = new FileInfo($"{Guid.NewGuid()}-bytecode"); errorFile = new FileInfo($"{Guid.NewGuid()}-error"); outputFile = new FileInfo($"{Guid.NewGuid()}-output"); + loggerMock = new Mock(); // Create a QirExecutableWrapper to be used by the tests. byte[] bytecode = { 1, 2, 3, 4, 5 }; diff --git a/src/Qir/Controller/Utility/ILogger.cs b/src/Qir/Controller/Utility/ILogger.cs index 83a0bb86452..7049bee9582 100644 --- a/src/Qir/Controller/Utility/ILogger.cs +++ b/src/Qir/Controller/Utility/ILogger.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; + namespace Microsoft.Quantum.Qir.Utility { /// @@ -20,5 +22,11 @@ public interface ILogger /// /// Message to log. void LogError(string message); + + /// + /// Formats an exception into an error log. Logs the exception type, message, and stack trace. + /// + /// Exception to log. + void LogException(Exception e); } } From 351385898af088f58f253595efb375399db6d166 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 8 Apr 2021 16:54:52 -0700 Subject: [PATCH 012/145] Fix warning level --- src/Qir/Controller/QirController.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index 3c7e124c26a..aff9bd1d39c 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -7,7 +7,7 @@ - 5 + 4 From 74fb929cd4425c84ec57577ab38f0097d1651b4c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 9 Apr 2021 09:25:05 -0700 Subject: [PATCH 013/145] Fix unit tests for linux --- .../Tests.QirController/LoggerTests.cs | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Qir/Controller/Tests.QirController/LoggerTests.cs b/src/Qir/Controller/Tests.QirController/LoggerTests.cs index eb180e7fecc..ee7adfee70a 100644 --- a/src/Qir/Controller/Tests.QirController/LoggerTests.cs +++ b/src/Qir/Controller/Tests.QirController/LoggerTests.cs @@ -1,22 +1,11 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; -using System.Collections.Generic; using System.IO; -using System.Reflection; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Quantum.Qir; -using Microsoft.Quantum.Qir.Driver; -using Microsoft.Quantum.Qir.Executable; -using Microsoft.Quantum.Qir.Model; using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; -using Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper; using Moq; using Xunit; -using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; namespace Tests.QirController { @@ -36,8 +25,9 @@ public void TestLogInfo() { using var consoleOutput = new StringWriter(); var message = "some message"; - clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); - var expectedLog = "1/1/0001 12:00:00 AM +00:00 [INFO]: some message" + Environment.NewLine; + var time = DateTimeOffset.MinValue; + clockMock.SetupGet(obj => obj.Now).Returns(time); + var expectedLog = $"{time} [INFO]: some message" + Environment.NewLine; Console.SetOut(consoleOutput); logger.LogInfo(message); var actualLog = consoleOutput.ToString(); @@ -49,8 +39,9 @@ public void TestLogError() { using var consoleOutput = new StringWriter(); var message = "some message"; - clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); - var expectedLog = "1/1/0001 12:00:00 AM +00:00 [ERROR]: some message" + Environment.NewLine; + var time = DateTimeOffset.MinValue; + clockMock.SetupGet(obj => obj.Now).Returns(time); + var expectedLog = $"{time} [ERROR]: some message" + Environment.NewLine; Console.SetOut(consoleOutput); logger.LogError(message); var actualLog = consoleOutput.ToString(); @@ -61,9 +52,10 @@ public void TestLogError() public void TestLogExceptionWithoutStackTrace() { using var consoleOutput = new StringWriter(); - clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); + var time = DateTimeOffset.MinValue; + clockMock.SetupGet(obj => obj.Now).Returns(time); var exception = new InvalidOperationException(); - var expectedLog = "1/1/0001 12:00:00 AM +00:00 [ERROR]: " + + var expectedLog = $"{time} [ERROR]: " + "Exception encountered: System.InvalidOperationException: " + exception.Message + Environment.NewLine + exception.StackTrace + Environment.NewLine; Console.SetOut(consoleOutput); @@ -76,7 +68,8 @@ public void TestLogExceptionWithoutStackTrace() public void TestLogExceptionWithStackTrace() { using var consoleOutput = new StringWriter(); - clockMock.SetupGet(obj => obj.Now).Returns(DateTimeOffset.MinValue); + var time = DateTimeOffset.MinValue; + clockMock.SetupGet(obj => obj.Now).Returns(time); Exception exception; try { @@ -88,7 +81,7 @@ public void TestLogExceptionWithStackTrace() exception = thrownException; } - var expectedLog = "1/1/0001 12:00:00 AM +00:00 [ERROR]: " + + var expectedLog = $"{time} [ERROR]: " + "Exception encountered: System.InvalidOperationException: " + exception.Message + Environment.NewLine + exception.StackTrace + Environment.NewLine; Console.SetOut(consoleOutput); From 66ddfb007f738fe838a736bc3f65b42b9d000344 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 9 Apr 2021 09:27:03 -0700 Subject: [PATCH 014/145] Fix header --- src/Qir/Controller/Tests.QirController/ControllerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 2298026d4d6..69071170985 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; From f2ff7b27f7a38837895b8eaeaabc520e886e0137 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 9 Apr 2021 09:44:39 -0700 Subject: [PATCH 015/145] Add include directory --- src/Qir/Controller/Controller.cs | 5 +++-- src/Qir/Controller/Executable/ClangClient.cs | 4 ++-- src/Qir/Controller/Executable/IClangClient.cs | 2 +- .../Executable/IQirExecutableGenerator.cs | 3 ++- .../Executable/IQuantumExecutableRunner.cs | 3 ++- .../Executable/QirExecutableGenerator.cs | 2 +- .../Executable/QuantumExecutableRunner.cs | 2 +- src/Qir/Controller/Program.cs | 13 ++++++++++--- .../Tests.QirController/ControllerTests.cs | 18 ++++++++++++++---- src/Qir/Controller/test-qir-controller.ps1 | 2 +- 10 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 5849fa99d33..ffa0c0617a1 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -19,6 +19,7 @@ public static async Task ExecuteAsync( FileInfo inputFile, FileInfo outputFile, DirectoryInfo libraryDirectory, + DirectoryInfo includeDirectory, FileInfo errorFile, FileInfo bytecodeFile, IQirDriverGenerator driverGenerator, @@ -48,12 +49,12 @@ public static async Task ExecuteAsync( // Step 4: Create executable. logger.LogInfo("Compiling and linking executable."); var executableFile = new FileInfo(Constant.FilePath.ExecutableFilePath); - await executableGenerator.GenerateExecutableAsync(driverFile, bytecodeFile, libraryDirectory, executableFile); + await executableGenerator.GenerateExecutableAsync(driverFile, bytecodeFile, libraryDirectory, includeDirectory, executableFile); // Step 5: Run executable. logger.LogInfo("Running executable."); using var outputFileStream = outputFile.OpenWrite(); - await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); + await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, libraryDirectory, outputFile); } catch (Exception e) { diff --git a/src/Qir/Controller/Executable/ClangClient.cs b/src/Qir/Controller/Executable/ClangClient.cs index 59693fafdf4..27a13806c3f 100644 --- a/src/Qir/Controller/Executable/ClangClient.cs +++ b/src/Qir/Controller/Executable/ClangClient.cs @@ -17,11 +17,11 @@ public ClangClient(ILogger logger) this.logger = logger; } - public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string outputPath) + public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string includePath, string outputPath) { var inputsArg = string.Join(' ', inputFiles); var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; - var arguments = $"{inputsArg} -L {libraryPath} {librariesArg} -o {outputPath}"; + var arguments = $"{inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath}"; logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); var result = await Process.ExecuteAsync( "clang", diff --git a/src/Qir/Controller/Executable/IClangClient.cs b/src/Qir/Controller/Executable/IClangClient.cs index 313c92f3e89..7e7a8e1c95d 100644 --- a/src/Qir/Controller/Executable/IClangClient.cs +++ b/src/Qir/Controller/Executable/IClangClient.cs @@ -10,6 +10,6 @@ namespace Microsoft.Quantum.Qir.Executable /// public interface IClangClient { - Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string outputPath); + Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string includePath, string outputPath); } } diff --git a/src/Qir/Controller/Executable/IQirExecutableGenerator.cs b/src/Qir/Controller/Executable/IQirExecutableGenerator.cs index 54854cfed21..21aab292831 100644 --- a/src/Qir/Controller/Executable/IQirExecutableGenerator.cs +++ b/src/Qir/Controller/Executable/IQirExecutableGenerator.cs @@ -14,8 +14,9 @@ public interface IQirExecutableGenerator /// The C++ source driver file. /// The QIR bytecode. /// Location of the libraries that must be linked. + /// Location of the headers that must be included. /// File path to create the executable at. /// - Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, FileInfo executableFile); + Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executableFile); } } diff --git a/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs b/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs index 135fbbbfb4f..f74aae5a028 100644 --- a/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs +++ b/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs @@ -14,8 +14,9 @@ public interface IQuantumExecutableRunner /// /// Location of the executable to run. /// Entry point and arguments to pass. + /// Location of the libraries that are linked to the executable. /// Location to write program output. /// - Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile); + Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, DirectoryInfo libraryDirectory, FileInfo outputFile); } } diff --git a/src/Qir/Controller/Executable/QirExecutableGenerator.cs b/src/Qir/Controller/Executable/QirExecutableGenerator.cs index 46daf7ebb8a..59fa798e955 100644 --- a/src/Qir/Controller/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Controller/Executable/QirExecutableGenerator.cs @@ -18,7 +18,7 @@ public QirExecutableGenerator(IClangClient clangClient, ILogger logger) this.logger = logger; } - public Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, FileInfo executableFile) + public Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executableFile) { // TODO: Compile and link libraries- "Microsoft.Quantum.Qir.Runtime", "Microsoft.Quantum.Qir.QSharp.Foundation", "Microsoft.Quantum.Qir.QSharp.Core" throw new System.NotImplementedException(); diff --git a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs index 774aa0cf517..0d7875ead4d 100644 --- a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs +++ b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs @@ -17,7 +17,7 @@ public QuantumExecutableRunner(ILogger logger) this.logger = logger; } - public Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile) + public Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, DirectoryInfo libraryDirectory, FileInfo outputFile) { throw new System.NotImplementedException(); } diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 92d0041fca1..3edddc4cbdf 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -48,6 +48,13 @@ static void Main(string[] args) IsRequired = true }; + var includeDirectoryOption = new Option( + aliases: new string[] { "--includeDirectory" }) + { + Description = "Path to the directory containing headers that must be included by the C++ driver.", + IsRequired = true + }; + rootCommand.AddOption(libraryDirectoryOption); var errorOption = new Option( aliases: new string[] { "--error",}) @@ -62,9 +69,9 @@ static void Main(string[] args) var bytecodeFile = new FileInfo(Constant.FilePath.BytecodeFilePath); // Bind to a handler and invoke. - rootCommand.Handler = CommandHandler.Create( - async (input, output, libraryDirectory, error) => - await Controller.ExecuteAsync(input, output, libraryDirectory, error, bytecodeFile, driverGenerator, execGenerator, execRunner, logger)); + rootCommand.Handler = CommandHandler.Create( + async (input, output, libraryDirectory, includeDirectory, error) => + await Controller.ExecuteAsync(input, output, libraryDirectory, includeDirectory, error, bytecodeFile, driverGenerator, execGenerator, execRunner, logger)); rootCommand.Invoke(args); } } diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 69071170985..5eafd144888 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -77,9 +77,10 @@ public void Dispose() public async Task TestExecute() { var libraryDirectory = new DirectoryInfo("libraries"); + var includeDirectory = new DirectoryInfo("includes"); var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Callback(() => + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Callback(() => { // Verify that the "bytecode" file was created correctly. using var bytecode = bytecodeFile.OpenRead(); @@ -94,6 +95,7 @@ await Controller.ExecuteAsync( inputFile, outputFile, libraryDirectory, + includeDirectory, errorFile, bytecodeFile, driverGeneratorMock.Object, @@ -111,12 +113,14 @@ await Controller.ExecuteAsync( It.Is(driverPath => driverPath.FullName == expectedDriverPath.FullName), It.Is(actualBytecodeFile => actualBytecodeFile.FullName == bytecodeFile.FullName), It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), + It.Is(actualIncludeDirectory => actualIncludeDirectory.FullName == includeDirectory.FullName), It.Is(actualExecutableFile => actualExecutableFile.FullName == expectedExecutablePath.FullName))); // Verify executable was run. executableRunnerMock.Verify(obj => obj.RunExecutableAsync( It.Is(actualExecutableFile => actualExecutableFile.FullName == expectedExecutablePath.FullName), It.Is(entryPoint => EntryPointsAreEqual(entryPoint, input.EntryPoint)), + It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), It.Is(actualOutputFile => actualOutputFile.FullName == outputFile.FullName))); } @@ -124,9 +128,10 @@ await Controller.ExecuteAsync( public async Task TestExecuteEncountersGenericExceptionWithOutputFileAlreadyCreated() { var libraryDirectory = new DirectoryInfo("libraries"); + var includeDirectory = new DirectoryInfo("includes"); var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception("exception message")); // Create output file to ensure that it will be deleted unconditionally. @@ -141,6 +146,7 @@ await Controller.ExecuteAsync( inputFile, outputFile, libraryDirectory, + includeDirectory, errorFile, bytecodeFile, driverGeneratorMock.Object, @@ -165,9 +171,10 @@ await Controller.ExecuteAsync( public async Task TestExecuteEncountersGenericExceptionWithOutputFileNeverCreated() { var libraryDirectory = new DirectoryInfo("libraries"); + var includeDirectory = new DirectoryInfo("includes"); var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception("exception message")); // Execute controller. @@ -175,6 +182,7 @@ await Controller.ExecuteAsync( inputFile, outputFile, libraryDirectory, + includeDirectory, errorFile, bytecodeFile, driverGeneratorMock.Object, @@ -198,9 +206,10 @@ public async Task TestExecuteEncountersControllerException() var exceptionMessage = "exception message"; var errorCode = "error code"; var libraryDirectory = new DirectoryInfo("libraries"); + var includeDirectory = new DirectoryInfo("includes"); var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new ControllerException(exceptionMessage, errorCode)); // Create output file to ensure that it will be deleted unconditionally. @@ -215,6 +224,7 @@ await Controller.ExecuteAsync( inputFile, outputFile, libraryDirectory, + includeDirectory, errorFile, bytecodeFile, driverGeneratorMock.Object, diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index 5b96a520b96..824c8ad4bba 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -20,7 +20,7 @@ Foreach-Object { # Get the paths to the output and error files to pass to the QIR controller. $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) - dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile --libraryDirectory "placeholder for now" + dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile --includeDirectory "placeholder for now" --libraryDirectory "placeholder for now" # Compare the expected content of the output and error files vs the actual content. $expectedOutputFile = (Join-Path $testCasesFolder ($_.BaseName + ".out")) From 0b1936607b5a51b477dd1d924472fdc9c54517db Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 9 Apr 2021 09:49:17 -0700 Subject: [PATCH 016/145] Clean up and fix input --- src/Qir/Controller/Program.cs | 3 ++- src/Qir/Controller/QirController.csproj | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 3edddc4cbdf..6448ebcc678 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -48,6 +48,7 @@ static void Main(string[] args) IsRequired = true }; + rootCommand.AddOption(libraryDirectoryOption); var includeDirectoryOption = new Option( aliases: new string[] { "--includeDirectory" }) { @@ -55,7 +56,7 @@ static void Main(string[] args) IsRequired = true }; - rootCommand.AddOption(libraryDirectoryOption); + rootCommand.AddOption(includeDirectoryOption); var errorOption = new Option( aliases: new string[] { "--error",}) { diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index aff9bd1d39c..4570cafa210 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -6,10 +6,6 @@ Microsoft.Quantum.Qir - - 4 - - From ae18d34ad636789fb6b488569c041a000de5609b Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 9 Apr 2021 12:05:05 -0700 Subject: [PATCH 017/145] Change how directories are passed --- src/Qir/Controller/Constant.cs | 8 --- src/Qir/Controller/Controller.cs | 29 ++++---- .../Controller/Driver/IQirDriverGenerator.cs | 8 ++- .../Controller/Driver/QirDriverGenerator.cs | 5 +- .../Executable/IQirExecutableGenerator.cs | 7 +- .../Executable/IQuantumExecutableRunner.cs | 3 +- .../Executable/QirExecutableGenerator.cs | 2 +- .../Executable/QuantumExecutableRunner.cs | 2 +- src/Qir/Controller/Program.cs | 5 +- .../Tests.QirController/ControllerTests.cs | 69 ++++++++++--------- 10 files changed, 66 insertions(+), 72 deletions(-) diff --git a/src/Qir/Controller/Constant.cs b/src/Qir/Controller/Constant.cs index 13cb9b2cef1..23d5a8ba351 100644 --- a/src/Qir/Controller/Constant.cs +++ b/src/Qir/Controller/Constant.cs @@ -5,14 +5,6 @@ namespace Microsoft.Quantum.Qir { public static class Constant { - public static class FilePath - { - // TODO validate/improve these names. - public const string BytecodeFilePath = "/home/bytecode.ll"; - public const string DriverFilePath = "/home/driver.cpp"; - public const string ExecutableFilePath = "/home/simulation.exe"; - } - // TODO: errors will be added as dependencies are implemented. public static class ErrorCode { diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index ffa0c0617a1..463c28014a4 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -15,13 +15,16 @@ namespace Microsoft.Quantum.Qir { public static class Controller { + private const string SourceDirectoryPath = "src"; + private const string BinaryDirectoryPath = "bin"; + private const string ExecutableName = "simulation.exe"; + public static async Task ExecuteAsync( FileInfo inputFile, FileInfo outputFile, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo errorFile, - FileInfo bytecodeFile, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner executableRunner, @@ -34,27 +37,21 @@ public static async Task ExecuteAsync( using var inputFileStream = inputFile.OpenRead(); var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); - // Step 2: Create bytecode file. - logger.LogInfo("Creating bytecode file."); - using (var bytecodeFileStream = bytecodeFile.OpenWrite()) - { - await bytecodeFileStream.WriteAsync(input.QirBytecode.Array, input.QirBytecode.Offset, input.QirBytecode.Count); - } - - // Step 3: Create driver file. + // Step 32: Create driver. logger.LogInfo("Creating driver file."); - var driverFile = new FileInfo(Constant.FilePath.DriverFilePath); - await driverGenerator.GenerateQirDriverCppAsync(input.EntryPoint, driverFile); + var sourceDirectory = new DirectoryInfo(SourceDirectoryPath); + await driverGenerator.GenerateQirDriverCppAsync(sourceDirectory, input.EntryPoint, input.QirBytecode); - // Step 4: Create executable. + // Step 3: Create executable. logger.LogInfo("Compiling and linking executable."); - var executableFile = new FileInfo(Constant.FilePath.ExecutableFilePath); - await executableGenerator.GenerateExecutableAsync(driverFile, bytecodeFile, libraryDirectory, includeDirectory, executableFile); + var binaryDirectory = new DirectoryInfo(BinaryDirectoryPath); + var executableFile = new FileInfo(Path.Combine(BinaryDirectoryPath, ExecutableName)); + await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, libraryDirectory, includeDirectory); - // Step 5: Run executable. + // Step 4: Run executable. logger.LogInfo("Running executable."); using var outputFileStream = outputFile.OpenWrite(); - await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, libraryDirectory, outputFile); + await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); } catch (Exception e) { diff --git a/src/Qir/Controller/Driver/IQirDriverGenerator.cs b/src/Qir/Controller/Driver/IQirDriverGenerator.cs index 5e26df14ee5..e4dc2a6172c 100644 --- a/src/Qir/Controller/Driver/IQirDriverGenerator.cs +++ b/src/Qir/Controller/Driver/IQirDriverGenerator.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; @@ -10,11 +11,12 @@ namespace Microsoft.Quantum.Qir.Driver public interface IQirDriverGenerator { /// - /// Generates the C++ driver source file to compile with the bytecode. + /// Generates the C++ driver source file and writes the bytecode to a file. /// + /// Directory to which driver and bytecode will be written. /// Entry point information. - /// The file to which the source will be written. + /// The QIR bytecode. /// - Task GenerateQirDriverCppAsync(EntryPointOperation entryPointOperation, FileInfo driverFile); + Task GenerateQirDriverCppAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode); } } diff --git a/src/Qir/Controller/Driver/QirDriverGenerator.cs b/src/Qir/Controller/Driver/QirDriverGenerator.cs index 75711d7a056..e169ea12be4 100644 --- a/src/Qir/Controller/Driver/QirDriverGenerator.cs +++ b/src/Qir/Controller/Driver/QirDriverGenerator.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; @@ -17,9 +18,9 @@ public QirDriverGenerator(ILogger logger) this.logger = logger; } - public Task GenerateQirDriverCppAsync(EntryPointOperation entryPointOperation, FileInfo driverFile) + public Task GenerateQirDriverCppAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } } } diff --git a/src/Qir/Controller/Executable/IQirExecutableGenerator.cs b/src/Qir/Controller/Executable/IQirExecutableGenerator.cs index 21aab292831..e8ce44f7b7a 100644 --- a/src/Qir/Controller/Executable/IQirExecutableGenerator.cs +++ b/src/Qir/Controller/Executable/IQirExecutableGenerator.cs @@ -11,12 +11,11 @@ public interface IQirExecutableGenerator /// /// Generates a quantum simulation program executable. /// - /// The C++ source driver file. - /// The QIR bytecode. + /// File path to create the executable at. Dependencies will be copied to its directory. + /// Location of the source files. /// Location of the libraries that must be linked. /// Location of the headers that must be included. - /// File path to create the executable at. /// - Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executableFile); + public Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory); } } diff --git a/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs b/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs index f74aae5a028..135fbbbfb4f 100644 --- a/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs +++ b/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs @@ -14,9 +14,8 @@ public interface IQuantumExecutableRunner /// /// Location of the executable to run. /// Entry point and arguments to pass. - /// Location of the libraries that are linked to the executable. /// Location to write program output. /// - Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, DirectoryInfo libraryDirectory, FileInfo outputFile); + Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile); } } diff --git a/src/Qir/Controller/Executable/QirExecutableGenerator.cs b/src/Qir/Controller/Executable/QirExecutableGenerator.cs index 59fa798e955..c09a7a0fa67 100644 --- a/src/Qir/Controller/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Controller/Executable/QirExecutableGenerator.cs @@ -18,7 +18,7 @@ public QirExecutableGenerator(IClangClient clangClient, ILogger logger) this.logger = logger; } - public Task GenerateExecutableAsync(FileInfo driverFile, FileInfo bytecodeFile, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executableFile) + public Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) { // TODO: Compile and link libraries- "Microsoft.Quantum.Qir.Runtime", "Microsoft.Quantum.Qir.QSharp.Foundation", "Microsoft.Quantum.Qir.QSharp.Core" throw new System.NotImplementedException(); diff --git a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs index 0d7875ead4d..774aa0cf517 100644 --- a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs +++ b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs @@ -17,7 +17,7 @@ public QuantumExecutableRunner(ILogger logger) this.logger = logger; } - public Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, DirectoryInfo libraryDirectory, FileInfo outputFile) + public Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile) { throw new System.NotImplementedException(); } diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 6448ebcc678..88677d0d1ce 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -66,13 +66,10 @@ static void Main(string[] args) rootCommand.AddOption(errorOption); - // The bytecode file is not needed as an input to the program, but we provide the path as an argument to the controller so it can be configured by tests. - var bytecodeFile = new FileInfo(Constant.FilePath.BytecodeFilePath); - // Bind to a handler and invoke. rootCommand.Handler = CommandHandler.Create( async (input, output, libraryDirectory, includeDirectory, error) => - await Controller.ExecuteAsync(input, output, libraryDirectory, includeDirectory, error, bytecodeFile, driverGenerator, execGenerator, execRunner, logger)); + await Controller.ExecuteAsync(input, output, libraryDirectory, includeDirectory, error, driverGenerator, execGenerator, execRunner, logger)); rootCommand.Invoke(args); } } diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 5eafd144888..6475d753913 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -78,18 +78,17 @@ public async Task TestExecute() { var libraryDirectory = new DirectoryInfo("libraries"); var includeDirectory = new DirectoryInfo("includes"); - var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); - var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Callback(() => + FileInfo actualExecutableFile = null; + Action generateExecutableCallback = async (executableFile, srcDir, libDir, inclDir) => { - // Verify that the "bytecode" file was created correctly. - using var bytecode = bytecodeFile.OpenRead(); - Assert.Equal(bytecode.Length, input.QirBytecode.Count); - for (var i = 0; i < bytecode.Length; ++i) - { - Assert.Equal(input.QirBytecode[i], bytecode.ReadByte()); - } - }); + actualExecutableFile = executableFile; + await Task.CompletedTask; + }; + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync( + It.IsAny(), + It.IsAny(), + It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), + It.Is(actualIncludeDirectory => actualIncludeDirectory.FullName == includeDirectory.FullName))).Callback(generateExecutableCallback); await Controller.ExecuteAsync( inputFile, @@ -97,7 +96,6 @@ await Controller.ExecuteAsync( libraryDirectory, includeDirectory, errorFile, - bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, executableRunnerMock.Object, @@ -105,22 +103,22 @@ await Controller.ExecuteAsync( // Verify driver was created. driverGeneratorMock.Verify(obj => obj.GenerateQirDriverCppAsync( + It.IsAny(), It.Is(entryPoint => EntryPointsAreEqual(entryPoint, input.EntryPoint)), - It.Is(fileInfo => fileInfo.FullName == expectedDriverPath.FullName))); + It.Is>(bytecode => BytecodesAreEqual(bytecode, input.QirBytecode)))); // Verify executable was generated. executableGeneratorMock.Verify(obj => obj.GenerateExecutableAsync( - It.Is(driverPath => driverPath.FullName == expectedDriverPath.FullName), - It.Is(actualBytecodeFile => actualBytecodeFile.FullName == bytecodeFile.FullName), + It.IsAny(), + It.IsAny(), It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), - It.Is(actualIncludeDirectory => actualIncludeDirectory.FullName == includeDirectory.FullName), - It.Is(actualExecutableFile => actualExecutableFile.FullName == expectedExecutablePath.FullName))); + It.Is(actualIncludeDirectory => actualIncludeDirectory.FullName == includeDirectory.FullName))); + Assert.NotNull(actualExecutableFile); // Verify executable was run. executableRunnerMock.Verify(obj => obj.RunExecutableAsync( - It.Is(actualExecutableFile => actualExecutableFile.FullName == expectedExecutablePath.FullName), + It.Is(executableFile => actualExecutableFile.FullName == executableFile.FullName), It.Is(entryPoint => EntryPointsAreEqual(entryPoint, input.EntryPoint)), - It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), It.Is(actualOutputFile => actualOutputFile.FullName == outputFile.FullName))); } @@ -129,9 +127,7 @@ public async Task TestExecuteEncountersGenericExceptionWithOutputFileAlreadyCrea { var libraryDirectory = new DirectoryInfo("libraries"); var includeDirectory = new DirectoryInfo("includes"); - var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); - var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception("exception message")); // Create output file to ensure that it will be deleted unconditionally. @@ -148,7 +144,6 @@ await Controller.ExecuteAsync( libraryDirectory, includeDirectory, errorFile, - bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, executableRunnerMock.Object, @@ -172,9 +167,7 @@ public async Task TestExecuteEncountersGenericExceptionWithOutputFileNeverCreate { var libraryDirectory = new DirectoryInfo("libraries"); var includeDirectory = new DirectoryInfo("includes"); - var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); - var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception("exception message")); // Execute controller. @@ -184,7 +177,6 @@ await Controller.ExecuteAsync( libraryDirectory, includeDirectory, errorFile, - bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, executableRunnerMock.Object, @@ -207,9 +199,7 @@ public async Task TestExecuteEncountersControllerException() var errorCode = "error code"; var libraryDirectory = new DirectoryInfo("libraries"); var includeDirectory = new DirectoryInfo("includes"); - var expectedDriverPath = new FileInfo(Constant.FilePath.DriverFilePath); - var expectedExecutablePath = new FileInfo(Constant.FilePath.ExecutableFilePath); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new ControllerException(exceptionMessage, errorCode)); // Create output file to ensure that it will be deleted unconditionally. @@ -226,7 +216,6 @@ await Controller.ExecuteAsync( libraryDirectory, includeDirectory, errorFile, - bytecodeFile, driverGeneratorMock.Object, executableGeneratorMock.Object, executableRunnerMock.Object, @@ -252,5 +241,23 @@ private bool EntryPointsAreEqual(EntryPointOperation entryPointA, EntryPointOper object[] parameters = { entryPointA, entryPointB }; return (bool)method.Invoke(null, parameters); } + + private bool BytecodesAreEqual(ArraySegment bytecodeA, ArraySegment bytecodeB) + { + if (bytecodeA.Count != bytecodeB.Count) + { + return false; + } + + for (var i = 0; i < bytecodeA.Count; ++i) + { + if (bytecodeA[i] != bytecodeB[i]) + { + return false; + } + } + + return true; + } } } From ef1a2f8e5091cfde94a245d2a8b84a08274dfa70 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 9 Apr 2021 12:05:48 -0700 Subject: [PATCH 018/145] Add comment --- src/Qir/Controller/Executable/ClangClient.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Qir/Controller/Executable/ClangClient.cs b/src/Qir/Controller/Executable/ClangClient.cs index 27a13806c3f..72fc903d4e8 100644 --- a/src/Qir/Controller/Executable/ClangClient.cs +++ b/src/Qir/Controller/Executable/ClangClient.cs @@ -20,6 +20,8 @@ public ClangClient(ILogger logger) public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string includePath, string outputPath) { var inputsArg = string.Join(' ', inputFiles); + + // string.Join does not automatically prepend the delimiter, so it is included again in the string here. var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; var arguments = $"{inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath}"; logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); From ce030fab3de69659a7b5d5f21d1524122fbaa168 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 9 Apr 2021 14:32:34 -0700 Subject: [PATCH 019/145] Do not delete output file on error --- src/Qir/Controller/Controller.cs | 1 - .../Tests.QirController/ControllerTests.cs | 52 +------------------ src/Qir/Controller/test-qir-controller.ps1 | 18 ------- 3 files changed, 1 insertion(+), 70 deletions(-) diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 463c28014a4..5f9cc2b65cc 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -58,7 +58,6 @@ public static async Task ExecuteAsync( logger.LogError("An error has been encountered. Will write an error to the error file and delete any output that has been generated."); logger.LogException(e); await WriteExceptionToFileAsync(e, errorFile); - outputFile.Delete(); } } diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 6475d753913..5da9e861d37 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -123,47 +123,7 @@ await Controller.ExecuteAsync( } [Fact] - public async Task TestExecuteEncountersGenericExceptionWithOutputFileAlreadyCreated() - { - var libraryDirectory = new DirectoryInfo("libraries"); - var includeDirectory = new DirectoryInfo("includes"); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("exception message")); - - // Create output file to ensure that it will be deleted unconditionally. - using (var outputFileStream = outputFile.OpenWrite()) - using (var streamWriter = new StreamWriter(outputFileStream)) - { - await streamWriter.WriteAsync("program output"); - } - - // Execute controller. - await Controller.ExecuteAsync( - inputFile, - outputFile, - libraryDirectory, - includeDirectory, - errorFile, - driverGeneratorMock.Object, - executableGeneratorMock.Object, - executableRunnerMock.Object, - loggerMock.Object); - - // Verify error file was created and contains the error. - Assert.True(errorFile.Exists); - using var errorFileStream = errorFile.OpenRead(); - using var streamReader = new StreamReader(errorFileStream); - var errorFileContents = await streamReader.ReadToEndAsync(); - var error = JsonSerializer.Deserialize(errorFileContents); - Assert.Equal(ErrorMessages.InternalError, error.Message); - Assert.Equal(Constant.ErrorCode.InternalError, error.Code); - - // Verify output file was deleted. - Assert.False(outputFile.Exists); - } - - [Fact] - public async Task TestExecuteEncountersGenericExceptionWithOutputFileNeverCreated() + public async Task TestExecuteEncountersGenericException() { var libraryDirectory = new DirectoryInfo("libraries"); var includeDirectory = new DirectoryInfo("includes"); @@ -202,13 +162,6 @@ public async Task TestExecuteEncountersControllerException() executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new ControllerException(exceptionMessage, errorCode)); - // Create output file to ensure that it will be deleted unconditionally. - using (var outputFileStream = outputFile.OpenWrite()) - using (var streamWriter = new StreamWriter(outputFileStream)) - { - await streamWriter.WriteAsync("program output"); - } - // Execute controller. await Controller.ExecuteAsync( inputFile, @@ -229,9 +182,6 @@ await Controller.ExecuteAsync( var error = JsonSerializer.Deserialize(errorFileContents); Assert.Equal(exceptionMessage, error.Message); Assert.Equal(errorCode, error.Code); - - // Verify output file was deleted. - Assert.False(outputFile.Exists); } private bool EntryPointsAreEqual(EntryPointOperation entryPointA, EntryPointOperation entryPointB) diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index 824c8ad4bba..ad70d23d1b7 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -37,15 +37,6 @@ Foreach-Object { Write-Host $actualOutput $script:all_ok = $False } - elseif ((Test-Path $errorFile)) { - $actualError = Get-Content -Path $errorFile -Raw - - # An error file should not have been generated, so fail test if one was found. - Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" - Write-Host "##[info]Unexpected error file was found:" - Write-Host $actualError - $script:all_ok = $False - } else { Write-Host "##[info]Test case '$($_.BaseName)' passed" } @@ -63,15 +54,6 @@ Foreach-Object { $script:all_ok = $False continue } - elseif ((Test-Path $outputFile)) { - $actualOutput = Get-Content -Path $outputFile -Raw - - # An error file should not have been generated, so fail test if one was found. - Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" - Write-Host "##[info]Unexpected output file was found:" - Write-Host $actualOutput - $script:all_ok = $False - } else { Write-Host "##[info]Test case '$($_.BaseName)' passed" } From 22d1b23d83bb3e5005cbf5db55808870ba85051a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Mon, 12 Apr 2021 20:04:22 -0700 Subject: [PATCH 020/145] Create IQirMachine interface. --- src/Simulation/Core/IAzureMachine.cs | 28 ++++++++++++++++++ src/Simulation/Core/IQirMachine.cs | 43 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/Simulation/Core/IAzureMachine.cs create mode 100644 src/Simulation/Core/IQirMachine.cs diff --git a/src/Simulation/Core/IAzureMachine.cs b/src/Simulation/Core/IAzureMachine.cs new file mode 100644 index 00000000000..c92f18290e4 --- /dev/null +++ b/src/Simulation/Core/IAzureMachine.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.Quantum.Simulation.Core; + +namespace Microsoft.Quantum.Runtime +{ + public interface IAzureMachine + { + /// + /// Function that configures a job object before submission. + /// + public delegate void ConfigureJob(object job); + + /// + /// Gets the ID of the quantum machine provider. + /// + string ProviderId { get; } + + /// + /// Gets the name of the target quantum machine. + /// A provider may expose multiple targets that can be used to execute programs. + /// Users may select which target they would like to be used for execution. + /// + string Target { get; } + } +} diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs new file mode 100644 index 00000000000..0a633dd5435 --- /dev/null +++ b/src/Simulation/Core/IQirMachine.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.Quantum.Simulation.Core; + +namespace Microsoft.Quantum.Runtime +{ + public interface IQirMachine : IAzureMachine + { + /// + /// Submits a job to execute a Q# program. + /// Does not wait for execution to be completed. + /// + /// Information about the Q# program. + /// Input for the Q# program. + /// Input for the Q# program. + /// Type of input the quantum program receives. + /// Type of output the quantum program returns. + /// An object that implements the IQuantumMachineJob interface through which data about the job can be obtained. + Task SubmitAsync( + EntryPointInfo info, + TInput input, + byte[] qir) => SubmitAsync(info, input, qir, null); + + /// + /// Submits a job to execute a Q# program. + /// Does not wait for execution to be completed. + /// + /// Information about the Q# program. + /// Input for the Q# program. + /// Input for the Q# program. + /// Function that configures a job object before submission. + /// Type of input the quantum program receives. + /// Type of output the quantum program returns. + /// An object that implements the IQuantumMachineJob interface through which data about the job can be obtained. + Task SubmitAsync( + EntryPointInfo info, + TInput input, + byte[] qir, + ConfigureJob configureJobCallback); + } +} From 7df14c5a97f4cf751a6775849cb671b077be3231 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 13 Apr 2021 17:01:08 -0700 Subject: [PATCH 021/145] Remove ConfigureJob, IQuantumMachine inherits IAzureMachine --- src/Simulation/Core/IAzureMachine.cs | 8 ------ src/Simulation/Core/IQirMachine.cs | 36 +++++++------------------- src/Simulation/Core/IQuantumMachine.cs | 15 +---------- 3 files changed, 11 insertions(+), 48 deletions(-) diff --git a/src/Simulation/Core/IAzureMachine.cs b/src/Simulation/Core/IAzureMachine.cs index c92f18290e4..d161055cc8d 100644 --- a/src/Simulation/Core/IAzureMachine.cs +++ b/src/Simulation/Core/IAzureMachine.cs @@ -1,18 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Threading.Tasks; -using Microsoft.Quantum.Simulation.Core; - namespace Microsoft.Quantum.Runtime { public interface IAzureMachine { - /// - /// Function that configures a job object before submission. - /// - public delegate void ConfigureJob(object job); - /// /// Gets the ID of the quantum machine provider. /// diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 0a633dd5435..99dbe0fc75c 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -9,35 +9,19 @@ namespace Microsoft.Quantum.Runtime public interface IQirMachine : IAzureMachine { /// - /// Submits a job to execute a Q# program. - /// Does not wait for execution to be completed. + /// Submits a job to execute a QIR program. Does not wait for execution to be completed. /// - /// Information about the Q# program. - /// Input for the Q# program. - /// Input for the Q# program. - /// Type of input the quantum program receives. - /// Type of output the quantum program returns. - /// An object that implements the IQuantumMachineJob interface through which data about the job can be obtained. + /// The entry point information. + /// The input to the entry point. + /// The QIR program as a byte string. + /// Type of input the QIR program receives. + /// Type of output the QIR program returns. + /// + /// An object that implements the IQuantumMachineJob interface through which data about the job can be obtained. + /// Task SubmitAsync( EntryPointInfo info, TInput input, - byte[] qir) => SubmitAsync(info, input, qir, null); - - /// - /// Submits a job to execute a Q# program. - /// Does not wait for execution to be completed. - /// - /// Information about the Q# program. - /// Input for the Q# program. - /// Input for the Q# program. - /// Function that configures a job object before submission. - /// Type of input the quantum program receives. - /// Type of output the quantum program returns. - /// An object that implements the IQuantumMachineJob interface through which data about the job can be obtained. - Task SubmitAsync( - EntryPointInfo info, - TInput input, - byte[] qir, - ConfigureJob configureJobCallback); + byte[] qir); } } diff --git a/src/Simulation/Core/IQuantumMachine.cs b/src/Simulation/Core/IQuantumMachine.cs index 0e7cc236692..2d81d39ec0a 100644 --- a/src/Simulation/Core/IQuantumMachine.cs +++ b/src/Simulation/Core/IQuantumMachine.cs @@ -9,26 +9,13 @@ namespace Microsoft.Quantum.Runtime /// /// Interface that a quantum machine must implement. /// - public interface IQuantumMachine + public interface IQuantumMachine : IAzureMachine { - /// /// Function that configures a job object before submission. /// public delegate void ConfigureJob(object job); - /// - /// Gets the ID of the quantum machine provider. - /// - string ProviderId { get; } - - /// - /// Gets the name of the target quantum machine. - /// A provider may expose multiple targets that can be used to execute programs. - /// Users may select which target they would like to be used for execution. - /// - string Target { get; } - /// /// Executes a Q# program. /// Submits a job to execute it and continuously checks whether it has been completed. From 15f485b812be395d6e362dd0faab093440cd4340 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 13 Apr 2021 17:27:14 -0700 Subject: [PATCH 022/145] Use Stream --- src/Simulation/Core/IQirMachine.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 99dbe0fc75c..3f2534be19e 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; @@ -13,7 +14,7 @@ public interface IQirMachine : IAzureMachine /// /// The entry point information. /// The input to the entry point. - /// The QIR program as a byte string. + /// The QIR program as a byte stream. /// Type of input the QIR program receives. /// Type of output the QIR program returns. /// @@ -22,6 +23,6 @@ public interface IQirMachine : IAzureMachine Task SubmitAsync( EntryPointInfo info, TInput input, - byte[] qir); + Stream qir); } } From 4ad0265f44e3c258cde6db39cd197418d3d48610 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 13 Apr 2021 18:12:29 -0700 Subject: [PATCH 023/145] Add Argument class --- src/Simulation/Core/IQirMachine.cs | 95 ++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 3f2534be19e..773a599af38 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -1,28 +1,99 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; +using Core = Microsoft.Quantum.Simulation.Core; namespace Microsoft.Quantum.Runtime { public interface IQirMachine : IAzureMachine { /// - /// Submits a job to execute a QIR program. Does not wait for execution to be completed. + /// Submits a job to execute a QIR program without waiting for execution to complete. /// - /// The entry point information. - /// The input to the entry point. /// The QIR program as a byte stream. - /// Type of input the QIR program receives. - /// Type of output the QIR program returns. - /// - /// An object that implements the IQuantumMachineJob interface through which data about the job can be obtained. - /// - Task SubmitAsync( - EntryPointInfo info, - TInput input, - Stream qir); + /// The fully-qualified name of the entry point to execute. + /// The arguments to the entry point. + /// The submitted job. + Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments); + } + + public class Argument + { + public string Name { get; } + + public ArgumentValue Value { get; } + + public Argument(string name, ArgumentValue value) + { + this.Name = name; + this.Value = value; + } + } + + public abstract class ArgumentValue + { + private ArgumentValue() + { + } + + public class Bool : ArgumentValue + { + public bool Value { get; } + + public Bool(bool value) => this.Value = value; + } + + public class Int : ArgumentValue + { + public long Value { get; } + + public Int(long value) => this.Value = value; + } + + public class Double : ArgumentValue + { + public double Value { get; } + + public Double(double value) => this.Value = value; + } + + public class Pauli : ArgumentValue + { + public Core.Pauli Value { get; } + + public Pauli(Core.Pauli value) => this.Value = value; + } + + public class Range : ArgumentValue + { + public QRange Value { get; } + + public Range(QRange value) => this.Value = value; + } + + public class Result : ArgumentValue + { + public Core.Result Value { get; } + + public Result(Core.Result value) => this.Value = value; + } + + public class String : ArgumentValue + { + public string Value { get; } + + public String(string value) => this.Value = value; + } + + public class Array : ArgumentValue + { + public QArray Values { get; } + + public Array(QArray values) => this.Values = values; + } } } From dc7c79a5aa8619745dbec7afa8b2a1afd24ec7b0 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 13 Apr 2021 18:18:54 -0700 Subject: [PATCH 024/145] Use IQArray --- src/Simulation/Core/IQirMachine.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 773a599af38..32dea97378e 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -43,57 +43,49 @@ private ArgumentValue() public class Bool : ArgumentValue { public bool Value { get; } - public Bool(bool value) => this.Value = value; } public class Int : ArgumentValue { public long Value { get; } - public Int(long value) => this.Value = value; } public class Double : ArgumentValue { public double Value { get; } - public Double(double value) => this.Value = value; } public class Pauli : ArgumentValue { public Core.Pauli Value { get; } - public Pauli(Core.Pauli value) => this.Value = value; } public class Range : ArgumentValue { public QRange Value { get; } - public Range(QRange value) => this.Value = value; } public class Result : ArgumentValue { public Core.Result Value { get; } - public Result(Core.Result value) => this.Value = value; } public class String : ArgumentValue { public string Value { get; } - public String(string value) => this.Value = value; } public class Array : ArgumentValue { - public QArray Values { get; } - - public Array(QArray values) => this.Values = values; + public IQArray Values { get; } + public Array(IQArray values) => this.Values = values; } } } From 1e4129dc84bac733e7819d8be2383763e90c5350 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 13 Apr 2021 18:25:33 -0700 Subject: [PATCH 025/145] Tuple assignment --- src/Simulation/Core/IQirMachine.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 32dea97378e..22049b42046 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -27,11 +27,7 @@ public class Argument public ArgumentValue Value { get; } - public Argument(string name, ArgumentValue value) - { - this.Name = name; - this.Value = value; - } + public Argument(string name, ArgumentValue value) => (this.Name, this.Value) = (name, value); } public abstract class ArgumentValue @@ -43,48 +39,56 @@ private ArgumentValue() public class Bool : ArgumentValue { public bool Value { get; } + public Bool(bool value) => this.Value = value; } public class Int : ArgumentValue { public long Value { get; } + public Int(long value) => this.Value = value; } public class Double : ArgumentValue { public double Value { get; } + public Double(double value) => this.Value = value; } public class Pauli : ArgumentValue { public Core.Pauli Value { get; } + public Pauli(Core.Pauli value) => this.Value = value; } public class Range : ArgumentValue { public QRange Value { get; } + public Range(QRange value) => this.Value = value; } public class Result : ArgumentValue { public Core.Result Value { get; } + public Result(Core.Result value) => this.Value = value; } public class String : ArgumentValue { public string Value { get; } + public String(string value) => this.Value = value; } public class Array : ArgumentValue { public IQArray Values { get; } + public Array(IQArray values) => this.Values = values; } } From 9d3a929decb6d10fd2af78cfd89cd13675c42ed6 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 14 Apr 2021 13:47:00 -0700 Subject: [PATCH 026/145] Add doc comments --- src/Simulation/Core/IQirMachine.cs | 102 ++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 22049b42046..39802fa95b1 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -9,6 +9,9 @@ namespace Microsoft.Quantum.Runtime { + /// + /// A machine that can submit QIR programs to Azure. + /// public interface IQirMachine : IAzureMachine { /// @@ -16,79 +19,176 @@ public interface IQirMachine : IAzureMachine /// /// The QIR program as a byte stream. /// The fully-qualified name of the entry point to execute. - /// The arguments to the entry point. + /// The arguments to the entry point in the order in which they are declared. /// The submitted job. Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments); } + /// + /// An argument to a QIR callable. + /// public class Argument { + /// + /// The name of the argument. + /// public string Name { get; } + /// + /// The value of the argument. + /// public ArgumentValue Value { get; } + /// + /// Creates a new argument. + /// + /// The name of the argument. + /// The value of the argument. public Argument(string name, ArgumentValue value) => (this.Name, this.Value) = (name, value); } + /// + /// The value of an argument to a QIR callable is a discriminated union of the argument types. + /// public abstract class ArgumentValue { private ArgumentValue() { } + /// + /// A boolean argument value. + /// public class Bool : ArgumentValue { + /// + /// The value of the argument. + /// public bool Value { get; } + /// + /// Creates a boolean argument value. + /// + /// The value of the argument. public Bool(bool value) => this.Value = value; } + /// + /// An integer argument value. + /// public class Int : ArgumentValue { + /// + /// The value of the argument. + /// public long Value { get; } + /// + /// Creates an integer argument value. + /// + /// The value of the argument. public Int(long value) => this.Value = value; } + /// + /// A double-precision floating point argument value. + /// public class Double : ArgumentValue { + /// + /// The value of the argument. + /// public double Value { get; } + /// + /// Creates a double-precision floating point argument value. + /// + /// The value of the argument. public Double(double value) => this.Value = value; } + /// + /// A Pauli operator argument value. + /// public class Pauli : ArgumentValue { + /// + /// The value of the argument. + /// public Core.Pauli Value { get; } + /// + /// Creates a Pauli operator argument value. + /// + /// The value of the argument. public Pauli(Core.Pauli value) => this.Value = value; } + /// + /// A range argument value. + /// public class Range : ArgumentValue { + /// + /// The value of the argument. + /// public QRange Value { get; } + /// + /// Creates a range argument value. + /// + /// The value of the argument. public Range(QRange value) => this.Value = value; } + /// + /// A result argument value. + /// public class Result : ArgumentValue { + /// + /// The value of the argument. + /// public Core.Result Value { get; } + /// + /// Creates a result argument value. + /// + /// The value of the argument. public Result(Core.Result value) => this.Value = value; } + /// + /// A string argument value. + /// public class String : ArgumentValue { + /// + /// The value of the argument. + /// public string Value { get; } + /// + /// Creates a string argument value. + /// + /// The value of the argument. public String(string value) => this.Value = value; } + /// + /// An array argument value. + /// public class Array : ArgumentValue { + /// + /// The values of the argument. + /// public IQArray Values { get; } + /// + /// Creates an array argument value. + /// + /// The values of the argument. public Array(IQArray values) => this.Values = values; } } From eb763a06e3695fbc55e6c08ee77ea2bfb1698752 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 14 Apr 2021 13:47:53 -0700 Subject: [PATCH 027/145] Enable nullable --- src/Simulation/Core/IAzureMachine.cs | 2 ++ src/Simulation/Core/IQirMachine.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Simulation/Core/IAzureMachine.cs b/src/Simulation/Core/IAzureMachine.cs index d161055cc8d..f73baacbd0d 100644 --- a/src/Simulation/Core/IAzureMachine.cs +++ b/src/Simulation/Core/IAzureMachine.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable + namespace Microsoft.Quantum.Runtime { public interface IAzureMachine diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 39802fa95b1..4c5a0734988 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable + using System.Collections.Generic; using System.IO; using System.Threading.Tasks; From 76d02d6f829b98042862d0fc1f311bc71350954f Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 14 Apr 2021 13:52:55 -0700 Subject: [PATCH 028/145] Add doc comment to IAzureMachine --- src/Simulation/Core/IAzureMachine.cs | 3 +++ src/Simulation/Core/IQirMachine.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Simulation/Core/IAzureMachine.cs b/src/Simulation/Core/IAzureMachine.cs index f73baacbd0d..f5444521e7b 100644 --- a/src/Simulation/Core/IAzureMachine.cs +++ b/src/Simulation/Core/IAzureMachine.cs @@ -5,6 +5,9 @@ namespace Microsoft.Quantum.Runtime { + /// + /// A machine that can execute quantum programs on Azure. + /// public interface IAzureMachine { /// diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 4c5a0734988..4e2ed5de478 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -12,7 +12,7 @@ namespace Microsoft.Quantum.Runtime { /// - /// A machine that can submit QIR programs to Azure. + /// A machine that can execute QIR programs on Azure. /// public interface IQirMachine : IAzureMachine { From 3542f8863b27edeabcb8dc1a9bba657722174f9c Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 14 Apr 2021 22:39:31 -0700 Subject: [PATCH 029/145] Enforce array homogeneity --- src/Simulation/Core/IQirMachine.cs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 4e2ed5de478..698dce20521 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -3,8 +3,10 @@ #nullable enable +using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; using Core = Microsoft.Quantum.Simulation.Core; @@ -178,7 +180,7 @@ public class String : ArgumentValue } /// - /// An array argument value. + /// An array argument value where all values in the array are of the same type. /// public class Array : ArgumentValue { @@ -191,7 +193,26 @@ public class Array : ArgumentValue /// Creates an array argument value. /// /// The values of the argument. - public Array(IQArray values) => this.Values = values; + /// The array values are not all of the same type. + public Array(IQArray values) => + this.Values = IsHomogeneous(values) + ? values + : throw new ArgumentException("The array values are not all of the same type."); + + private static bool IsHomogeneous(IQArray values) => values + .Zip(values.Skip(1), ValueTuple.Create) + .All(pair => pair switch + { + (Bool _, Bool _) => true, + (Int _, Int _) => true, + (Double _, Double _) => true, + (Pauli _, Pauli _) => true, + (Range _, Range _) => true, + (Result _, Result _) => true, + (String _, String _) => true, + (Array _, Array _) => true, + _ => false + }); } } } From 3e524d3d5b741956f7cd64b271bfcdd78482456b Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 14 Apr 2021 22:57:40 -0700 Subject: [PATCH 030/145] Avoid exception --- src/Simulation/Core/IQirMachine.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 698dce20521..5b2c046dcbc 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -180,7 +180,7 @@ public class String : ArgumentValue } /// - /// An array argument value where all values in the array are of the same type. + /// An array argument value where all values are of the same type. /// public class Array : ArgumentValue { @@ -189,15 +189,15 @@ public class Array : ArgumentValue /// public IQArray Values { get; } + private Array(IQArray values) => this.Values = values; + /// - /// Creates an array argument value. + /// Tries to create an array argument value. /// /// The values of the argument. - /// The array values are not all of the same type. - public Array(IQArray values) => - this.Values = IsHomogeneous(values) - ? values - : throw new ArgumentException("The array values are not all of the same type."); + /// The array or null if not all values are of the same type. + public static Array? TryCreate(IQArray values) => + IsHomogeneous(values) ? new Array(values) : null; private static bool IsHomogeneous(IQArray values) => values .Zip(values.Skip(1), ValueTuple.Create) From 0269a6ef897165ecfea733e4a4405e08b64ac079 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Apr 2021 14:57:35 -0700 Subject: [PATCH 031/145] Fix array homogeneity check --- src/Simulation/Core/IQirMachine.cs | 126 ++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 19 deletions(-) diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 5b2c046dcbc..7a1ab53137a 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; using Core = Microsoft.Quantum.Simulation.Core; @@ -51,11 +52,90 @@ public class Argument public Argument(string name, ArgumentValue value) => (this.Name, this.Value) = (name, value); } + /// + /// The type of an argument to a QIR callable. + /// + public class ArgumentType + { + private ArgumentType() + { + } + + /// + /// The boolean type. + /// + public static ArgumentType Bool { get; } = new ArgumentType(); + + /// + /// The integer type. + /// + public static ArgumentType Int { get; } = new ArgumentType(); + + /// + /// The double-precision floating point type. + /// + public static ArgumentType Double { get; } = new ArgumentType(); + + /// + /// The Pauli operator type. + /// + public static ArgumentType Pauli { get; } = new ArgumentType(); + + /// + /// The range type. + /// + public static ArgumentType Range { get; } = new ArgumentType(); + + /// + /// The result type. + /// + public static ArgumentType Result { get; } = new ArgumentType(); + + /// + /// The string type. + /// + public static ArgumentType String { get; } = new ArgumentType(); + + /// + /// The array type. + /// + public class Array : ArgumentType + { + /// + /// The type of the array items. + /// + public ArgumentType Item { get; } + + /// + /// Creates a new array type. + /// + /// The type of the array items. + public Array(ArgumentType item) => this.Item = item; + + public override bool Equals(object obj) => obj is Array array && this.Item.Equals(array.Item); + + public override int GetHashCode() => HashCode.Combine(1, this.Item.GetHashCode()); + } + + public override bool Equals(object obj) => ReferenceEquals(this, obj); + + public override int GetHashCode() => RuntimeHelpers.GetHashCode(this); + + public static bool operator ==(ArgumentType lhs, ArgumentType rhs) => lhs.Equals(rhs); + + public static bool operator !=(ArgumentType lhs, ArgumentType rhs) => !(lhs == rhs); + } + /// /// The value of an argument to a QIR callable is a discriminated union of the argument types. /// public abstract class ArgumentValue { + /// + /// The type of the argument. + /// + public abstract ArgumentType Type { get; } + private ArgumentValue() { } @@ -70,6 +150,8 @@ public class Bool : ArgumentValue /// public bool Value { get; } + public override ArgumentType Type => ArgumentType.Bool; + /// /// Creates a boolean argument value. /// @@ -87,6 +169,8 @@ public class Int : ArgumentValue /// public long Value { get; } + public override ArgumentType Type => ArgumentType.Int; + /// /// Creates an integer argument value. /// @@ -104,6 +188,8 @@ public class Double : ArgumentValue /// public double Value { get; } + public override ArgumentType Type => ArgumentType.Double; + /// /// Creates a double-precision floating point argument value. /// @@ -121,6 +207,8 @@ public class Pauli : ArgumentValue /// public Core.Pauli Value { get; } + public override ArgumentType Type => ArgumentType.Pauli; + /// /// Creates a Pauli operator argument value. /// @@ -138,6 +226,8 @@ public class Range : ArgumentValue /// public QRange Value { get; } + public override ArgumentType Type => ArgumentType.Range; + /// /// Creates a range argument value. /// @@ -155,6 +245,8 @@ public class Result : ArgumentValue /// public Core.Result Value { get; } + public override ArgumentType Type => ArgumentType.Result; + /// /// Creates a result argument value. /// @@ -172,6 +264,8 @@ public class String : ArgumentValue /// public string Value { get; } + public override ArgumentType Type => ArgumentType.String; + /// /// Creates a string argument value. /// @@ -189,30 +283,24 @@ public class Array : ArgumentValue /// public IQArray Values { get; } - private Array(IQArray values) => this.Values = values; + /// + /// The type of the array items. + /// + public ArgumentType ItemType { get; } + + public override ArgumentType Type => new ArgumentType.Array(this.ItemType); + + private Array(IQArray values, ArgumentType itemType) => + (this.Values, this.ItemType) = (values, itemType); /// /// Tries to create an array argument value. /// /// The values of the argument. - /// The array or null if not all values are of the same type. - public static Array? TryCreate(IQArray values) => - IsHomogeneous(values) ? new Array(values) : null; - - private static bool IsHomogeneous(IQArray values) => values - .Zip(values.Skip(1), ValueTuple.Create) - .All(pair => pair switch - { - (Bool _, Bool _) => true, - (Int _, Int _) => true, - (Double _, Double _) => true, - (Pauli _, Pauli _) => true, - (Range _, Range _) => true, - (Result _, Result _) => true, - (String _, String _) => true, - (Array _, Array _) => true, - _ => false - }); + /// The type of the values. + /// The array or null if not all values have the type . + public static Array? TryCreate(IQArray values, ArgumentType itemType) => + values.All(value => value.Type == itemType) ? new Array(values, itemType) : null; } } } From fc5d5fe1ab0a4edfb00d9fbd93c038852eb9242e Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Apr 2021 17:02:51 -0700 Subject: [PATCH 032/145] Use separate files for argument classes --- src/Simulation/Core/Argument.cs | 30 +++ src/Simulation/Core/ArgumentType.cs | 84 ++++++++ src/Simulation/Core/ArgumentValue.cs | 188 ++++++++++++++++++ src/Simulation/Core/IQirMachine.cs | 280 --------------------------- 4 files changed, 302 insertions(+), 280 deletions(-) create mode 100644 src/Simulation/Core/Argument.cs create mode 100644 src/Simulation/Core/ArgumentType.cs create mode 100644 src/Simulation/Core/ArgumentValue.cs diff --git a/src/Simulation/Core/Argument.cs b/src/Simulation/Core/Argument.cs new file mode 100644 index 00000000000..b7ef2efbff5 --- /dev/null +++ b/src/Simulation/Core/Argument.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +namespace Microsoft.Quantum.Runtime +{ + /// + /// An argument to a QIR callable. + /// + public class Argument + { + /// + /// The name of the argument. + /// + public string Name { get; } + + /// + /// The value of the argument. + /// + public ArgumentValue Value { get; } + + /// + /// Creates a new argument. + /// + /// The name of the argument. + /// The value of the argument. + public Argument(string name, ArgumentValue value) => (this.Name, this.Value) = (name, value); + } +} diff --git a/src/Simulation/Core/ArgumentType.cs b/src/Simulation/Core/ArgumentType.cs new file mode 100644 index 00000000000..b2e9f03dba4 --- /dev/null +++ b/src/Simulation/Core/ArgumentType.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Runtime.CompilerServices; + +namespace Microsoft.Quantum.Runtime +{ + /// + /// The type of an argument to a QIR callable. + /// + public class ArgumentType + { + private ArgumentType() + { + } + + /// + /// The boolean type. + /// + public static ArgumentType Bool { get; } = new ArgumentType(); + + /// + /// The integer type. + /// + public static ArgumentType Int { get; } = new ArgumentType(); + + /// + /// The double-precision floating point type. + /// + public static ArgumentType Double { get; } = new ArgumentType(); + + /// + /// The Pauli operator type. + /// + public static ArgumentType Pauli { get; } = new ArgumentType(); + + /// + /// The range type. + /// + public static ArgumentType Range { get; } = new ArgumentType(); + + /// + /// The result type. + /// + public static ArgumentType Result { get; } = new ArgumentType(); + + /// + /// The string type. + /// + public static ArgumentType String { get; } = new ArgumentType(); + + /// + /// The array type. + /// + public class Array : ArgumentType + { + /// + /// The type of the array items. + /// + public ArgumentType Item { get; } + + /// + /// Creates a new array type. + /// + /// The type of the array items. + public Array(ArgumentType item) => this.Item = item; + + public override bool Equals(object obj) => obj is Array array && this.Item.Equals(array.Item); + + public override int GetHashCode() => HashCode.Combine(1, this.Item.GetHashCode()); + } + + public override bool Equals(object obj) => ReferenceEquals(this, obj); + + public override int GetHashCode() => RuntimeHelpers.GetHashCode(this); + + public static bool operator ==(ArgumentType lhs, ArgumentType rhs) => lhs.Equals(rhs); + + public static bool operator !=(ArgumentType lhs, ArgumentType rhs) => !(lhs == rhs); + } +} diff --git a/src/Simulation/Core/ArgumentValue.cs b/src/Simulation/Core/ArgumentValue.cs new file mode 100644 index 00000000000..33f5f4c85dd --- /dev/null +++ b/src/Simulation/Core/ArgumentValue.cs @@ -0,0 +1,188 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Linq; +using Microsoft.Quantum.Simulation.Core; + +namespace Microsoft.Quantum.Runtime +{ + /// + /// The value of an argument to a QIR callable is a discriminated union of the argument types. + /// + public abstract class ArgumentValue + { + /// + /// The type of the argument. + /// + public abstract ArgumentType Type { get; } + + private ArgumentValue() + { + } + + /// + /// A boolean argument value. + /// + public class Bool : ArgumentValue + { + /// + /// The value of the argument. + /// + public bool Value { get; } + + public override ArgumentType Type => ArgumentType.Bool; + + /// + /// Creates a boolean argument value. + /// + /// The value of the argument. + public Bool(bool value) => this.Value = value; + } + + /// + /// An integer argument value. + /// + public class Int : ArgumentValue + { + /// + /// The value of the argument. + /// + public long Value { get; } + + public override ArgumentType Type => ArgumentType.Int; + + /// + /// Creates an integer argument value. + /// + /// The value of the argument. + public Int(long value) => this.Value = value; + } + + /// + /// A double-precision floating point argument value. + /// + public class Double : ArgumentValue + { + /// + /// The value of the argument. + /// + public double Value { get; } + + public override ArgumentType Type => ArgumentType.Double; + + /// + /// Creates a double-precision floating point argument value. + /// + /// The value of the argument. + public Double(double value) => this.Value = value; + } + + /// + /// A Pauli operator argument value. + /// + public class Pauli : ArgumentValue + { + /// + /// The value of the argument. + /// + public Simulation.Core.Pauli Value { get; } + + public override ArgumentType Type => ArgumentType.Pauli; + + /// + /// Creates a Pauli operator argument value. + /// + /// The value of the argument. + public Pauli(Simulation.Core.Pauli value) => this.Value = value; + } + + /// + /// A range argument value. + /// + public class Range : ArgumentValue + { + /// + /// The value of the argument. + /// + public QRange Value { get; } + + public override ArgumentType Type => ArgumentType.Range; + + /// + /// Creates a range argument value. + /// + /// The value of the argument. + public Range(QRange value) => this.Value = value; + } + + /// + /// A result argument value. + /// + public class Result : ArgumentValue + { + /// + /// The value of the argument. + /// + public Simulation.Core.Result Value { get; } + + public override ArgumentType Type => ArgumentType.Result; + + /// + /// Creates a result argument value. + /// + /// The value of the argument. + public Result(Simulation.Core.Result value) => this.Value = value; + } + + /// + /// A string argument value. + /// + public class String : ArgumentValue + { + /// + /// The value of the argument. + /// + public string Value { get; } + + public override ArgumentType Type => ArgumentType.String; + + /// + /// Creates a string argument value. + /// + /// The value of the argument. + public String(string value) => this.Value = value; + } + + /// + /// An array argument value where all values are of the same type. + /// + public class Array : ArgumentValue + { + /// + /// The values of the argument. + /// + public IQArray Values { get; } + + /// + /// The type of the array items. + /// + public ArgumentType ItemType { get; } + + public override ArgumentType Type => new ArgumentType.Array(this.ItemType); + + private Array(IQArray values, ArgumentType itemType) => + (this.Values, this.ItemType) = (values, itemType); + + /// + /// Tries to create an array argument value. + /// + /// The values of the argument. + /// The type of the values. + /// The array or null if not all values have the type . + public static Array? TryCreate(IQArray values, ArgumentType itemType) => + values.All(value => value.Type == itemType) ? new Array(values, itemType) : null; + } + } +} diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirMachine.cs index 7a1ab53137a..1519990852c 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirMachine.cs @@ -3,14 +3,9 @@ #nullable enable -using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.Quantum.Simulation.Core; -using Core = Microsoft.Quantum.Simulation.Core; namespace Microsoft.Quantum.Runtime { @@ -28,279 +23,4 @@ public interface IQirMachine : IAzureMachine /// The submitted job. Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments); } - - /// - /// An argument to a QIR callable. - /// - public class Argument - { - /// - /// The name of the argument. - /// - public string Name { get; } - - /// - /// The value of the argument. - /// - public ArgumentValue Value { get; } - - /// - /// Creates a new argument. - /// - /// The name of the argument. - /// The value of the argument. - public Argument(string name, ArgumentValue value) => (this.Name, this.Value) = (name, value); - } - - /// - /// The type of an argument to a QIR callable. - /// - public class ArgumentType - { - private ArgumentType() - { - } - - /// - /// The boolean type. - /// - public static ArgumentType Bool { get; } = new ArgumentType(); - - /// - /// The integer type. - /// - public static ArgumentType Int { get; } = new ArgumentType(); - - /// - /// The double-precision floating point type. - /// - public static ArgumentType Double { get; } = new ArgumentType(); - - /// - /// The Pauli operator type. - /// - public static ArgumentType Pauli { get; } = new ArgumentType(); - - /// - /// The range type. - /// - public static ArgumentType Range { get; } = new ArgumentType(); - - /// - /// The result type. - /// - public static ArgumentType Result { get; } = new ArgumentType(); - - /// - /// The string type. - /// - public static ArgumentType String { get; } = new ArgumentType(); - - /// - /// The array type. - /// - public class Array : ArgumentType - { - /// - /// The type of the array items. - /// - public ArgumentType Item { get; } - - /// - /// Creates a new array type. - /// - /// The type of the array items. - public Array(ArgumentType item) => this.Item = item; - - public override bool Equals(object obj) => obj is Array array && this.Item.Equals(array.Item); - - public override int GetHashCode() => HashCode.Combine(1, this.Item.GetHashCode()); - } - - public override bool Equals(object obj) => ReferenceEquals(this, obj); - - public override int GetHashCode() => RuntimeHelpers.GetHashCode(this); - - public static bool operator ==(ArgumentType lhs, ArgumentType rhs) => lhs.Equals(rhs); - - public static bool operator !=(ArgumentType lhs, ArgumentType rhs) => !(lhs == rhs); - } - - /// - /// The value of an argument to a QIR callable is a discriminated union of the argument types. - /// - public abstract class ArgumentValue - { - /// - /// The type of the argument. - /// - public abstract ArgumentType Type { get; } - - private ArgumentValue() - { - } - - /// - /// A boolean argument value. - /// - public class Bool : ArgumentValue - { - /// - /// The value of the argument. - /// - public bool Value { get; } - - public override ArgumentType Type => ArgumentType.Bool; - - /// - /// Creates a boolean argument value. - /// - /// The value of the argument. - public Bool(bool value) => this.Value = value; - } - - /// - /// An integer argument value. - /// - public class Int : ArgumentValue - { - /// - /// The value of the argument. - /// - public long Value { get; } - - public override ArgumentType Type => ArgumentType.Int; - - /// - /// Creates an integer argument value. - /// - /// The value of the argument. - public Int(long value) => this.Value = value; - } - - /// - /// A double-precision floating point argument value. - /// - public class Double : ArgumentValue - { - /// - /// The value of the argument. - /// - public double Value { get; } - - public override ArgumentType Type => ArgumentType.Double; - - /// - /// Creates a double-precision floating point argument value. - /// - /// The value of the argument. - public Double(double value) => this.Value = value; - } - - /// - /// A Pauli operator argument value. - /// - public class Pauli : ArgumentValue - { - /// - /// The value of the argument. - /// - public Core.Pauli Value { get; } - - public override ArgumentType Type => ArgumentType.Pauli; - - /// - /// Creates a Pauli operator argument value. - /// - /// The value of the argument. - public Pauli(Core.Pauli value) => this.Value = value; - } - - /// - /// A range argument value. - /// - public class Range : ArgumentValue - { - /// - /// The value of the argument. - /// - public QRange Value { get; } - - public override ArgumentType Type => ArgumentType.Range; - - /// - /// Creates a range argument value. - /// - /// The value of the argument. - public Range(QRange value) => this.Value = value; - } - - /// - /// A result argument value. - /// - public class Result : ArgumentValue - { - /// - /// The value of the argument. - /// - public Core.Result Value { get; } - - public override ArgumentType Type => ArgumentType.Result; - - /// - /// Creates a result argument value. - /// - /// The value of the argument. - public Result(Core.Result value) => this.Value = value; - } - - /// - /// A string argument value. - /// - public class String : ArgumentValue - { - /// - /// The value of the argument. - /// - public string Value { get; } - - public override ArgumentType Type => ArgumentType.String; - - /// - /// Creates a string argument value. - /// - /// The value of the argument. - public String(string value) => this.Value = value; - } - - /// - /// An array argument value where all values are of the same type. - /// - public class Array : ArgumentValue - { - /// - /// The values of the argument. - /// - public IQArray Values { get; } - - /// - /// The type of the array items. - /// - public ArgumentType ItemType { get; } - - public override ArgumentType Type => new ArgumentType.Array(this.ItemType); - - private Array(IQArray values, ArgumentType itemType) => - (this.Values, this.ItemType) = (values, itemType); - - /// - /// Tries to create an array argument value. - /// - /// The values of the argument. - /// The type of the values. - /// The array or null if not all values have the type . - public static Array? TryCreate(IQArray values, ArgumentType itemType) => - values.All(value => value.Type == itemType) ? new Array(values, itemType) : null; - } - } } From 78c09c6bce8c3a73a7ed4f1aa99fa33118097f75 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Apr 2021 18:45:42 -0700 Subject: [PATCH 033/145] Remove ArgumentValue.Array.ItemType property --- src/Simulation/Core/ArgumentValue.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Simulation/Core/ArgumentValue.cs b/src/Simulation/Core/ArgumentValue.cs index 33f5f4c85dd..0a7e36de1ac 100644 --- a/src/Simulation/Core/ArgumentValue.cs +++ b/src/Simulation/Core/ArgumentValue.cs @@ -165,15 +165,10 @@ public class Array : ArgumentValue /// public IQArray Values { get; } - /// - /// The type of the array items. - /// - public ArgumentType ItemType { get; } - - public override ArgumentType Type => new ArgumentType.Array(this.ItemType); + public override ArgumentType Type { get; } - private Array(IQArray values, ArgumentType itemType) => - (this.Values, this.ItemType) = (values, itemType); + private Array(IQArray values, ArgumentType itemType) => + (this.Values, this.Type) = (values, new ArgumentType.Array(itemType)); /// /// Tries to create an array argument value. From 66f9fc3ea8a39bca0c8532c65f62d7b153839ab7 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Apr 2021 18:46:56 -0700 Subject: [PATCH 034/145] Shorter qualified names --- src/Simulation/Core/ArgumentValue.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Simulation/Core/ArgumentValue.cs b/src/Simulation/Core/ArgumentValue.cs index 0a7e36de1ac..b5ba4d5d62d 100644 --- a/src/Simulation/Core/ArgumentValue.cs +++ b/src/Simulation/Core/ArgumentValue.cs @@ -5,6 +5,7 @@ using System.Linq; using Microsoft.Quantum.Simulation.Core; +using Core = Microsoft.Quantum.Simulation.Core; namespace Microsoft.Quantum.Runtime { @@ -87,7 +88,7 @@ public class Pauli : ArgumentValue /// /// The value of the argument. /// - public Simulation.Core.Pauli Value { get; } + public Core.Pauli Value { get; } public override ArgumentType Type => ArgumentType.Pauli; @@ -95,7 +96,7 @@ public class Pauli : ArgumentValue /// Creates a Pauli operator argument value. /// /// The value of the argument. - public Pauli(Simulation.Core.Pauli value) => this.Value = value; + public Pauli(Core.Pauli value) => this.Value = value; } /// @@ -125,7 +126,7 @@ public class Result : ArgumentValue /// /// The value of the argument. /// - public Simulation.Core.Result Value { get; } + public Core.Result Value { get; } public override ArgumentType Type => ArgumentType.Result; @@ -133,7 +134,7 @@ public class Result : ArgumentValue /// Creates a result argument value. /// /// The value of the argument. - public Result(Simulation.Core.Result value) => this.Value = value; + public Result(Core.Result value) => this.Value = value; } /// From 87fd479e63d2deb1198bb3ce01d2ddacefcf5325 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Apr 2021 19:08:41 -0700 Subject: [PATCH 035/145] Use ImmutableArray --- src/Simulation/Core/ArgumentValue.cs | 7 ++++--- src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Simulation/Core/ArgumentValue.cs b/src/Simulation/Core/ArgumentValue.cs index b5ba4d5d62d..7769e8fbdea 100644 --- a/src/Simulation/Core/ArgumentValue.cs +++ b/src/Simulation/Core/ArgumentValue.cs @@ -3,6 +3,7 @@ #nullable enable +using System.Collections.Immutable; using System.Linq; using Microsoft.Quantum.Simulation.Core; using Core = Microsoft.Quantum.Simulation.Core; @@ -164,11 +165,11 @@ public class Array : ArgumentValue /// /// The values of the argument. /// - public IQArray Values { get; } + public ImmutableArray Values { get; } public override ArgumentType Type { get; } - private Array(IQArray values, ArgumentType itemType) => + private Array(ImmutableArray values, ArgumentType itemType) => (this.Values, this.Type) = (values, new ArgumentType.Array(itemType)); /// @@ -177,7 +178,7 @@ private Array(IQArray values, ArgumentType itemType) => /// The values of the argument. /// The type of the values. /// The array or null if not all values have the type . - public static Array? TryCreate(IQArray values, ArgumentType itemType) => + public static Array? TryCreate(ImmutableArray values, ArgumentType itemType) => values.All(value => value.Type == itemType) ? new Array(values, itemType) : null; } } diff --git a/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj b/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj index b5169a63955..866adc91ba0 100644 --- a/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj +++ b/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj @@ -18,6 +18,7 @@ + From d23898536de57b8dd6cc3fb4c18375ac869dc3c8 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Apr 2021 20:57:13 -0700 Subject: [PATCH 036/145] Remove == overload --- src/Simulation/Core/ArgumentType.cs | 13 +------------ src/Simulation/Core/ArgumentValue.cs | 2 +- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/Simulation/Core/ArgumentType.cs b/src/Simulation/Core/ArgumentType.cs index b2e9f03dba4..7dc2db55f22 100644 --- a/src/Simulation/Core/ArgumentType.cs +++ b/src/Simulation/Core/ArgumentType.cs @@ -3,9 +3,6 @@ #nullable enable -using System; -using System.Runtime.CompilerServices; - namespace Microsoft.Quantum.Runtime { /// @@ -70,15 +67,7 @@ public class Array : ArgumentType public override bool Equals(object obj) => obj is Array array && this.Item.Equals(array.Item); - public override int GetHashCode() => HashCode.Combine(1, this.Item.GetHashCode()); + public override int GetHashCode() => this.Item.GetHashCode() + 1; } - - public override bool Equals(object obj) => ReferenceEquals(this, obj); - - public override int GetHashCode() => RuntimeHelpers.GetHashCode(this); - - public static bool operator ==(ArgumentType lhs, ArgumentType rhs) => lhs.Equals(rhs); - - public static bool operator !=(ArgumentType lhs, ArgumentType rhs) => !(lhs == rhs); } } diff --git a/src/Simulation/Core/ArgumentValue.cs b/src/Simulation/Core/ArgumentValue.cs index 7769e8fbdea..8f9c713b29b 100644 --- a/src/Simulation/Core/ArgumentValue.cs +++ b/src/Simulation/Core/ArgumentValue.cs @@ -179,7 +179,7 @@ private Array(ImmutableArray values, ArgumentType itemType) => /// The type of the values. /// The array or null if not all values have the type . public static Array? TryCreate(ImmutableArray values, ArgumentType itemType) => - values.All(value => value.Type == itemType) ? new Array(values, itemType) : null; + values.All(value => value.Type.Equals(itemType)) ? new Array(values, itemType) : null; } } } From fc5c8b017a3a4c5a79a23dc3069ebfc0e680a776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 16 Apr 2021 12:59:07 -0700 Subject: [PATCH 037/145] Base for Microsoft.Quantum.Qir.Tools package. --- Simulation.sln | 22 +++++++++++++++++++ .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 7 ++++++ src/Qir/Execution/Tools/QirExecutable.cs | 10 +++++++++ .../Execution/Tools/QirFullStateExecutable.cs | 9 ++++++++ 4 files changed, 48 insertions(+) create mode 100644 src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj create mode 100644 src/Qir/Execution/Tools/QirExecutable.cs create mode 100644 src/Qir/Execution/Tools/QirFullStateExecutable.cs diff --git a/Simulation.sln b/Simulation.sln index 7f2fab57378..8bf6718fb86 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -119,6 +119,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirController", "src\Qir\Co EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.QirController", "src\Qir\Controller\Tests.QirController\Tests.QirController.csproj", "{2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Execution", "Execution", "{442E66C8-F69F-44E9-9CD9-1F52C37EA41B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools\Microsoft.Quantum.Qir.Tools.csproj", "{C60226E3-98DE-4E92-AED4-B4A93D4CA063}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -787,6 +791,22 @@ Global {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|x64.ActiveCfg = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|x64.Build.0 = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|Any CPU.Build.0 = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|x64.ActiveCfg = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Release|x64.Build.0 = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -843,6 +863,8 @@ Global {4E07F247-ED93-4497-8B58-022314308E67} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {A77E6661-D143-4E3E-BCD1-8E321A966829} = {4E07F247-ED93-4497-8B58-022314308E67} {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68} = {4E07F247-ED93-4497-8B58-022314308E67} + {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} + {C60226E3-98DE-4E92-AED4-B4A93D4CA063} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj new file mode 100644 index 00000000000..cb631906963 --- /dev/null +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp3.1 + + + diff --git a/src/Qir/Execution/Tools/QirExecutable.cs b/src/Qir/Execution/Tools/QirExecutable.cs new file mode 100644 index 00000000000..4a8acb88f62 --- /dev/null +++ b/src/Qir/Execution/Tools/QirExecutable.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Qir.Tools +{ + public abstract class QirExecutable + { + + } +} diff --git a/src/Qir/Execution/Tools/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/QirFullStateExecutable.cs new file mode 100644 index 00000000000..117a09ee9d5 --- /dev/null +++ b/src/Qir/Execution/Tools/QirFullStateExecutable.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Qir.Tools +{ + public class QirFullStateExecutable : QirExecutable + { + } +} From d2937ee03448b3b672197d474c314435e389ffdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 16 Apr 2021 13:23:34 -0700 Subject: [PATCH 038/145] Included build methods. --- .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 4 ++++ src/Qir/Execution/Tools/QirExecutable.cs | 21 +++++++++++++++++++ .../Execution/Tools/QirFullStateExecutable.cs | 19 +++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index cb631906963..c07b9da92ed 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -4,4 +4,8 @@ netcoreapp3.1 + + + + diff --git a/src/Qir/Execution/Tools/QirExecutable.cs b/src/Qir/Execution/Tools/QirExecutable.cs index 4a8acb88f62..1582ee44891 100644 --- a/src/Qir/Execution/Tools/QirExecutable.cs +++ b/src/Qir/Execution/Tools/QirExecutable.cs @@ -1,10 +1,31 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using System; +using System.Collections.Generic; +using System.IO; + namespace Microsoft.Quantum.Qir.Tools { public abstract class QirExecutable { + private readonly EntryPointOperation EntryPointOperation; + private readonly byte[] QirBytecode; + + public QirExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) + { + this.EntryPointOperation = entryPoint; + this.QirBytecode = qirBytecode; + } + + public void Build(FileInfo executable, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) + { + throw new NotImplementedException(); + } + + protected abstract void GenerateDriver(Stream driver); + protected abstract IList GetLinkLibraries(); } } diff --git a/src/Qir/Execution/Tools/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/QirFullStateExecutable.cs index 117a09ee9d5..911daa66042 100644 --- a/src/Qir/Execution/Tools/QirFullStateExecutable.cs +++ b/src/Qir/Execution/Tools/QirFullStateExecutable.cs @@ -1,9 +1,28 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using System; +using System.Collections.Generic; +using System.IO; + namespace Microsoft.Quantum.Qir.Tools { public class QirFullStateExecutable : QirExecutable { + public QirFullStateExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) : + base(entryPoint, qirBytecode) + { + } + + protected override void GenerateDriver(Stream driver) + { + throw new NotImplementedException(); + } + + protected override IList GetLinkLibraries() + { + throw new NotImplementedException(); + } } } From 28775ce91719082dabad40ae6b54b57bcb9264b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 16 Apr 2021 13:38:27 -0700 Subject: [PATCH 039/145] Create QirTools static class and make async the methods that make sense. --- src/Qir/Execution/Tools/QirExecutable.cs | 5 +++-- .../Execution/Tools/QirFullStateExecutable.cs | 3 ++- src/Qir/Execution/Tools/QirTools.cs | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 src/Qir/Execution/Tools/QirTools.cs diff --git a/src/Qir/Execution/Tools/QirExecutable.cs b/src/Qir/Execution/Tools/QirExecutable.cs index 1582ee44891..859a9c30fc0 100644 --- a/src/Qir/Execution/Tools/QirExecutable.cs +++ b/src/Qir/Execution/Tools/QirExecutable.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; namespace Microsoft.Quantum.Qir.Tools { @@ -19,12 +20,12 @@ public QirExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) this.QirBytecode = qirBytecode; } - public void Build(FileInfo executable, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) + public Task BuildAsync(DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executable) { throw new NotImplementedException(); } - protected abstract void GenerateDriver(Stream driver); + protected abstract Task GenerateDriverAsync(Stream driver); protected abstract IList GetLinkLibraries(); } diff --git a/src/Qir/Execution/Tools/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/QirFullStateExecutable.cs index 911daa66042..cd0efae81ac 100644 --- a/src/Qir/Execution/Tools/QirFullStateExecutable.cs +++ b/src/Qir/Execution/Tools/QirFullStateExecutable.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; namespace Microsoft.Quantum.Qir.Tools { @@ -15,7 +16,7 @@ public QirFullStateExecutable(EntryPointOperation entryPoint, byte[] qirBytecode { } - protected override void GenerateDriver(Stream driver) + protected override Task GenerateDriverAsync(Stream driver) { throw new NotImplementedException(); } diff --git a/src/Qir/Execution/Tools/QirTools.cs b/src/Qir/Execution/Tools/QirTools.cs new file mode 100644 index 00000000000..0162745868e --- /dev/null +++ b/src/Qir/Execution/Tools/QirTools.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Tools +{ + public static class QirTools + { + public static Task BuildFromQSharpDll(FileInfo qsharpDll) + { + throw new NotImplementedException(); + } + } +} From f2377c86615a9762560b68acde4ec77ffe25b486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 16 Apr 2021 13:57:28 -0700 Subject: [PATCH 040/145] Added method to run executable. --- src/Qir/Execution/Tools/QirExecutable.cs | 14 +++++++++++++- src/Qir/Execution/Tools/QirFullStateExecutable.cs | 6 ++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Qir/Execution/Tools/QirExecutable.cs b/src/Qir/Execution/Tools/QirExecutable.cs index 859a9c30fc0..119749ff0aa 100644 --- a/src/Qir/Execution/Tools/QirExecutable.cs +++ b/src/Qir/Execution/Tools/QirExecutable.cs @@ -20,13 +20,25 @@ public QirExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) this.QirBytecode = qirBytecode; } - public Task BuildAsync(DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executable) + public Task BuildAsync(DirectoryInfo librariesDirectory, DirectoryInfo includeDirectory, FileInfo executable) { throw new NotImplementedException(); } + // TODO: How arguments are passed to this API will change. + public Task RunAsync(FileInfo executable, DirectoryInfo librariesDirectory, IList arguments) + { + throw new NotImplementedException(); + } + + // TODO: To be used by BuildAsync. protected abstract Task GenerateDriverAsync(Stream driver); + // TODO: To be used by RunAsync. + // TODO: How arguments are passed to this API will change. + protected abstract string GetCommandLineArguments(IList arguments); + + // TODO: To be used by BuildAsync. protected abstract IList GetLinkLibraries(); } } diff --git a/src/Qir/Execution/Tools/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/QirFullStateExecutable.cs index cd0efae81ac..ca5178f6b46 100644 --- a/src/Qir/Execution/Tools/QirFullStateExecutable.cs +++ b/src/Qir/Execution/Tools/QirFullStateExecutable.cs @@ -21,6 +21,12 @@ protected override Task GenerateDriverAsync(Stream driver) throw new NotImplementedException(); } + // TODO: How arguments are passed to this API will change. + protected override string GetCommandLineArguments(IList arguments) + { + throw new NotImplementedException(); + } + protected override IList GetLinkLibraries() { throw new NotImplementedException(); From 8dcb5f5dc0d9c5c8e3f3dcd2e552dfa9fb265c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 16 Apr 2021 14:17:33 -0700 Subject: [PATCH 041/145] Changed project to netstandard. --- .../Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index c07b9da92ed..5ad95e9541e 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -1,7 +1,13 @@ - netcoreapp3.1 + netstandard2.1 + x64 + + + + Tools for interacting with QIR. + Quantum QIR From e69141a1a99121fd9f049f4d43e1b12c803d5dc8 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Apr 2021 14:51:50 -0700 Subject: [PATCH 042/145] Use Submitter suffix for new interfaces --- src/Simulation/Core/IAzureMachine.cs | 25 ------------------- src/Simulation/Core/IAzureSubmitter.cs | 24 ++++++++++++++++++ .../Core/{IQirMachine.cs => IQirSubmitter.cs} | 4 +-- src/Simulation/Core/IQuantumMachine.cs | 4 +-- 4 files changed, 28 insertions(+), 29 deletions(-) delete mode 100644 src/Simulation/Core/IAzureMachine.cs create mode 100644 src/Simulation/Core/IAzureSubmitter.cs rename src/Simulation/Core/{IQirMachine.cs => IQirSubmitter.cs} (88%) diff --git a/src/Simulation/Core/IAzureMachine.cs b/src/Simulation/Core/IAzureMachine.cs deleted file mode 100644 index f5444521e7b..00000000000 --- a/src/Simulation/Core/IAzureMachine.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#nullable enable - -namespace Microsoft.Quantum.Runtime -{ - /// - /// A machine that can execute quantum programs on Azure. - /// - public interface IAzureMachine - { - /// - /// Gets the ID of the quantum machine provider. - /// - string ProviderId { get; } - - /// - /// Gets the name of the target quantum machine. - /// A provider may expose multiple targets that can be used to execute programs. - /// Users may select which target they would like to be used for execution. - /// - string Target { get; } - } -} diff --git a/src/Simulation/Core/IAzureSubmitter.cs b/src/Simulation/Core/IAzureSubmitter.cs new file mode 100644 index 00000000000..0fc11515b3f --- /dev/null +++ b/src/Simulation/Core/IAzureSubmitter.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +namespace Microsoft.Quantum.Runtime +{ + /// + /// An interface for submitting quantum programs to Azure. + /// + public interface IAzureSubmitter + { + /// + /// The ID of the quantum machine provider. + /// + string ProviderId { get; } + + /// + /// The name of the target quantum machine. A provider may expose multiple targets that can be used to execute + /// programs. Users may select which target they would like to be used for execution. + /// + string Target { get; } + } +} diff --git a/src/Simulation/Core/IQirMachine.cs b/src/Simulation/Core/IQirSubmitter.cs similarity index 88% rename from src/Simulation/Core/IQirMachine.cs rename to src/Simulation/Core/IQirSubmitter.cs index 1519990852c..f18c171c6f0 100644 --- a/src/Simulation/Core/IQirMachine.cs +++ b/src/Simulation/Core/IQirSubmitter.cs @@ -10,9 +10,9 @@ namespace Microsoft.Quantum.Runtime { /// - /// A machine that can execute QIR programs on Azure. + /// An interface for submitting QIR programs to Azure. /// - public interface IQirMachine : IAzureMachine + public interface IQirSubmitter : IAzureSubmitter { /// /// Submits a job to execute a QIR program without waiting for execution to complete. diff --git a/src/Simulation/Core/IQuantumMachine.cs b/src/Simulation/Core/IQuantumMachine.cs index 2d81d39ec0a..361a6eea37a 100644 --- a/src/Simulation/Core/IQuantumMachine.cs +++ b/src/Simulation/Core/IQuantumMachine.cs @@ -7,9 +7,9 @@ namespace Microsoft.Quantum.Runtime { /// - /// Interface that a quantum machine must implement. + /// An interface for submitting Q# programs to Azure. /// - public interface IQuantumMachine : IAzureMachine + public interface IQuantumMachine : IAzureSubmitter { /// /// Function that configures a job object before submission. From d6b0689c62890a2bcddf0dfed4dbc34d3470585c Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Apr 2021 17:48:02 -0700 Subject: [PATCH 043/145] Move new interfaces to Submitters folder --- src/Simulation/Core/{ => Submitters}/IAzureSubmitter.cs | 0 src/Simulation/Core/{ => Submitters}/IQirSubmitter.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/Simulation/Core/{ => Submitters}/IAzureSubmitter.cs (100%) rename src/Simulation/Core/{ => Submitters}/IQirSubmitter.cs (100%) diff --git a/src/Simulation/Core/IAzureSubmitter.cs b/src/Simulation/Core/Submitters/IAzureSubmitter.cs similarity index 100% rename from src/Simulation/Core/IAzureSubmitter.cs rename to src/Simulation/Core/Submitters/IAzureSubmitter.cs diff --git a/src/Simulation/Core/IQirSubmitter.cs b/src/Simulation/Core/Submitters/IQirSubmitter.cs similarity index 100% rename from src/Simulation/Core/IQirSubmitter.cs rename to src/Simulation/Core/Submitters/IQirSubmitter.cs From c536255371701fd4dd304539b76c508a029d75f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Sun, 18 Apr 2021 12:25:36 -0700 Subject: [PATCH 044/145] Add needed parameters to static API. --- src/Qir/Execution/Tools/QirTools.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Execution/Tools/QirTools.cs b/src/Qir/Execution/Tools/QirTools.cs index 0162745868e..d4bf53d62c4 100644 --- a/src/Qir/Execution/Tools/QirTools.cs +++ b/src/Qir/Execution/Tools/QirTools.cs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Qir.Tools { public static class QirTools { - public static Task BuildFromQSharpDll(FileInfo qsharpDll) + public static Task BuildFromQSharpDll(FileInfo qsharpDll, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executable) { throw new NotImplementedException(); } From b1d638259cc0dd14c3ecdb01f83e3b78f2c0c2d3 Mon Sep 17 00:00:00 2001 From: Zander Chocron Date: Mon, 19 Apr 2021 13:29:17 -0700 Subject: [PATCH 045/145] Implement dependencies and tests (#626) --- .gitignore | 6 +- src/Qir/Controller/Controller.cs | 9 +- ...enerator.cs => IQirSourceFileGenerator.cs} | 4 +- .../Controller/Driver/QirDriverGenerator.cs | 26 ---- .../Driver/QirSourceFileGenerator.cs | 53 ++++++++ src/Qir/Controller/Executable/ClangClient.cs | 2 +- .../Executable/QirExecutableGenerator.cs | 38 +++++- .../Executable/QuantumExecutableRunner.cs | 20 ++- src/Qir/Controller/Program.cs | 2 +- src/Qir/Controller/QirController.csproj | 6 +- .../Tests.QirController/ControllerTests.cs | 19 +-- .../QirDriverGeneratorTests.cs | 63 +++++++++ .../QirExecutableGeneratorTests.cs | 120 ++++++++++++++++++ .../Controller/Tests.QirController/Util.cs | 30 +++++ .../test-cases/standalone-input-test.in | Bin 0 -> 44066 bytes .../test-cases/standalone-input-test.out | 14 ++ src/Qir/Controller/test-qir-controller.ps1 | 44 ++++++- 17 files changed, 398 insertions(+), 58 deletions(-) rename src/Qir/Controller/Driver/{IQirDriverGenerator.cs => IQirSourceFileGenerator.cs} (77%) delete mode 100644 src/Qir/Controller/Driver/QirDriverGenerator.cs create mode 100644 src/Qir/Controller/Driver/QirSourceFileGenerator.cs create mode 100644 src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs create mode 100644 src/Qir/Controller/Tests.QirController/QirExecutableGeneratorTests.cs create mode 100644 src/Qir/Controller/Tests.QirController/Util.cs create mode 100644 src/Qir/Controller/test-cases/standalone-input-test.in create mode 100644 src/Qir/Controller/test-cases/standalone-input-test.out diff --git a/.gitignore b/.gitignore index 7127ca52075..0553c56ac2a 100644 --- a/.gitignore +++ b/.gitignore @@ -341,4 +341,8 @@ ASALocalRun/ dbw_test # Controller test artifacts -/src/Qir/Controller/test-artifacts/ \ No newline at end of file +/src/Qir/Controller/test-artifacts/ +/src/Qir/Controller/src + +# out folders +out/ \ No newline at end of file diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 5f9cc2b65cc..70378632128 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -25,7 +25,7 @@ public static async Task ExecuteAsync( DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo errorFile, - IQirDriverGenerator driverGenerator, + IQirSourceFileGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner executableRunner, ILogger logger) @@ -37,10 +37,10 @@ public static async Task ExecuteAsync( using var inputFileStream = inputFile.OpenRead(); var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); - // Step 32: Create driver. + // Step 2: Create driver. logger.LogInfo("Creating driver file."); var sourceDirectory = new DirectoryInfo(SourceDirectoryPath); - await driverGenerator.GenerateQirDriverCppAsync(sourceDirectory, input.EntryPoint, input.QirBytecode); + await driverGenerator.GenerateQirSourceFilesAsync(sourceDirectory, input.EntryPoint, input.QirBytecode); // Step 3: Create executable. logger.LogInfo("Compiling and linking executable."); @@ -50,12 +50,11 @@ public static async Task ExecuteAsync( // Step 4: Run executable. logger.LogInfo("Running executable."); - using var outputFileStream = outputFile.OpenWrite(); await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); } catch (Exception e) { - logger.LogError("An error has been encountered. Will write an error to the error file and delete any output that has been generated."); + logger.LogError("An error has been encountered. Will write an error to the error file."); logger.LogException(e); await WriteExceptionToFileAsync(e, errorFile); } diff --git a/src/Qir/Controller/Driver/IQirDriverGenerator.cs b/src/Qir/Controller/Driver/IQirSourceFileGenerator.cs similarity index 77% rename from src/Qir/Controller/Driver/IQirDriverGenerator.cs rename to src/Qir/Controller/Driver/IQirSourceFileGenerator.cs index e4dc2a6172c..92e0449c77a 100644 --- a/src/Qir/Controller/Driver/IQirDriverGenerator.cs +++ b/src/Qir/Controller/Driver/IQirSourceFileGenerator.cs @@ -8,7 +8,7 @@ namespace Microsoft.Quantum.Qir.Driver { - public interface IQirDriverGenerator + public interface IQirSourceFileGenerator { /// /// Generates the C++ driver source file and writes the bytecode to a file. @@ -17,6 +17,6 @@ public interface IQirDriverGenerator /// Entry point information. /// The QIR bytecode. /// - Task GenerateQirDriverCppAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode); + Task GenerateQirSourceFilesAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode); } } diff --git a/src/Qir/Controller/Driver/QirDriverGenerator.cs b/src/Qir/Controller/Driver/QirDriverGenerator.cs deleted file mode 100644 index e169ea12be4..00000000000 --- a/src/Qir/Controller/Driver/QirDriverGenerator.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; - -namespace Microsoft.Quantum.Qir.Driver -{ - public class QirDriverGenerator : IQirDriverGenerator - { - private readonly ILogger logger; - - public QirDriverGenerator(ILogger logger) - { - this.logger = logger; - } - - public Task GenerateQirDriverCppAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Qir/Controller/Driver/QirSourceFileGenerator.cs b/src/Qir/Controller/Driver/QirSourceFileGenerator.cs new file mode 100644 index 00000000000..7a7cfe891a2 --- /dev/null +++ b/src/Qir/Controller/Driver/QirSourceFileGenerator.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Utility; +using Microsoft.Quantum.QsCompiler; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Driver +{ + public class QirSourceFileGenerator : IQirSourceFileGenerator + { + private const string BytecodeFileName = "qir.bc"; + private const string DriverFileName = "driver.cpp"; + private readonly ILogger logger; + + public QirSourceFileGenerator(ILogger logger) + { + this.logger = logger; + } + + public async Task GenerateQirSourceFilesAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode) + { + if (sourceDirectory.Exists) + { + sourceDirectory.Delete(true); + } + + sourceDirectory.Create(); + logger.LogInfo($"Created source directory at {sourceDirectory.FullName}."); + + // Create driver. + var driverFile = new FileInfo(Path.Combine(sourceDirectory.FullName, DriverFileName)); + using var driverFileStream = driverFile.OpenWrite(); + GenerateQirDriverCppHelper(entryPointOperation, driverFileStream); + logger.LogInfo($"Created driver file at {driverFile.FullName}."); + + // Create bytecode file. + var bytecodeFile = new FileInfo(Path.Combine(sourceDirectory.FullName, BytecodeFileName)); + using var bytecodeFileStream = bytecodeFile.OpenWrite(); + await bytecodeFileStream.WriteAsync(bytecode.Array, bytecode.Offset, bytecode.Count); + logger.LogInfo($"Created bytecode file at {bytecodeFile.FullName}."); + } + + // Virtual method wrapper is to enable mocking in unit tests. + public virtual void GenerateQirDriverCppHelper(EntryPointOperation entryPointOperation, Stream stream) + { + QirDriverGeneration.GenerateQirDriverCpp(entryPointOperation, stream); + } + } +} diff --git a/src/Qir/Controller/Executable/ClangClient.cs b/src/Qir/Controller/Executable/ClangClient.cs index 72fc903d4e8..81bd435aff4 100644 --- a/src/Qir/Controller/Executable/ClangClient.cs +++ b/src/Qir/Controller/Executable/ClangClient.cs @@ -23,7 +23,7 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, // string.Join does not automatically prepend the delimiter, so it is included again in the string here. var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; - var arguments = $"{inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath}"; + var arguments = $"-v {inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath}"; logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); var result = await Process.ExecuteAsync( "clang", diff --git a/src/Qir/Controller/Executable/QirExecutableGenerator.cs b/src/Qir/Controller/Executable/QirExecutableGenerator.cs index c09a7a0fa67..9445f300115 100644 --- a/src/Qir/Controller/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Controller/Executable/QirExecutableGenerator.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System.IO; +using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; @@ -9,6 +10,11 @@ namespace Microsoft.Quantum.Qir.Executable { public class QirExecutableGenerator : IQirExecutableGenerator { + private static readonly string[] LibrariesToLink = { + "Microsoft.Quantum.Qir.Runtime", + "Microsoft.Quantum.Qir.QSharp.Foundation", + "Microsoft.Quantum.Qir.QSharp.Core" + }; private readonly IClangClient clangClient; private readonly ILogger logger; @@ -18,10 +24,36 @@ public QirExecutableGenerator(IClangClient clangClient, ILogger logger) this.logger = logger; } - public Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) + public async Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) { - // TODO: Compile and link libraries- "Microsoft.Quantum.Qir.Runtime", "Microsoft.Quantum.Qir.QSharp.Foundation", "Microsoft.Quantum.Qir.QSharp.Core" - throw new System.NotImplementedException(); + // Wrap in a Task.Run because FileInfo methods are not asynchronous. + await Task.Run(async () => + { + var binDirectory = executableFile.Directory; + logger.LogInfo($"Creating binary directory at {binDirectory.FullName}."); + executableFile.Directory.Create(); + + // Copy all library contents to bin. + logger.LogInfo("Copying library directory contents into the executable's folder."); + var libraryFiles = libraryDirectory.GetFiles(); + foreach (var file in libraryFiles) + { + CopyFileIfNotExists(file, binDirectory); + } + + var inputFiles = sourceDirectory.GetFiles().Select(fileInfo => fileInfo.FullName).ToArray(); + await clangClient.CreateExecutableAsync(inputFiles, LibrariesToLink, libraryDirectory.FullName, includeDirectory.FullName, executableFile.FullName); + }); + } + + private void CopyFileIfNotExists(FileInfo fileToCopy, DirectoryInfo destinationDirectory) + { + var newPath = Path.Combine(destinationDirectory.FullName, fileToCopy.Name); + if (!File.Exists(newPath)) + { + var newFile = fileToCopy.CopyTo(newPath); + logger.LogInfo($"Copied file {fileToCopy.FullName} to {newFile.FullName}"); + } } } } diff --git a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs index 774aa0cf517..8ce2bcd41d7 100644 --- a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs +++ b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.CommandLine.Invocation; using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; +using Microsoft.Quantum.QsCompiler; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; namespace Microsoft.Quantum.Qir.Executable @@ -17,9 +19,23 @@ public QuantumExecutableRunner(ILogger logger) this.logger = logger; } - public Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile) + public async Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile) { - throw new System.NotImplementedException(); + var arguments = QirDriverGeneration.GenerateCommandLineArguments(entryPointOperation.Arguments); + logger.LogInfo($"Invoking executable {executableFile.FullName} with the following arguments: {arguments}"); + arguments = $"--simulation-output {outputFile.FullName} {arguments}"; + if (outputFile.Exists) + { + outputFile.Delete(); + } + + outputFile.Create().Dispose(); + var result = await Process.ExecuteAsync( + executableFile.FullName, + arguments, + stdOut: s => { logger.LogInfo("executable: " + s); }, + stdErr: s => { logger.LogError("executable: " + s); }); + logger.LogInfo($"Executable has finished running. Result code: {result}"); } } } diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 88677d0d1ce..6def5f9d223 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -16,7 +16,7 @@ static void Main(string[] args) { var logger = new Logger(new Clock()); var execGenerator = new QirExecutableGenerator(new ClangClient(logger), logger); - var driverGenerator = new QirDriverGenerator(logger); + var driverGenerator = new QirSourceFileGenerator(logger); var execRunner = new QuantumExecutableRunner(logger); logger.LogInfo("QIR controller beginning."); diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index 4570cafa210..e9574233c00 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -7,18 +7,22 @@ + + + + - + diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs index 5da9e861d37..6e85b07976b 100644 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ b/src/Qir/Controller/Tests.QirController/ControllerTests.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Reflection; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Quantum.Qir; @@ -22,7 +21,7 @@ namespace Tests.QirController { public class ControllerTests : IDisposable { - private Mock driverGeneratorMock; + private Mock driverGeneratorMock; private Mock executableGeneratorMock; private Mock executableRunnerMock; private Mock loggerMock; @@ -34,7 +33,7 @@ public class ControllerTests : IDisposable public ControllerTests() { - driverGeneratorMock = new Mock(); + driverGeneratorMock = new Mock(); executableGeneratorMock = new Mock(); executableRunnerMock = new Mock(); inputFile = new FileInfo($"{Guid.NewGuid()}-input"); @@ -102,9 +101,9 @@ await Controller.ExecuteAsync( loggerMock.Object); // Verify driver was created. - driverGeneratorMock.Verify(obj => obj.GenerateQirDriverCppAsync( + driverGeneratorMock.Verify(obj => obj.GenerateQirSourceFilesAsync( It.IsAny(), - It.Is(entryPoint => EntryPointsAreEqual(entryPoint, input.EntryPoint)), + It.Is(entryPoint => Util.EntryPointsAreEqual(entryPoint, input.EntryPoint)), It.Is>(bytecode => BytecodesAreEqual(bytecode, input.QirBytecode)))); // Verify executable was generated. @@ -118,7 +117,7 @@ await Controller.ExecuteAsync( // Verify executable was run. executableRunnerMock.Verify(obj => obj.RunExecutableAsync( It.Is(executableFile => actualExecutableFile.FullName == executableFile.FullName), - It.Is(entryPoint => EntryPointsAreEqual(entryPoint, input.EntryPoint)), + It.Is(entryPoint => Util.EntryPointsAreEqual(entryPoint, input.EntryPoint)), It.Is(actualOutputFile => actualOutputFile.FullName == outputFile.FullName))); } @@ -184,14 +183,6 @@ await Controller.ExecuteAsync( Assert.Equal(errorCode, error.Code); } - private bool EntryPointsAreEqual(EntryPointOperation entryPointA, EntryPointOperation entryPointB) - { - var method = typeof(Extensions) - .GetMethod("ValueEquals", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(EntryPointOperation), typeof(EntryPointOperation) }, null); - object[] parameters = { entryPointA, entryPointB }; - return (bool)method.Invoke(null, parameters); - } - private bool BytecodesAreEqual(ArraySegment bytecodeA, ArraySegment bytecodeB) { if (bytecodeA.Count != bytecodeB.Count) diff --git a/src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs b/src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs new file mode 100644 index 00000000000..e93837e62ea --- /dev/null +++ b/src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Driver; +using Microsoft.Quantum.Qir.Utility; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Moq; +using Xunit; + +namespace Tests.QirController +{ + public class QirDriverGeneratorTests : IDisposable + { + private readonly Mock driverGeneratorMock; + private readonly DirectoryInfo sourceDirectory; + + public QirDriverGeneratorTests() + { + driverGeneratorMock = new Mock(Mock.Of()) { CallBase = true }; + driverGeneratorMock.Setup(obj => obj.GenerateQirDriverCppHelper(It.IsAny(), It.IsAny())); + sourceDirectory = new DirectoryInfo($"{Guid.NewGuid()}-source"); + } + + public void Dispose() + { + Util.DeleteDirectory(sourceDirectory); + } + + [Fact] + public async Task TestGenerateDriver() + { + var entryPoint = new EntryPointOperation() + { + Arguments = new List + { + new Argument() + { + Position = 0, + Name = "argname", + Values = new List { new ArgumentValue { String = "argvalue" } }, + } + } + }; + byte[] bytes = { 1, 2, 3, 4, 5 }; + var bytecode = new ArraySegment(bytes, 1, 3); + await driverGeneratorMock.Object.GenerateQirSourceFilesAsync(sourceDirectory, entryPoint, bytecode); + driverGeneratorMock.Verify(obj => obj.GenerateQirDriverCppHelper(It.Is(actualEntryPoint => Util.EntryPointsAreEqual(entryPoint, actualEntryPoint)), It.IsAny())); + + // Verify that the "bytecode" file was created correctly. + var bytecodeFilePath = new FileInfo(Path.Combine(sourceDirectory.FullName, "qir.bc")); + using var bytecodeFileStream = bytecodeFilePath.OpenRead(); + Assert.Equal(bytecodeFileStream.Length, bytecode.Count); + for (var i = 0; i < bytecodeFileStream.Length; ++i) + { + Assert.Equal(bytecode[i], bytecodeFileStream.ReadByte()); + } + } + } +} diff --git a/src/Qir/Controller/Tests.QirController/QirExecutableGeneratorTests.cs b/src/Qir/Controller/Tests.QirController/QirExecutableGeneratorTests.cs new file mode 100644 index 00000000000..3d9da400687 --- /dev/null +++ b/src/Qir/Controller/Tests.QirController/QirExecutableGeneratorTests.cs @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Executable; +using Microsoft.Quantum.Qir.Utility; +using Moq; +using Xunit; + +namespace Tests.QirController +{ + public class QirExecutableGeneratorTests : IDisposable + { + private readonly Mock clangClientMock; + private readonly QirExecutableGenerator executableGenerator; + private readonly DirectoryInfo sourceDirectory; + private readonly DirectoryInfo includeDirectory; + private readonly DirectoryInfo libraryDirectory; + private readonly DirectoryInfo binDirectory; + private readonly IList libraryFiles; + private readonly IList sourceFiles; + + public QirExecutableGeneratorTests() + { + clangClientMock = new Mock(); + executableGenerator = new QirExecutableGenerator(clangClientMock.Object, Mock.Of()); + + // Set up files. + var prefix = Guid.NewGuid().ToString(); + binDirectory = new DirectoryInfo($"{prefix}-bin"); + binDirectory.Create(); + libraryDirectory = new DirectoryInfo($"{prefix}-library"); + libraryDirectory.Create(); + libraryFiles = new List() + { + CreateFile("lib1", libraryDirectory, "lib1 contents"), + CreateFile("lib2", libraryDirectory, "lib2 contents"), + }; + includeDirectory = new DirectoryInfo($"{prefix}-include"); + includeDirectory.Create(); + sourceDirectory = new DirectoryInfo($"{prefix}-source"); + sourceDirectory.Create(); + sourceFiles = new List() + { + CreateFile("src1.cpp", sourceDirectory, "src1 contents"), + CreateFile("src2.bc", sourceDirectory, "src2 contents"), + }; + } + + public void Dispose() + { + Util.DeleteDirectory(sourceDirectory); + Util.DeleteDirectory(includeDirectory); + Util.DeleteDirectory(libraryDirectory); + Util.DeleteDirectory(binDirectory); + } + + [Fact] + public async Task TestGenerateExecutable() + { + string[] expectedLibraries = { + "Microsoft.Quantum.Qir.Runtime", + "Microsoft.Quantum.Qir.QSharp.Foundation", + "Microsoft.Quantum.Qir.QSharp.Core" + }; + + var executableFile = new FileInfo(Path.Combine(binDirectory.FullName, "executableFile")); + await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, libraryDirectory, includeDirectory); + + // Verify invocation of clang. + clangClientMock.Verify(obj => obj.CreateExecutableAsync( + It.Is(s => s.SequenceEqual(sourceFiles.Select(fileInfo => fileInfo.FullName))), + It.Is(s => s.SequenceEqual(expectedLibraries)), + libraryDirectory.FullName, + includeDirectory.FullName, + executableFile.FullName)); + + // Verify files were copied. + Assert.True(FilesWereCopied(libraryFiles.ToArray(), binDirectory)); + } + + private static FileInfo CreateFile(string fileName, DirectoryInfo directory, string contents) + { + var filePath = Path.Combine(directory.FullName, fileName); + var fileInfo = new FileInfo(filePath); + using var fileStream = fileInfo.OpenWrite(); + using var streamWriter = new StreamWriter(fileStream); + streamWriter.Write(contents); + return fileInfo; + } + + private static bool FilesWereCopied(FileInfo[] files, DirectoryInfo destinationDirectory) + { + var destinationDirectoryFiles = destinationDirectory.GetFiles(); + foreach (var file in files) + { + var copiedFile = destinationDirectoryFiles.FirstOrDefault(fileInfo => fileInfo.Name == file.Name); + if (copiedFile == null) + { + return false; + } + + using var originalFileReader = file.OpenText(); + var originalFileContents = originalFileReader.ReadToEnd(); + using var copiedFileReader = copiedFile.OpenText(); + var copiedFileContents = copiedFileReader.ReadToEnd(); + if (originalFileContents != copiedFileContents) + { + return false; + } + } + + return true; + } + } +} diff --git a/src/Qir/Controller/Tests.QirController/Util.cs b/src/Qir/Controller/Tests.QirController/Util.cs new file mode 100644 index 00000000000..476848705ea --- /dev/null +++ b/src/Qir/Controller/Tests.QirController/Util.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Reflection; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Tests.QirController +{ + public static class Util + { + public static void DeleteDirectory(DirectoryInfo directory) + { + foreach (var file in directory.GetFiles()) + { + file.Delete(); + } + directory.Delete(); + } + + + public static bool EntryPointsAreEqual(EntryPointOperation entryPointA, EntryPointOperation entryPointB) + { + var method = typeof(Extensions) + .GetMethod("ValueEquals", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(EntryPointOperation), typeof(EntryPointOperation) }, null); + object[] parameters = { entryPointA, entryPointB }; + return (bool)method.Invoke(null, parameters); + } + } +} diff --git a/src/Qir/Controller/test-cases/standalone-input-test.in b/src/Qir/Controller/test-cases/standalone-input-test.in new file mode 100644 index 0000000000000000000000000000000000000000..2251eb15f36354835911c0b1eb4f81ff2a71e3a6 GIT binary patch literal 44066 zcmeHw3tZFX`uO*|jctxGHbCV%Ho!zg-NsNtFUJp=;D^X^YIJ4QHKn<^cU0@j^tzJrGQ%A;Mq_zpwL!nI%ve)h zm7AMcYpBdGsxshz`*RQum+yz52!c%DAnc;D>brC$H3t7MgoFAAA_6o4iB`!ll~zHAB80F$7bNq`lABB%lP#WgP=j)X~f@j;tpM^PEm$z*5EfjiD_cn^7HSU{ zPY7yEfU^hE5CI3_!aKMGfk*@n!CycLatrII(oj`Xf*T8{BQ{9INyQST;H@kInG|9I zM213mB*%n^g+ef(5Tqc)9TW=%hs9P^R~D76Bvr?uij7Ampj&OJkO?M;x0G)X>CNZ=&gY+1o=z>GK;! zZ=*7cEi@rM!7hEkx#Ce#Z!e(xun0k_z+D!@=7{v`7{PIEHt=)Y)@lz4%CZ9yW4!yp2Yu)05-O^m!*# zXl9!VUEG$A-WivU-lI=P4SfQWIxHkKr7_lTcJFb{jP*!K6C$#UO{tcFrpN5mxZ@)d^aLBPZTN&?|$$(nc0SfUia%r>09e1#!8UvYUrgc5c{xRg3-ey^Eq^Z&~ zm0^x&V>UPU=Y)k+r^Ihz$I?2M+602)gsxupyoox7>Dl#?C24nL^4YChWlkHr|ITS4 zX=&Bf@qgjYo*mn9C&Mr5j4UIo@sGR*A5)7NO$3RflKxLr z$j1J+Ly!qAD$}KGNt!7xk0uD0qsYW16TW=XVGEjOt8Q`xr)|7R>sXK{Nn_I&hKu!^ z;)^yd167ISgd#{FxJSG&0KHvkOZ<2(10yA*rH7nf%~n2Y{90q`le- zYLWUkkY))&ztE#~k$n$jPr;>1OLmbnUd~pv>3}NIUkbEQaLm%=7 zH9q7;5o^83wMJYrV;@=fOGYqL=EF?3)z=ORTShRm(}$TC+&;{xnzdN-E%PvvJ+-~IyBPUCcUVE13`m4=8w zRTeK^xAe#eEuBx;obH{7VXj`6lI17zA^^1%pV+BRpkf)23G3+PeD~zL2oH+k!`hs< z*#GbSFqok(Xdx&5FtqM}s1yJI_m$=Mm1R~B>?+6$GtQlpAJD{nM~J`bW~bV>PH#QhkX%U70{~R%j!XR&-f2+wLu)T8z0+XP zTW%RiaO+Q_5HyRoGmCwhES@;wZ;>W1ny~2SW4ALSeN>e2RNQ+ex|fQf+IKvWF^bxS zQ(Pm}{_S*>cg(9COquIfPe>Udc&lVP)7wvC6_k3@`wnkYhNYi;*A^l7CJ9xv?5Wcu zR8+M1fk-br%#07+bYuj<%+GqlM-W`Qd6|{y=r9`4G9TL-T-NVJ5wqd0)p?O!-aKM9 zd^Wgb1m%}jkU_Rp&j0tIdikO{bI_Dm}xxbtzpc7U#oi5{|j%TBH-xGboj4WHlq35 za_>kRE(MUYaMAGGfQ@jG>=CD?j5Pj)Y6U-nD2CqBF@`8 zM^R?9;?oiB;_#XIBgHxYiFTwoA4ZH6XVZhnM~Wk^9aPT+-3+C7*b98#-TgF6L?s~z z^lz`%)?V=STAb)d{wg$iAwsWp_=KDJFJH_Ad0=WIur~&UEJfl{*ddc9qDU_dw$?kr zf0?jF6ea+J;t4k`*uzMtg`)B1@OD}dc6XqW#;TgPReK$cv)fEiH7fH^HZCUetJ;WTW`IUCI9iK zpJD_Te)wTS#^GHh1#}=8i|7_@X9-;4tOfxn1wQz&d%(crWWf z!EH~x_{qxqTJD+km8!aR!^Iy9{?I+RW;yFX=B2f-SS#z4f1~Hr%Z7~4JVTJ>&Rwzc zMLc6#Y~UOJFyPOgFk6mBa?BQ}?Cl`*{}Z?;u}zUZ$07?t(0PsNN?UhRnu%3c%c^Rr z;GRMPzvlDKn|MjwG+~!J>b=&;0*N1nW{v2h&+AQ}*F>M!SKCx=WZlnZ)nzppjjT0B z`l{Lnqo^UQPrw_r^NvXZ%Oruvhj>F8UJ}12>QgZo0!MY}gawj^=j^i1=}%AXpwHc9 zool1d=^F}JrDfe;$WjzGRDxeqgVEk#)UsB^vsPX717ug5K=0mA5!z7M(ool8PCPrr zJ3GL;;NlHR=y|=ZktbRs`>@}my2y9Lkv-<9cXZ76?dhq#>8UN)Z)dl%IbGREpVQnu z3lw_EGUpI|j$@*Vej1$coqpfr{SHj^NyuGIuLo{SkxI*SP+_{bf(YVY@O4mi6aEjHmt5?)wbkhpSK4> z4G4>c@8}{=i=#euN3BJLkYRDukdC=@omJV_J;#|o4=ChP*W457a~i>)-A%hWK+=ZQ zfFCw%O+2fz#k}G;pEu~@oz(EYlf=3YsD&qvO+Iog3QRH-WQEOfTIY3GBW&Huru5Xl z?zx@r)ZT6&_F$VS?4vw4sJj2O|ai*_04Uw&e;qqls?a4 zoeL`0-VObRPJ|$}ARY>4s1u+IrLa$ii#VHoR`v6iRn>$a!Q7_yZ35Xn?fTV zC>fF-GRO5Yqaz;R)?_Ss*}az;ogNkZJdU!!Fat-)S-y`z+4Ks5asfx#yH1UxROk*6 zCQCu7W6TWvh=QJ0y&Q4NXpsf*j)INd|)Vm1Nxp!adL61<2CS2!)S ziJ;IyQdn&dzfY29gv1^+hEF?ChZpQ*Z54F5anc>?5+k0g|kr{@UqK@dBufWT$K_b#f1W80UK!B2}Bm3%&Ok6w(>*X9GHLACsPa+)JV+ROO zb9~kgaU02zyVOLoftFIjx=Xo07EGTN#)z(PQrH1f*iw6hj?mmg{D@TqZjI5yoFl>- zL6&{Get=+Zi1~(qAQsiTC#oql5^^7XsJ>|%N}#)iee>-svZ~(FQC$CB?V?yMr!?j+ zXIGJ|4n^#aBsFH+OX?=-qDKoh&;m#;91|ZRw9tpvhTy3h)_|BnA{>_Ayc!*$b zmwFB02pX=DwM)v0WwM|RvyN|%t#c6QPS%@(<}T94?kCmMgWk_yOS0+^qEezp`-N#_ z@sS-11b`&oEWQyC^fatNj~2d>Hgyr!>As)+9HE7(0pV__+_n_j$51_|a+8 z$jazrfvUy~HOl3Yw{Nczl#QF@cjC>20K3o!33>aO7jghckU0tG^D&<|;bW4-JwgXD{}Bv>9|#s?9^qIwt1BAa$& z@6!Wm1UhKi3x+5O6Z0sQPER{evAUjW+UN%M0LiK=#!pFFQ)e$QEZmy5HBzmovsc6; zt!ZXVV>ju|H&9J`Mhw-oB{F+AVbo|7`vfVvC>EFyR&g~$9(hHv)>Km7-bO7b1)Ag# zGl`H_9ns&LKqB<9XEzh152>3Nr%3@+v9#GFPJh;H2f^Pi^+tjz2U8&nB+-kFvEP~q zaX`j7o>#`#UK!6)85OG7ZDae4uJZuYY2Q?j-u|fX1B$A1x3%xx9&qwn>>t!5Q=&y2c+q9d^GfND#Cm z8$P##l_(JBybH;rfD=54;j=PJf+m!NErB8|*pAXDr+(&^l56Hal zafj%Xjr0PiGv#>bR%M#Jm*|SndnrHXzL!fxhdu6l*#vkc-O_JF%n7HRr|LceIC^#w8Fp0Nw8G$2ADz27;X%S9M&2k-kdHV%q-s@S3W zfW`!o371Y|-H%wy326}dHVKfwo9_EKX7pSGuZqYZdZ2BwC#~37*B!@W?3t+wyssURjrl~)~4~F zv3-S+C0)elE@huXs&^aHMQ!dxtCnzvMt{k-?6C7Q{Al^O?d(CPJj?y*)gJ=f-vO&d zr34)bZ@P3N9z>=#^<*-_7-g(T+QMhGaeXpwhUyVlrz1pr#MEd(Tc(KcIx@|9_(Zr= zg76vivvEzprj&a_w2zBK3$=vBCk)x1zy}cOgh3KChuh{qQOf6m=^LoFQ$k1fdyK?C zrzcxCvf^&f;5H)JJ!nWqQsxmsqUB(AR=VJFZmv0PMXyc1=kf=W?U4)#fB)qVR^k;@ zdI4o^=X3XG`&P`OUKIoD1kEZn10zBzN& z&eJu@H;AQIod`jG$)~e}5{>(rYwu^K9r-yw zV;_KiCbW@pf5{in_DSb*?fndUre6%vM`3=3y)%%9`x*7`+0XFHq9dW7A-mk^&KvG$ zYA8QbNcx$_Zmgei>*~!!K4x#4oLJ zo4K@|be{Skj9gT0 zGC+dn@QdqKdE%E>e`EY|?zhA*Sd6B2Xyb_ZW%{-o?pL0t{K|c#U)g&Cb26 zgp`lD_OS~i(GMYg3>+hIcTOf^7mttm9gdMg%VxpY1rZU`1&Qr9+{YZId`ubXV=mlS zA7ktcY5tip(rx1F;$vRajQg11>SIRE#XS78V|`4T!3VWXp9DhkX`Yef6f7qc|{eIYvVH@tKr zurC4J|C^qf<0TIbz#TcXWN;(;RR^<3$0nz@i*g9i&WTe~V5|p>lX_Ai$Oel!cK;Y% zNDna+Tx_2N*154|AOL0(;1*R-1_??$peiWclbR0K4d8n*c!kUt_Gj2KX8Z{*AY|Po zv@18Va$J_1Q-mTZLzE+M^Y?WGf!Y2|PqHMpRn5jTp;UMst^jwk4zIP$_zsHy6s>ub z{hy%shrIMo2QXY?QN_jr$YXEC6@(2rn8l>&fnlSU>3P5@UZzKa;IUCCIQ>OA#00pV zBN1?kl^K5#vBIKGXvvU}v((Kb=$>iI5R<7r87d;;nPsEQ)fhys{cq7i&;&QByrv17 zKrV>FMImDF3qW%4Yv)WAQ$ymLJm6G;C)EQ=JqQvHDD@ynNbqM%tMJhEfKzpzR9#3o zj{*1mU$K3?AaoHe?Q-tNwWc1vDI=4SEl*^_*;-*^TD^659h@96Zm#cl0ZeyJTA0ajYMC<-QoEc1Z~_{N^<{o&hkNbD0CT52i> zg4lYG(v|VJ`S?Hgh@IO$RkHtwSgCx&6uc;z5W+MGtY2dL+TK(JyPc?%!2m_EwJNHV zHG&9gn^?l73>R6-MF@)ErmUIgdqSd!#nN{3A{$EVKr0>y(h=z9aQmJP{7C@LCqQ+= zrJn5+Jr8&(!%3xjz_#5KuEPViWm32f5`;yBmXJDcla^ATfB@~BTfQX_?3|lD;4S+- zsryTS3qjz^IJgfSe0mK)L0(gql}FN^bBJtu z`fEQ{us7LgOc`FA$F)J(%s+iRrNL43`U#P8pA!{}V9hf8(DQrLbwW;cFTUBSxjTz7 zpRk6_S)q^A)6w6w9=Hhb<=ZYdv(|uic^0-yOb+ix`StcK*xK-G*=0{eT8^LIWHm*` z+4w=BS@Zw+aYTb@Io2HUCNoW7ki2$JC1^5>cxjA)2!5Ix>1Jk__%3`4PgDA$rD03U zUW}xzKhtd0OnynQEy{e}!Nv*-}>uv}E_01iDXbpJD2@3}ZEp z;M&qtiCZK3V$fc)-54jiNl-h<{roW%ToV1YYp5bGoni5tl%|3Ag|L1tI)|!(Y~{N$ zsI}+L4DI3_U-Ie)h_V8gJ!3X*WijVJp6(8em;rH7X#^b5~Kk?M~ zScV!r{BFlG<1sa>x;1>u4T!0ah5wBzWjv-P=e@>b>e2Vu-QpFO;cJNxpY|Oaj22VB zjm3}MV0_SqjSoWBdBz9EpvBnuz*Pap2Xo&WK0Yvu;P?RB6Fr!g&G-inwxum&9Ka*( z^B@%;hH7|I1d$)$2*$XI3^JI2i0*xPa^ok8yX)L86Ya@2Y&X@6~9%Nc|zwpo@lp7^a}S&^6it~?$ZAD8`K znxh!^rwB6cPsjb~jrONIz5MBa{hWO-=(X^P^?@MI#CkY*TMB=Zxqo+2+kE0R&n@;~ zGdZ1Tf*|(baU^&-6HbDL{CIT|rZ6F}SUeEHE3&1)- zx(ZB<+7Kp#eAC=9dE2+)#GANnUAHri5;QCjL}}o?*Ar>CXYU8SE__AH9Nw7`O1y&Z zV9pdU3G{ZfDEnjlNdRULAfOjXf))=5O7WypVA|ajF3kg`K~b=Xvkj9913?is^8Kn} zRro>j&3#q)egfPw6#Neo9Pofc!TUU^`(6NR?c?+KV|%Y>ypJ63BY(~NVB=$s-?o1C z-?H{G?mx!;$GHDsGjDW^4Zl-LuD@e*7Q^;G+Bsg^8)L{lW*}8c?R1QRAlzVLy z(=5;a!OP@FQWB_5gX#pkXaAtdvwzU#**|Ea_77s42Jr<<4ctG7P1}9p@TWe$lF(w) zkeeBrJzz_QC)ESGJP5lypv!}>%LBIbPzx%}9kNg{7kG6=dEe?8l9{HNbo`AcT6ZgRqn)WIxwN6srE|#emx{uokVPP z8wvs-KCm_hX|RE{qX-PFmHqg*bFgbsxsT62gP9dau zKrod~;-*nxySlKJOr_mEmjt_Rqd?m2a!;zf1#}Lc{kY8N;eA7j5N@J-a;@rwd^-4) zjXd~K>&=&QpMJn}-19dx9>LouY;u=#BOX-YnYI+h_rOrVr4x(nbQt}CJ@>rw>NEMGDN@fR3p z=oj*XB$U`OfblYX1=5>&4tCYX8vD-GxqS|Bx$KP40Jb zLJ*&KM*=9LfM(V4qD-81#TGyD8je57+`Z#&I#`@y$cF z`UWy}sK-izgC1}w!;_j}EmHEw=LWC-o4ezE*LdGG-gn*jzH2=8h3}(}zfbgg{Z7I7 z-oD?qw=W8XvF~#1>;yj$2ghmnOC>boV>Ny`@D(}arBeGPZDDEmc@}d5&B~ZWe0b(N zC#T+SQ3<6S{3L_~G^3k12|>k}s;bOH!p={FXCPoFW0awZL9y1qN2Q1?I;3Diefl!A zV1niS6q9*+_DiK~>;E{j_@Qx5JAU*;OT#@*TL|M^k%1$DJO$?Bk(9~McjO*We)h52p#PUifkAH$6bW{n;F~xQN7}#pRBNy9%c>wdfIN zL(7yxW&-1)_Jx(5V*UZ`<8HGh_?-H$Y!Q9Z^A3@o+*V-p?`Vw-V+?{%gm6*GqM;SE zAjzWsj-AIQW_%tJ&ky~&w9#+VGCvMu{{0aJ?zkmpnpypTOi~a*qqmf@*K1!Di)_c3 zD;$23P^k!<6JcG`{;&X?I1J7$X?UuojBjb(5%2~Qyrcgk=Dm#*R*2MEyDJSpTtX{c zLz|3g{VAaJLPwf0IR0ru>v0K6bSl)kHiyIMGNx;I;6OPQ{1n#(?W9;H18i>61Qtj? z5iyAESw}4o%5P;hkX4esx6!XJD1&$(fH~)LaCi+LJY-_t{A}QHQ{XE`&a)bp(Xl*- z{GOUoc-%>xaN}TpA@%>tlku!q2Fm)%7`z-*VKS&f&W;sC6;7Ijud%pioM%nZ!*7Wa zmetwN$^KmT_`vIFGqjI8h;LCR8w0b2WoOY1 z^31G!cmmJrR-(}F{o+_CH{<-}9iF3lDkk73s9Xjg2*b|oDFj^a5jx@L{0;)9Dg?v{ zD{BLA;Fh(1IPlhk6A55#D8|-To->3zCkNFF?TkOZ0*T_g>h8ji1L}eDdX58n#wAeF z{|SzKi8Lo^FPHzh3;R<69SXQ~A_ST0<$JL2oD;qW`ydbSJv}mT6wq4d?!A+ufe&i= z$pxCRA7{7^a&a1<4^k68C~=q%%JB6;VjmxLH|~RM?&-^3D&^Cc4fjE;dplukVBd}V zAnh<8Bp%^|(tLc-dFX>Cuz(L@Dv^ey!qW6eo39W08uvjNgb(T*=7UV5`Jm9@K4=r> zgVZSSK?vuZ9rz&jI$s}jjPOC7gb(`nFduY&G#|8MxDN`#eGocne%eIL2iez=KB(|m z+*0U+9`yA=^()#vKFCS>AlB1_58A~K?gZZXUc0XkdLRb#LF}h-A7mQlgT&rGNbB)I zM#=}R^!7nrK0c_)+Xu}(NBN*zUJg8NALfIwOUpF6B0esXl;HzXj zevIvwA0`wo{l>Il1HUmO(7fmoLGRK8^WqJ`7n^6BHE)H4PQ2TE$6FJ#?kqLm`TFF> zbq|`CpABu#e8zmwxvNB2zc43)fXX+n=D9tqWaX!#@h z{)~&Ek~0=N`rXXBt!}yD= zPow{m_lEKBwLXLXka9Y#e~tCe=vf6j+_}Npif%}a5AT24`W*UGYF4;&oAr70={ber zj(4puqJwiA!}~w7Zb84F*BdiOSIuQ%6gb zN=8i`RZOYuYK%Lx)=-&WRAnHIJ+E9}mz!HbHj7H2L|tX2t}eI6s0VhPt1BteRpsWF z*Fg0SL#wK;EGk=>n_p>wc*FBb4OLa3QhZX0CkV=wh5|#Sp)B7pD)k~zUUhjc@yKxM zWXa`au<4auZS#}or$}W5jpOTcX$de}}%N2&yTs0JYY55(vV7X8= zi;MCr%d5%@fbf)dF*N8W@(Pr?6j?#OPGQKG>*a>LB+vk5@?^c#kf#J~FgG1n8ze+M zeT^Lt-~y|`)s;G<(NO85@qArLi7u}MsCcwm(wEo3JW9=1#iKqsHBTx@NluX@E96NM zy-p|9eEKk}Nep)u2lnvlf4a zo4v9Y^UBLh#;7Hk-XK-v$s|fyN}gN-{G|^5PX#{I01Qy49J7{m5~ntnwecx5$J!Z5_6 zCZ7gdX{f3x@$!6E)g<#}GDTjhG$jR?gj@&osF0+97MX0&DU}98O8%I&Sdg5Otjkjx zQVM{llt~nMiae<x|Vkl?Jkxx^iDadBM?po~zRF zuZRh839gFzuXb5iMg3Pd^{b-(t6RubQU48=Q!z5AS!t-wttwh$$d&4S8Xg|>zxb!jWpAWu#O?q_9iXy-Rhzm;U^1XQgv6VLu*G)th1%ft-iP%sN%Y@mwuha2lVr+OMJwyt}*^xxHnvSU=h`o=Uz>?eXtmpA}y3R+tV708Qz-3IHncN+yvs29p4| znA5llg9fPH*7FM-090?nBP|>l`8&S1T)y>P`51*F7lf zO1vkJK_vj!oAX~Fd$lS7RDG)dN`zC!z%RhPT7CiQ)$)s@dK10|Rk*Mqvjk2o4GS*3 z+@B{JDJn1k%xfQp_;7ITJl{ydKzG+(W!ElZ@L?Da6|Q8HiZR$Ez`a^SQ;vZw!1X43 z9n^c>4C31LfxZ<7SO!YDQq84~LB#;qyV3swS?}8TWz?%BER~FbVTe2y!dJ^OqziDp zNnam(!wb2R_M{*z9yW*jOUT|#{}S$1>jN<1qmL_+9!n4|1;|&;Gr+xSo^f1n(pNL3 z;JX3>IxItFxzVem@+^W7)8->)3y5htI9;#?JnZwVS1wpz96fXN!NS=2mr7?!X2Siv H*!BMaEy0!n literal 0 HcmV?d00001 diff --git a/src/Qir/Controller/test-cases/standalone-input-test.out b/src/Qir/Controller/test-cases/standalone-input-test.out new file mode 100644 index 00000000000..73833a0e784 --- /dev/null +++ b/src/Qir/Controller/test-cases/standalone-input-test.out @@ -0,0 +1,14 @@ +Exercise Supported Inputs Reference +intValue: 42 +intArray: [9223372036854775807, 4, 4, 2, 3] (5) +doubleValue: 3.14000000000000012 +doubleArray: [0.59999999999999998, 0.40000000000000002, 43.20000000000000284] (3) +boolValue: true +boolArray: [true, false, true, true, false] (5) +pauliValue: PauliZ +pauliArray: [PauliX, PauliI, PauliY, PauliY, PauliZ] (5) +rangeValue: 3..12..27 +resultValue: One +resultArray: [One, One, Zero, One] (4) +stringValue: string value +() diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index ad70d23d1b7..c8dc17ea1aa 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -5,14 +5,54 @@ $all_ok = $True Write-Host "##[info]Test QIR Controller" +$buildConfiguration = $Env:BUILD_CONFIGURATION $controllerProject = (Join-Path $PSScriptRoot QirController.csproj) $testCasesFolder = (Join-Path $PSScriptRoot "test-cases") $testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") +$includeDirectory = (Join-Path $testArtifactsFolder "include") +$headerPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Common\externals\CLI11"), (Join-Path $PSScriptRoot "..\..\Qir\Runtime\public")) +$libraryPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Runtime\build\$buildConfiguration\bin"), (Join-Path $PSScriptRoot "..\..\Simulation\Simulators\bin\$buildConfiguration\netstandard2.1")) +$includeDirectory = (Join-Path $testArtifactsFolder "include") +$libraryDirectory = (Join-Path $testArtifactsFolder "library") + +if (($IsWindows) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Win")))) +{ + Write-Host "On Windows build using Clang" + $env:CC = "clang.exe" + $env:CXX = "clang++.exe" + $env:RC = "clang++.exe" + + if (!(Get-Command clang -ErrorAction SilentlyContinue) -and (choco find --idonly -l llvm) -contains "llvm") { + # LLVM was installed by Chocolatey, so add the install location to the path. + $env:PATH += ";$($env:SystemDrive)\Program Files\LLVM\bin" + Write-Host "Adding clang to path. Path: $env:PATH" + } +} if (!(Test-Path $testArtifactsFolder -PathType Container)) { New-Item -ItemType Directory -Force -Path $testArtifactsFolder } -Get-ChildItem -Path $testArtifactsFolder | Remove-Item -Force +Get-ChildItem -Path $testArtifactsFolder | Remove-Item -Force -Recurse + +# Copy includes to the include folder +New-Item -ItemType "directory" -Path $includeDirectory -Force +foreach ( $path in $headerPaths ) +{ + Get-ChildItem $path -File | + Foreach-Object { + Copy-Item $_ -Destination (Join-Path $includeDirectory $_.Name) + } +} + +# Copy libraries to the library folder +New-Item -ItemType "directory" -Path $libraryDirectory -Force +foreach ( $path in $libraryPaths ) +{ + Get-ChildItem $path -File | + Foreach-Object { + Copy-Item $_ -Destination (Join-Path $libraryDirectory $_.Name) + } +} # Go through each input file in the test cases folder. Get-ChildItem $testCasesFolder -Filter *.in | @@ -20,7 +60,7 @@ Foreach-Object { # Get the paths to the output and error files to pass to the QIR controller. $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) - dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile --includeDirectory "placeholder for now" --libraryDirectory "placeholder for now" + dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile --includeDirectory $includeDirectory --libraryDirectory $libraryDirectory # Compare the expected content of the output and error files vs the actual content. $expectedOutputFile = (Join-Path $testCasesFolder ($_.BaseName + ".out")) From b6393254e41d4299e15486638c28f86a9d9ddff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Mon, 19 Apr 2021 14:24:12 -0700 Subject: [PATCH 046/145] Added documentation comments. --- src/Qir/Execution/Tools/QirExecutable.cs | 16 +++++++++++++++- .../Execution/Tools/QirFullStateExecutable.cs | 4 ++++ src/Qir/Execution/Tools/QirTools.cs | 12 +++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Qir/Execution/Tools/QirExecutable.cs b/src/Qir/Execution/Tools/QirExecutable.cs index 119749ff0aa..de641f4b174 100644 --- a/src/Qir/Execution/Tools/QirExecutable.cs +++ b/src/Qir/Execution/Tools/QirExecutable.cs @@ -9,18 +9,32 @@ namespace Microsoft.Quantum.Qir.Tools { + /// + /// Base for creating and running QIR-based executables. + /// public abstract class QirExecutable { private readonly EntryPointOperation EntryPointOperation; private readonly byte[] QirBytecode; + /// + /// Constructor for the QirExecutable class. + /// + /// Object that provides data to specify which entry-point to use for building and running a QIR-based executable. + /// QIR bytecode used to build the executable. public QirExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) { this.EntryPointOperation = entryPoint; this.QirBytecode = qirBytecode; } - public Task BuildAsync(DirectoryInfo librariesDirectory, DirectoryInfo includeDirectory, FileInfo executable) + /// + /// Creates a QIR-based executable. + /// + /// Directory where the libraries to link to are located. + /// Directory where the headers needed for compilation are located. + /// File to write the executable to. + public Task BuildAsync(DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executable) { throw new NotImplementedException(); } diff --git a/src/Qir/Execution/Tools/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/QirFullStateExecutable.cs index ca5178f6b46..882572810bc 100644 --- a/src/Qir/Execution/Tools/QirFullStateExecutable.cs +++ b/src/Qir/Execution/Tools/QirFullStateExecutable.cs @@ -9,8 +9,12 @@ namespace Microsoft.Quantum.Qir.Tools { + /// + /// Class to create and run QIR-based executables that use the full-state simulator. + /// public class QirFullStateExecutable : QirExecutable { + /// public QirFullStateExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) : base(entryPoint, qirBytecode) { diff --git a/src/Qir/Execution/Tools/QirTools.cs b/src/Qir/Execution/Tools/QirTools.cs index d4bf53d62c4..08531a54057 100644 --- a/src/Qir/Execution/Tools/QirTools.cs +++ b/src/Qir/Execution/Tools/QirTools.cs @@ -7,9 +7,19 @@ namespace Microsoft.Quantum.Qir.Tools { + /// + /// Provides high-level utility methods to work with QIR. + /// public static class QirTools { - public static Task BuildFromQSharpDll(FileInfo qsharpDll, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executable) + + /// + /// Creates a QIR-based executable from a .NET DLL generated by the Q# compiler. + /// + /// .NET DLL generated by the Q# compiler. + /// Directory where the libraries to link to are located. + /// Directory where the headers needed for compilation are located. + public static Task BuildFromQSharpDll(FileInfo qsharpDll, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) { throw new NotImplementedException(); } From 0eff3412b450a8a4f37d307fb0646a8ef2888056 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 21 Apr 2021 13:48:49 -0700 Subject: [PATCH 047/145] Update SDK version --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index f9fa3ed4ed8..758d19df817 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Quantum.Sdk": "0.15.210324735-alpha" + "Microsoft.Quantum.Sdk": "0.15.210425903-alpha" } } From 91f66caf0a58ecd35cacb4d30ba40f949e4874d9 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 21 Apr 2021 13:54:12 -0700 Subject: [PATCH 048/145] Nullable warnings as errors --- .../Microsoft.Quantum.EntryPointDriver.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Microsoft.Quantum.EntryPointDriver.csproj b/src/Simulation/EntryPointDriver/Microsoft.Quantum.EntryPointDriver.csproj index 3a6aa416ac1..20031845139 100644 --- a/src/Simulation/EntryPointDriver/Microsoft.Quantum.EntryPointDriver.csproj +++ b/src/Simulation/EntryPointDriver/Microsoft.Quantum.EntryPointDriver.csproj @@ -4,14 +4,14 @@ netstandard2.1 - enable - Microsoft.Quantum.EntryPointDriver - The standard command-line interface for standalone Q# console applications. x64 + enable + nullable - Entry point driver for Q# command line applications. + Microsoft.Quantum.EntryPointDriver + The standard command-line interface for standalone Q# console applications. Quantum Q# QSharp From 77a733d9c38f335e227dc75e1148b8a417745dde Mon Sep 17 00:00:00 2001 From: Zander Chocron Date: Fri, 23 Apr 2021 11:43:05 -0700 Subject: [PATCH 049/145] Refactor controller into library (#642) --- Simulation.sln | 38 ++-- src/Qir/Controller/Controller.cs | 32 ++- .../Driver/IQirSourceFileGenerator.cs | 22 -- .../Driver/QirSourceFileGenerator.cs | 53 ----- .../Executable/IQuantumExecutableRunner.cs | 21 -- .../Executable/QuantumExecutableRunner.cs | 41 ---- src/Qir/Controller/Program.cs | 7 +- src/Qir/Controller/QirController.csproj | 4 + .../Tests.QirController/ControllerTests.cs | 204 ------------------ .../QirDriverGeneratorTests.cs | 63 ------ .../test-cases/standalone-input-test.in | Bin 44066 -> 44066 bytes .../LoggerTests.cs | 2 +- .../QirExecutableGeneratorTests.cs | 16 +- .../QirExecutableTests.cs | 112 ++++++++++ .../Tests.Microsoft.Quantum.Qir.Tools.csproj} | 2 +- .../Util.cs | 2 +- src/Qir/Execution/Tools/AssemblyInfo.cs | 23 ++ .../Tools/Driver/IQirDriverGenerator.cs | 16 ++ .../Driver/QirFullStateDriverGenerator.cs | 23 ++ .../Tools}/Executable/ClangClient.cs | 24 ++- .../Tools}/Executable/IClangClient.cs | 4 +- .../Tools/Executable/IQirExecutable.cs | 29 +++ .../Executable/IQirExecutableGenerator.cs | 8 +- .../Executable/IQuantumExecutableRunner.cs | 20 ++ .../Tools/Executable/QirExecutable.cs | 91 ++++++++ .../Executable/QirExecutableGenerator.cs | 14 +- .../Executable/QirFullStateExecutable.cs | 32 +++ .../Executable/QuantumExecutableRunner.cs | 40 ++++ .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 4 +- src/Qir/Execution/Tools/QirExecutable.cs | 58 ----- .../Execution/Tools/QirFullStateExecutable.cs | 39 ---- .../Tools}/Utility/Clock.cs | 0 .../Tools}/Utility/IClock.cs | 0 .../Tools}/Utility/ILogger.cs | 0 .../Tools}/Utility/Logger.cs | 0 35 files changed, 462 insertions(+), 582 deletions(-) delete mode 100644 src/Qir/Controller/Driver/IQirSourceFileGenerator.cs delete mode 100644 src/Qir/Controller/Driver/QirSourceFileGenerator.cs delete mode 100644 src/Qir/Controller/Executable/IQuantumExecutableRunner.cs delete mode 100644 src/Qir/Controller/Executable/QuantumExecutableRunner.cs delete mode 100644 src/Qir/Controller/Tests.QirController/ControllerTests.cs delete mode 100644 src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs rename src/Qir/{Controller/Tests.QirController => Execution/Tests.Microsoft.Quantum.Qir.Tools}/LoggerTests.cs (98%) rename src/Qir/{Controller/Tests.QirController => Execution/Tests.Microsoft.Quantum.Qir.Tools}/QirExecutableGeneratorTests.cs (92%) create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs rename src/Qir/{Controller/Tests.QirController/Tests.QirController.csproj => Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj} (87%) rename src/Qir/{Controller/Tests.QirController => Execution/Tests.Microsoft.Quantum.Qir.Tools}/Util.cs (95%) create mode 100644 src/Qir/Execution/Tools/AssemblyInfo.cs create mode 100644 src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs rename src/Qir/{Controller => Execution/Tools}/Executable/ClangClient.cs (54%) rename src/Qir/{Controller => Execution/Tools}/Executable/IClangClient.cs (80%) create mode 100644 src/Qir/Execution/Tools/Executable/IQirExecutable.cs rename src/Qir/{Controller => Execution/Tools}/Executable/IQirExecutableGenerator.cs (75%) create mode 100644 src/Qir/Execution/Tools/Executable/IQuantumExecutableRunner.cs create mode 100644 src/Qir/Execution/Tools/Executable/QirExecutable.cs rename src/Qir/{Controller => Execution/Tools}/Executable/QirExecutableGenerator.cs (80%) create mode 100644 src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs create mode 100644 src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs delete mode 100644 src/Qir/Execution/Tools/QirExecutable.cs delete mode 100644 src/Qir/Execution/Tools/QirFullStateExecutable.cs rename src/Qir/{Controller => Execution/Tools}/Utility/Clock.cs (100%) rename src/Qir/{Controller => Execution/Tools}/Utility/IClock.cs (100%) rename src/Qir/{Controller => Execution/Tools}/Utility/ILogger.cs (100%) rename src/Qir/{Controller => Execution/Tools}/Utility/Logger.cs (100%) diff --git a/Simulation.sln b/Simulation.sln index 8bf6718fb86..1a4a4abbd59 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -117,12 +117,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Controller", "Controller", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirController", "src\Qir\Controller\QirController.csproj", "{A77E6661-D143-4E3E-BCD1-8E321A966829}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.QirController", "src\Qir\Controller\Tests.QirController\Tests.QirController.csproj", "{2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Execution", "Execution", "{442E66C8-F69F-44E9-9CD9-1F52C37EA41B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools\Microsoft.Quantum.Qir.Tools.csproj", "{C60226E3-98DE-4E92-AED4-B4A93D4CA063}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tests.Microsoft.Quantum.Qir.Tools\Tests.Microsoft.Quantum.Qir.Tools.csproj", "{4794FC80-4594-403F-AFEC-4889EFE87EA0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -775,22 +775,6 @@ Global {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|x64.ActiveCfg = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Debug|x64.Build.0 = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|Any CPU.Build.0 = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|x64.ActiveCfg = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.Release|x64.Build.0 = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.Build.0 = Debug|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -807,6 +791,22 @@ Global {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|x64.ActiveCfg = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Debug|x64.Build.0 = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|Any CPU.Build.0 = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|x64.ActiveCfg = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.Release|x64.Build.0 = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -862,9 +862,9 @@ Global {D7D34736-A719-4B45-A33F-2723F59EC29D} = {A7DB7367-9FD6-4164-8263-A05077BE54AB} {4E07F247-ED93-4497-8B58-022314308E67} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {A77E6661-D143-4E3E-BCD1-8E321A966829} = {4E07F247-ED93-4497-8B58-022314308E67} - {2E4B9604-A5CD-4B49-B1D4-A7AC8ABAEF68} = {4E07F247-ED93-4497-8B58-022314308E67} {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {C60226E3-98DE-4E92-AED4-B4A93D4CA063} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} + {4794FC80-4594-403F-AFEC-4889EFE87EA0} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 70378632128..09a8b1ef8c8 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -3,11 +3,11 @@ using System; using System.IO; +using System.Linq; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Driver; -using Microsoft.Quantum.Qir.Executable; using Microsoft.Quantum.Qir.Model; +using Microsoft.Quantum.Qir.Tools.Executable; using Microsoft.Quantum.Qir.Utility; using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; @@ -15,7 +15,6 @@ namespace Microsoft.Quantum.Qir { public static class Controller { - private const string SourceDirectoryPath = "src"; private const string BinaryDirectoryPath = "bin"; private const string ExecutableName = "simulation.exe"; @@ -25,9 +24,6 @@ public static async Task ExecuteAsync( DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo errorFile, - IQirSourceFileGenerator driverGenerator, - IQirExecutableGenerator executableGenerator, - IQuantumExecutableRunner executableRunner, ILogger logger) { try @@ -37,20 +33,20 @@ public static async Task ExecuteAsync( using var inputFileStream = inputFile.OpenRead(); var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); - // Step 2: Create driver. - logger.LogInfo("Creating driver file."); - var sourceDirectory = new DirectoryInfo(SourceDirectoryPath); - await driverGenerator.GenerateQirSourceFilesAsync(sourceDirectory, input.EntryPoint, input.QirBytecode); - - // Step 3: Create executable. - logger.LogInfo("Compiling and linking executable."); - var binaryDirectory = new DirectoryInfo(BinaryDirectoryPath); + // Step 2: Create executable. + logger.LogInfo("Creating executable."); + var bytecodeArray = input.QirBytecode.Array.Skip(input.QirBytecode.Offset).Take(input.QirBytecode.Count).ToList().ToArray(); var executableFile = new FileInfo(Path.Combine(BinaryDirectoryPath, ExecutableName)); - await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, libraryDirectory, includeDirectory); + var executable = new QirFullStateExecutable(executableFile, bytecodeArray, logger); + await executable.BuildAsync(input.EntryPoint, libraryDirectory, includeDirectory); - // Step 4: Run executable. - logger.LogInfo("Running executable."); - await executableRunner.RunExecutableAsync(executableFile, input.EntryPoint, outputFile); + // Step 3: Run executable. + if (outputFile.Exists) + { + outputFile.Delete(); + } + using var outputStream = outputFile.OpenWrite(); + await executable.RunAsync(input.EntryPoint, outputStream); } catch (Exception e) { diff --git a/src/Qir/Controller/Driver/IQirSourceFileGenerator.cs b/src/Qir/Controller/Driver/IQirSourceFileGenerator.cs deleted file mode 100644 index 92e0449c77a..00000000000 --- a/src/Qir/Controller/Driver/IQirSourceFileGenerator.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; - -namespace Microsoft.Quantum.Qir.Driver -{ - public interface IQirSourceFileGenerator - { - /// - /// Generates the C++ driver source file and writes the bytecode to a file. - /// - /// Directory to which driver and bytecode will be written. - /// Entry point information. - /// The QIR bytecode. - /// - Task GenerateQirSourceFilesAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode); - } -} diff --git a/src/Qir/Controller/Driver/QirSourceFileGenerator.cs b/src/Qir/Controller/Driver/QirSourceFileGenerator.cs deleted file mode 100644 index 7a7cfe891a2..00000000000 --- a/src/Qir/Controller/Driver/QirSourceFileGenerator.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; - -namespace Microsoft.Quantum.Qir.Driver -{ - public class QirSourceFileGenerator : IQirSourceFileGenerator - { - private const string BytecodeFileName = "qir.bc"; - private const string DriverFileName = "driver.cpp"; - private readonly ILogger logger; - - public QirSourceFileGenerator(ILogger logger) - { - this.logger = logger; - } - - public async Task GenerateQirSourceFilesAsync(DirectoryInfo sourceDirectory, EntryPointOperation entryPointOperation, ArraySegment bytecode) - { - if (sourceDirectory.Exists) - { - sourceDirectory.Delete(true); - } - - sourceDirectory.Create(); - logger.LogInfo($"Created source directory at {sourceDirectory.FullName}."); - - // Create driver. - var driverFile = new FileInfo(Path.Combine(sourceDirectory.FullName, DriverFileName)); - using var driverFileStream = driverFile.OpenWrite(); - GenerateQirDriverCppHelper(entryPointOperation, driverFileStream); - logger.LogInfo($"Created driver file at {driverFile.FullName}."); - - // Create bytecode file. - var bytecodeFile = new FileInfo(Path.Combine(sourceDirectory.FullName, BytecodeFileName)); - using var bytecodeFileStream = bytecodeFile.OpenWrite(); - await bytecodeFileStream.WriteAsync(bytecode.Array, bytecode.Offset, bytecode.Count); - logger.LogInfo($"Created bytecode file at {bytecodeFile.FullName}."); - } - - // Virtual method wrapper is to enable mocking in unit tests. - public virtual void GenerateQirDriverCppHelper(EntryPointOperation entryPointOperation, Stream stream) - { - QirDriverGeneration.GenerateQirDriverCpp(entryPointOperation, stream); - } - } -} diff --git a/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs b/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs deleted file mode 100644 index 135fbbbfb4f..00000000000 --- a/src/Qir/Controller/Executable/IQuantumExecutableRunner.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.IO; -using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; - -namespace Microsoft.Quantum.Qir.Executable -{ - public interface IQuantumExecutableRunner - { - /// - /// Runs a quantum program executable with the given arguments. - /// - /// Location of the executable to run. - /// Entry point and arguments to pass. - /// Location to write program output. - /// - Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile); - } -} diff --git a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs b/src/Qir/Controller/Executable/QuantumExecutableRunner.cs deleted file mode 100644 index 8ce2bcd41d7..00000000000 --- a/src/Qir/Controller/Executable/QuantumExecutableRunner.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.CommandLine.Invocation; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; - -namespace Microsoft.Quantum.Qir.Executable -{ - public class QuantumExecutableRunner : IQuantumExecutableRunner - { - private readonly ILogger logger; - - public QuantumExecutableRunner(ILogger logger) - { - this.logger = logger; - } - - public async Task RunExecutableAsync(FileInfo executableFile, EntryPointOperation entryPointOperation, FileInfo outputFile) - { - var arguments = QirDriverGeneration.GenerateCommandLineArguments(entryPointOperation.Arguments); - logger.LogInfo($"Invoking executable {executableFile.FullName} with the following arguments: {arguments}"); - arguments = $"--simulation-output {outputFile.FullName} {arguments}"; - if (outputFile.Exists) - { - outputFile.Delete(); - } - - outputFile.Create().Dispose(); - var result = await Process.ExecuteAsync( - executableFile.FullName, - arguments, - stdOut: s => { logger.LogInfo("executable: " + s); }, - stdErr: s => { logger.LogError("executable: " + s); }); - logger.LogInfo($"Executable has finished running. Result code: {result}"); - } - } -} diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 6def5f9d223..df24e0632f9 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -4,8 +4,6 @@ using System.CommandLine; using System.CommandLine.Invocation; using System.IO; -using Microsoft.Quantum.Qir.Driver; -using Microsoft.Quantum.Qir.Executable; using Microsoft.Quantum.Qir.Utility; namespace Microsoft.Quantum.Qir @@ -15,9 +13,6 @@ class Program static void Main(string[] args) { var logger = new Logger(new Clock()); - var execGenerator = new QirExecutableGenerator(new ClangClient(logger), logger); - var driverGenerator = new QirSourceFileGenerator(logger); - var execRunner = new QuantumExecutableRunner(logger); logger.LogInfo("QIR controller beginning."); var rootCommand = new RootCommand( @@ -69,7 +64,7 @@ static void Main(string[] args) // Bind to a handler and invoke. rootCommand.Handler = CommandHandler.Create( async (input, output, libraryDirectory, includeDirectory, error) => - await Controller.ExecuteAsync(input, output, libraryDirectory, includeDirectory, error, driverGenerator, execGenerator, execRunner, logger)); + await Controller.ExecuteAsync(input, output, libraryDirectory, includeDirectory, error, logger)); rootCommand.Invoke(args); } } diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index e9574233c00..c4398261366 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -26,6 +26,10 @@ + + + + True diff --git a/src/Qir/Controller/Tests.QirController/ControllerTests.cs b/src/Qir/Controller/Tests.QirController/ControllerTests.cs deleted file mode 100644 index 6e85b07976b..00000000000 --- a/src/Qir/Controller/Tests.QirController/ControllerTests.cs +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Quantum.Qir; -using Microsoft.Quantum.Qir.Driver; -using Microsoft.Quantum.Qir.Executable; -using Microsoft.Quantum.Qir.Model; -using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; -using Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper; -using Moq; -using Xunit; -using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; - -namespace Tests.QirController -{ - public class ControllerTests : IDisposable - { - private Mock driverGeneratorMock; - private Mock executableGeneratorMock; - private Mock executableRunnerMock; - private Mock loggerMock; - private FileInfo inputFile; - private FileInfo bytecodeFile; - private FileInfo errorFile; - private FileInfo outputFile; - private QirExecutionWrapper input; - - public ControllerTests() - { - driverGeneratorMock = new Mock(); - executableGeneratorMock = new Mock(); - executableRunnerMock = new Mock(); - inputFile = new FileInfo($"{Guid.NewGuid()}-input"); - bytecodeFile = new FileInfo($"{Guid.NewGuid()}-bytecode"); - errorFile = new FileInfo($"{Guid.NewGuid()}-error"); - outputFile = new FileInfo($"{Guid.NewGuid()}-output"); - loggerMock = new Mock(); - - // Create a QirExecutableWrapper to be used by the tests. - byte[] bytecode = { 1, 2, 3, 4, 5 }; - input = new QirExecutionWrapper() - { - EntryPoint = new EntryPointOperation() - { - Arguments = new List - { - new Argument() - { - Position = 0, - Name = "argname", - Values = new List { new ArgumentValue { String = "argvalue" } }, - } - } - }, - QirBytecode = new ArraySegment(bytecode, 1, 3), - }; - using var fileStream = inputFile.OpenWrite(); - QirExecutionWrapperSerialization.SerializeToFastBinary(input, fileStream); - } - - public void Dispose() - { - inputFile.Delete(); - bytecodeFile.Delete(); - errorFile.Delete(); - outputFile.Delete(); - } - - [Fact] - public async Task TestExecute() - { - var libraryDirectory = new DirectoryInfo("libraries"); - var includeDirectory = new DirectoryInfo("includes"); - FileInfo actualExecutableFile = null; - Action generateExecutableCallback = async (executableFile, srcDir, libDir, inclDir) => - { - actualExecutableFile = executableFile; - await Task.CompletedTask; - }; - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync( - It.IsAny(), - It.IsAny(), - It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), - It.Is(actualIncludeDirectory => actualIncludeDirectory.FullName == includeDirectory.FullName))).Callback(generateExecutableCallback); - - await Controller.ExecuteAsync( - inputFile, - outputFile, - libraryDirectory, - includeDirectory, - errorFile, - driverGeneratorMock.Object, - executableGeneratorMock.Object, - executableRunnerMock.Object, - loggerMock.Object); - - // Verify driver was created. - driverGeneratorMock.Verify(obj => obj.GenerateQirSourceFilesAsync( - It.IsAny(), - It.Is(entryPoint => Util.EntryPointsAreEqual(entryPoint, input.EntryPoint)), - It.Is>(bytecode => BytecodesAreEqual(bytecode, input.QirBytecode)))); - - // Verify executable was generated. - executableGeneratorMock.Verify(obj => obj.GenerateExecutableAsync( - It.IsAny(), - It.IsAny(), - It.Is(actualLibraryDirectory => actualLibraryDirectory.FullName == libraryDirectory.FullName), - It.Is(actualIncludeDirectory => actualIncludeDirectory.FullName == includeDirectory.FullName))); - Assert.NotNull(actualExecutableFile); - - // Verify executable was run. - executableRunnerMock.Verify(obj => obj.RunExecutableAsync( - It.Is(executableFile => actualExecutableFile.FullName == executableFile.FullName), - It.Is(entryPoint => Util.EntryPointsAreEqual(entryPoint, input.EntryPoint)), - It.Is(actualOutputFile => actualOutputFile.FullName == outputFile.FullName))); - } - - [Fact] - public async Task TestExecuteEncountersGenericException() - { - var libraryDirectory = new DirectoryInfo("libraries"); - var includeDirectory = new DirectoryInfo("includes"); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("exception message")); - - // Execute controller. - await Controller.ExecuteAsync( - inputFile, - outputFile, - libraryDirectory, - includeDirectory, - errorFile, - driverGeneratorMock.Object, - executableGeneratorMock.Object, - executableRunnerMock.Object, - loggerMock.Object); - - // Verify error file was created and contains the error. - Assert.True(errorFile.Exists); - using var errorFileStream = errorFile.OpenRead(); - using var streamReader = new StreamReader(errorFileStream); - var errorFileContents = await streamReader.ReadToEndAsync(); - var error = JsonSerializer.Deserialize(errorFileContents); - Assert.Equal(ErrorMessages.InternalError, error.Message); - Assert.Equal(Constant.ErrorCode.InternalError, error.Code); - } - - [Fact] - public async Task TestExecuteEncountersControllerException() - { - var exceptionMessage = "exception message"; - var errorCode = "error code"; - var libraryDirectory = new DirectoryInfo("libraries"); - var includeDirectory = new DirectoryInfo("includes"); - executableGeneratorMock.Setup(obj => obj.GenerateExecutableAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new ControllerException(exceptionMessage, errorCode)); - - // Execute controller. - await Controller.ExecuteAsync( - inputFile, - outputFile, - libraryDirectory, - includeDirectory, - errorFile, - driverGeneratorMock.Object, - executableGeneratorMock.Object, - executableRunnerMock.Object, - loggerMock.Object); - - // Verify error file was created and contains the error. - Assert.True(errorFile.Exists); - using var errorFileStream = errorFile.OpenRead(); - using var streamReader = new StreamReader(errorFileStream); - var errorFileContents = await streamReader.ReadToEndAsync(); - var error = JsonSerializer.Deserialize(errorFileContents); - Assert.Equal(exceptionMessage, error.Message); - Assert.Equal(errorCode, error.Code); - } - - private bool BytecodesAreEqual(ArraySegment bytecodeA, ArraySegment bytecodeB) - { - if (bytecodeA.Count != bytecodeB.Count) - { - return false; - } - - for (var i = 0; i < bytecodeA.Count; ++i) - { - if (bytecodeA[i] != bytecodeB[i]) - { - return false; - } - } - - return true; - } - } -} diff --git a/src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs b/src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs deleted file mode 100644 index e93837e62ea..00000000000 --- a/src/Qir/Controller/Tests.QirController/QirDriverGeneratorTests.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Driver; -using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; -using Moq; -using Xunit; - -namespace Tests.QirController -{ - public class QirDriverGeneratorTests : IDisposable - { - private readonly Mock driverGeneratorMock; - private readonly DirectoryInfo sourceDirectory; - - public QirDriverGeneratorTests() - { - driverGeneratorMock = new Mock(Mock.Of()) { CallBase = true }; - driverGeneratorMock.Setup(obj => obj.GenerateQirDriverCppHelper(It.IsAny(), It.IsAny())); - sourceDirectory = new DirectoryInfo($"{Guid.NewGuid()}-source"); - } - - public void Dispose() - { - Util.DeleteDirectory(sourceDirectory); - } - - [Fact] - public async Task TestGenerateDriver() - { - var entryPoint = new EntryPointOperation() - { - Arguments = new List - { - new Argument() - { - Position = 0, - Name = "argname", - Values = new List { new ArgumentValue { String = "argvalue" } }, - } - } - }; - byte[] bytes = { 1, 2, 3, 4, 5 }; - var bytecode = new ArraySegment(bytes, 1, 3); - await driverGeneratorMock.Object.GenerateQirSourceFilesAsync(sourceDirectory, entryPoint, bytecode); - driverGeneratorMock.Verify(obj => obj.GenerateQirDriverCppHelper(It.Is(actualEntryPoint => Util.EntryPointsAreEqual(entryPoint, actualEntryPoint)), It.IsAny())); - - // Verify that the "bytecode" file was created correctly. - var bytecodeFilePath = new FileInfo(Path.Combine(sourceDirectory.FullName, "qir.bc")); - using var bytecodeFileStream = bytecodeFilePath.OpenRead(); - Assert.Equal(bytecodeFileStream.Length, bytecode.Count); - for (var i = 0; i < bytecodeFileStream.Length; ++i) - { - Assert.Equal(bytecode[i], bytecodeFileStream.ReadByte()); - } - } - } -} diff --git a/src/Qir/Controller/test-cases/standalone-input-test.in b/src/Qir/Controller/test-cases/standalone-input-test.in index 2251eb15f36354835911c0b1eb4f81ff2a71e3a6..82a74f144f9776df10dafdcf777f60566c6767c0 100644 GIT binary patch delta 7903 zcmeHLdvH|M8Q*(%2`jr?*4K4%P5dzLst;|S@cEHxUw3(@`Px@YgZ@ZNXfo_A~|`M#BznZ?i9o$yO{kN81{J16Jkl69L;*dG}c z46Z-o^knSaS1m~O_WXTOXjs+owcWuI3uG~V8z8j%cgKS1cS3f9vs606`P&w_7EZoe z(*G9s{xHN8v|yIUzH^v;9vW^lNhB@SQ8Ru0qVvN{&XSb8FeSb=Sa$WMr{9CJTL+n> zssD%TaGzuF2E4_2;Gs2VAHCYpyURz4Zdc_X(WGRnW&OfIoW*TznzikN*VmS9wGN`g znU?C3`|?g8+2KKK+>&|c<4P{`@@K!u`%TwiOVv%K&#R9O=2VY9bEW^>ptTlt z!#9v#Wy6Ukozz`1{);r#YxM8qufSi}8`Ks%#;@w1u-9pSd8DiNFV1mpC}=528>XoL50yku6tA;7iz2?1 z@rB_2(gy3Q$OLe()TfwS=1G|x2d7JmChdE?TQ_-g;l?G~yO;-jP1_Ml&8k4(5|?=&vB&*G%$#@J|hJBS+BD`qZ;L#EQmerKqYWYnFsnAN?q^z*Y$v9 zk?Y>}4fdM)Huwu03@ay?urO${ATl#|ZNhQ6-j+HJ>TzljH{59tNg_)OaT)Xb0!O7vlfH z@P=Z0zUI`fw3Qz8k!9hn?Qo7RbO7;22;DbsZ{+P`X^%G)_v!K-BS=qW>OKhY=Iq?D zJq`?$&c5>63Oll&c2$vDYW0@A3ZNPv%=CcQ@9>W~A8ImEPKD}y^iDnl>T7(NhwHty z0bOBubT7r%tC!J_fZ~dRvheg+YT>1j0ul8h%g)DrIlUVqP#DSF57o9qw0^!AI8l@D z4<9{ftce>iJiW(Yfv2|7+H`Rl;A*|jrc=vOC#nEX)V>BE>I1)OEOLDa&$Z3a4eOi( znwNB1dmJcmEzPt35uOXsrG?gng9Q20y#;O;=Gmy%%|xhWrM6$}Li{03CG@NpJh^l} zVC!e5L*=&Pn&~a$w}4Ic3!OVcMrqm#7FF-Li3Yqd{p*auZ(*80|BXnwF*Vnja^J7{ zCZ*ikIosevXTc8_6ivR=R%<({rA>ELqwVyDpql*c>uQyHJzSk>9F!;f9X+o|@WFzY zzH+iI|L(ol+GCR2MJfreb(MGs{>fe5NUHaAs4)58p%(9gw9W62TOa#*>pA4U_q4FOR5cfzn(s|- zub!&}ojS?7T{yTn-@h1cw4Kpo^GKZnAy|pcfwp;bPANg6&dQOjo=|2>s^yk?(sc3t z(Be7oYbzBP(qT8;n4N-0>I|r80W0oN8p%EL{Fc!tDZOPTyau$4e#>CNm3yw$$!?X1 zy14e)YqZK+<%Iopjo_0e1T0_+0l|6v@NBm}_H-YaWk7hg(_q1){7moyr!BdQEmfDz z`|@S8j2*sQR#CAOfGH(e3CAUKI4?7Y^Gj~<$&{S2Wdr6A9y5pVfokyS%uEnnp5gCo zuTM?sJ51OaGFkAVK>0i44ThKrJKIebR6Hny<>E~}^&QflnlevmYE+!;DJ@^VI%Ck> z?Dhr;Jtr+H)Jn*b?Og~`^YjF^pM znFpJ*+ZKPkXe@1ADojiLGm=E>QEW@iR{0(+#{y`o2EjwF}Ao8Zevys)~wcx z*?tptSJh>|tLukNSXE~;S&;ugWkFTlG?Ou4RUK)vp#6bYu91^BVt#(%zPg*X`>JG? zeVbAyb`#=xQS%Lo=cCQv@OZvedd#<@i*8zT?+uRj^meQI@uAIu6TzLW{zv3tbL08&GnBx!n>+h2K+`WVT05$7pKuyst>uH`NE}X+7>!bfAV%N>jqxl_$vjEPEJtu6L(&XK@KPW^ z(uN?;;5aQv0YXw#lY+?5BF)G=MW8H!1$fC26mXPh8HJ;9l$1r9#RWp-7)GWQ8&OVH z1*4yLgkS`h1X{*q4C90VNue}H(vl>xguvhoieorf1TcicagpaqOrltlWC(!`FsQ)c zj6e~B#7iRRQG|xzmv%&wMINO^MHeZO3>#n>hM^S;C|r^RhLw}*I8{9x5XAr!AbD2c zXjXD>q{<=04FS@hZXU{Ij|C^6 z8B!8xfENo>V{D7jB1fQe4Vv9Xoi zkP2wP$O(!K#lS=%h{Mvg15Qib#6W3nCHSbc(h(-~WwC~unW}}-dw1_6BW6euEmAYH zlW)HJ-~V;~|D6AxT_?@EPMX8-Sf)=)DJyGgDtN&$bEfa5+b!cV-$w)G8#X(?ztx{( zY3q9|>M7-aP(8rbbw!|YW#iXgC@VIN_}c)%-CJJENxTiR8EmN|nDh31&ieM7OAXS* znH)V8O&iuNH<=AKDWR@h+?_z59l@D`X{LG8J2M~2Ni_sbrhZe}ZEvsrF#3Tx$)FX{ zy=hs;x>AD%85ccoa=tu*GkL7h_Px)qUtt?Rl0{69erI_0>OqsmU=_*tkF3Z3GR|X= zCPnhWwR6J$gb}17T5)PUaqkE&X8tD^2JRopDbc_6$j9_ZPSMyi_i}}M|NS`%LpcYm z^`>c`akGBnP5U!~Ba|vxdd_#ingRZrSWtL*TC=7`FHh_F8Ibb~nC(0R^+mELAQoHn z;?av<|3B{pweDXew4BO_cvBiCIHn!Q@L8>Mn=v-~?yyM~*2;kl*C9j+4#*mqsG57pzNgYnm=7S^??exL1sPz&L7B(La+ zgwMKP6L;NlFjaNkb#<=C@{@&rUVa(~H9si_^S@YrVn!Y%e*}R~*gTs}Szo)C1vRwC zTbdkzxjK`_X6=CuSeiUfXMug@VsM5gm3P5xCgZAf{E``?sSTihfgKdC$p#x2OiB;i zJvA0>QDK)OUL6B=j|&v>nRIb$AV*uV{y=G4T8dJ1C9Qf$jmZ$AMpvi6pc3fI)xcTq z_2%d3<&tN>e3!w3M`tYpJ>~Y)y!&-BpVeU=h?cJecir+8Wo9v$ws79v7gyCe*0m&| z@u=!Osi8Msv5v1Pu;s+l)MagQ!53ErJ6g?|s!&goJA|oOFu6l-zGB^2Q!t>)x8IDp zO0^85;8zQ?Cd1C@hlc+Y_p6 zg(x+?)8O@r9Pfqx1Nu7#ybuWMEO1rUdgq>Btwl1&fOAh6EO@-~uz9c!{Jb{b+3{+* zWxnd>_HxirzdZqVP6N(W*$Hj)DgnGIFClEFK+dgh-+&!+wW)jFzCdGB+)A{k|ADvz z(C%dL#HuBLsa}v6nr%5252SIp9c-$;+tCrwx0QCVV&2X#(Sa9l{fdh5Yu2Xwu8Y1& zt+>j*`Ci5K+c#?$Z8Z-zg2$HT7oRIzWH}zM{qC|_%NrZ~NY-F5*n3V=#Sy#-V=J)zNYnm1vpdn?A7<~ zjgkc9_Rjx#r#MQE$%_>~GERfg5^r(4JER{c3XDA)G`W{rH@`b&ee}o8gP!HTioC+^S#}hAlUvFinhT?NvnnySM)%uS1BTd4A#A@?txxAA#&muu zNgK*L0m|NA3dP%e0>0EPB9Pnfw_`5(DE(Io9b>?roh-qERVIdlj-{!GFn!?ziD0R(zxBQ zoj9;ab3t^~Y1<|Oo|C-GZgC0PvsnsM&hbX)P?A2a_f|Zl?!9{q*ln)LIH}t2TdYHK zmBnB|&ON0*bJZ;dqeF8QZm^*BoA==mPXX%^$( zOTEQ!ft}4MGfUpm=kp|YZx})>7I<~3EfZ3&NU~2Ixi>styLXGa{n~UJ1|K$0qW5XH z!=ZE?`lk=|hqTL_a|Rp=1a%h7e%KE-K5S1t*S}69hXOi02f7{}?VR|g?7t>o;Sr?u zALjhVtiiA|K6P|i|BTrGrrt%@H)ib`@c>k;pAR)go?Jh}lJ9SBPnZ=S{zB>9C)VWH|xFDV$>^j>1R^!z7NUc#7c!MKJQO_JG-g^CW^| zD2fOYhjS7l`^=LVPjNU#;FQRK6#(&Y63vpR#Iuyh;{q;nnCvNv69OV~wCpSh%R*zw zORGm97!H9+f`kbQ$6$eF5tbK4oTV9tqEIqsj^+>=qevEIc?^f;@I*q87=gi1hG#?; ziiEsR2GR*G31!-6B=$kX5U@F+@g3__B!+c+y5rC?G{D%B6#W#Ah1Dvfh)y@gI(<58{Gj$ZuS53~5m{ zUOAX4prrFwuygl35bT-+TDQBv_-EXpX-hiT*O?dDy8R;vOxSJ(pLR}^iJKx%?!X`g ZfcHA5fQj2Dfj?}SAPXc$PCQ%V_z#g@MX~?@ diff --git a/src/Qir/Controller/Tests.QirController/LoggerTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs similarity index 98% rename from src/Qir/Controller/Tests.QirController/LoggerTests.cs rename to src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs index ee7adfee70a..1df4bf96552 100644 --- a/src/Qir/Controller/Tests.QirController/LoggerTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs @@ -7,7 +7,7 @@ using Moq; using Xunit; -namespace Tests.QirController +namespace Tests.Microsoft.Quantum.Qir.Tools { public class LoggerTests { diff --git a/src/Qir/Controller/Tests.QirController/QirExecutableGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs similarity index 92% rename from src/Qir/Controller/Tests.QirController/QirExecutableGeneratorTests.cs rename to src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs index 3d9da400687..93a6f98a786 100644 --- a/src/Qir/Controller/Tests.QirController/QirExecutableGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs @@ -6,12 +6,12 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Executable; +using Microsoft.Quantum.Qir.Tools.Executable; using Microsoft.Quantum.Qir.Utility; using Moq; using Xunit; -namespace Tests.QirController +namespace Tests.Microsoft.Quantum.Qir.Tools { public class QirExecutableGeneratorTests : IDisposable { @@ -23,6 +23,7 @@ public class QirExecutableGeneratorTests : IDisposable private readonly DirectoryInfo binDirectory; private readonly IList libraryFiles; private readonly IList sourceFiles; + private IList linkLibraries; public QirExecutableGeneratorTests() { @@ -49,6 +50,7 @@ public QirExecutableGeneratorTests() CreateFile("src1.cpp", sourceDirectory, "src1 contents"), CreateFile("src2.bc", sourceDirectory, "src2 contents"), }; + linkLibraries = new List { "lib1", "lib2" }; } public void Dispose() @@ -62,19 +64,13 @@ public void Dispose() [Fact] public async Task TestGenerateExecutable() { - string[] expectedLibraries = { - "Microsoft.Quantum.Qir.Runtime", - "Microsoft.Quantum.Qir.QSharp.Foundation", - "Microsoft.Quantum.Qir.QSharp.Core" - }; - var executableFile = new FileInfo(Path.Combine(binDirectory.FullName, "executableFile")); - await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, libraryDirectory, includeDirectory); + await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, libraryDirectory, includeDirectory, linkLibraries); // Verify invocation of clang. clangClientMock.Verify(obj => obj.CreateExecutableAsync( It.Is(s => s.SequenceEqual(sourceFiles.Select(fileInfo => fileInfo.FullName))), - It.Is(s => s.SequenceEqual(expectedLibraries)), + It.Is(s => s.SequenceEqual(linkLibraries)), libraryDirectory.FullName, includeDirectory.FullName, executableFile.FullName)); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs new file mode 100644 index 00000000000..217a12ca09c --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Tools.Driver; +using Microsoft.Quantum.Qir.Tools.Executable; +using Microsoft.Quantum.Qir.Utility; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Moq; +using Xunit; + +namespace Tests.Microsoft.Quantum.Qir.Tools +{ + public class QirExecutableTests : IDisposable + { + private readonly DirectoryInfo sourceDirectory; + private readonly DirectoryInfo includeDirectory; + private readonly DirectoryInfo libraryDirectory; + private readonly DirectoryInfo binDirectory; + private readonly Mock driverGeneratorMock; + private readonly Mock executableGeneratorMock; + private readonly Mock runnerMock; + private readonly Mock qirExecutable; + private readonly FileInfo executableFile; + private readonly byte[] qirBytecode = { 1, 2, 3, 4, 5 }; + private readonly IList linkLibraries; + + public QirExecutableTests() + { + // Set up files. + var prefix = Guid.NewGuid().ToString(); + binDirectory = new DirectoryInfo($"{prefix}-bin"); + binDirectory.Create(); + libraryDirectory = new DirectoryInfo($"{prefix}-library"); + libraryDirectory.Create(); + includeDirectory = new DirectoryInfo($"{prefix}-include"); + includeDirectory.Create(); + sourceDirectory = new DirectoryInfo($"{prefix}-source"); + sourceDirectory.Create(); + executableFile = new FileInfo(Path.Combine(binDirectory.FullName, "executable")); + driverGeneratorMock = new Mock(); + executableGeneratorMock = new Mock(); + runnerMock = new Mock(); + qirExecutable = new Mock(executableFile, qirBytecode, Mock.Of(), driverGeneratorMock.Object, executableGeneratorMock.Object, runnerMock.Object) { CallBase = true }; + linkLibraries = new List { "lib1", "lib2" }; + qirExecutable.SetupGet(obj => obj.LinkLibraries).Returns(linkLibraries); + qirExecutable.SetupGet(obj => obj.SourceDirectoryPath).Returns(sourceDirectory.FullName); + qirExecutable.SetupGet(obj => obj.DriverFileExtension).Returns(".cpp"); + } + + public void Dispose() + { + Util.DeleteDirectory(sourceDirectory); + Util.DeleteDirectory(includeDirectory); + Util.DeleteDirectory(libraryDirectory); + Util.DeleteDirectory(binDirectory); + } + + [Fact] + public async Task TestBuild() + { + // Set up. + var entryPoint = new EntryPointOperation(); + var driverFileContents = "driver file contents"; + driverGeneratorMock.Setup(obj => obj.GenerateAsync(entryPoint, It.IsAny())).Callback((entryPoint, stream) => + { + using var streamWriter = new StreamWriter(stream); + streamWriter.Write(driverFileContents); + }); + + // Build the executable. + await qirExecutable.Object.BuildAsync(entryPoint, libraryDirectory, includeDirectory); + + // Verify that the "bytecode" file was created correctly. + var bytecodeFilePath = new FileInfo(Path.Combine(sourceDirectory.FullName, "qir.bc")); + using var bytecodeFileStream = bytecodeFilePath.OpenRead(); + Assert.Equal(bytecodeFileStream.Length, qirBytecode.Length); + for (var i = 0; i < bytecodeFileStream.Length; ++i) + { + Assert.Equal(qirBytecode[i], bytecodeFileStream.ReadByte()); + } + + // Verify that the driver was written to the correct file. + var driver = new FileInfo(Path.Combine(sourceDirectory.FullName, "driver.cpp")); + using var driverStreamReader = driver.OpenText(); + var actualDriverContents = driverStreamReader.ReadToEnd(); + Assert.Equal(driverFileContents, actualDriverContents); + + // Verify that the executable was generated. + executableGeneratorMock.Verify(obj => obj.GenerateExecutableAsync(executableFile, It.Is(arg => arg.FullName == sourceDirectory.FullName), libraryDirectory, includeDirectory, linkLibraries)); + } + + [Fact] + public async Task TestRun() + { + // Set up. + using var outputStream = new MemoryStream(); + var entryPoint = new EntryPointOperation(); + var arguments = "arguments"; + driverGeneratorMock.Setup(obj => obj.GetCommandLineArguments(entryPoint)).Returns(arguments); + + // Run executable. + await qirExecutable.Object.RunAsync(entryPoint, outputStream); + + // Verify runner was invoked properly. + runnerMock.Verify(obj => obj.RunExecutableAsync(executableFile, outputStream, arguments)); + } + } +} diff --git a/src/Qir/Controller/Tests.QirController/Tests.QirController.csproj b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj similarity index 87% rename from src/Qir/Controller/Tests.QirController/Tests.QirController.csproj rename to src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj index ba5183ca742..55ffaa29bd4 100644 --- a/src/Qir/Controller/Tests.QirController/Tests.QirController.csproj +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/Qir/Controller/Tests.QirController/Util.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs similarity index 95% rename from src/Qir/Controller/Tests.QirController/Util.cs rename to src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs index 476848705ea..85c1d3a90e6 100644 --- a/src/Qir/Controller/Tests.QirController/Util.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs @@ -5,7 +5,7 @@ using System.Reflection; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; -namespace Tests.QirController +namespace Tests.Microsoft.Quantum.Qir.Tools { public static class Util { diff --git a/src/Qir/Execution/Tools/AssemblyInfo.cs b/src/Qir/Execution/Tools/AssemblyInfo.cs new file mode 100644 index 00000000000..1a412a83263 --- /dev/null +++ b/src/Qir/Execution/Tools/AssemblyInfo.cs @@ -0,0 +1,23 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// In SDK-style projects such as this one, several assembly attributes that were historically +// defined in this file are now automatically added during build and populated with +// values defined in project properties. For details of which attributes are included +// and how to customise this process see: https://aka.ms/assembly-info-properties + + +// Setting ComVisible to false makes the types in this assembly not visible to COM +// components. If you need to access a type in this assembly from COM, set the ComVisible +// attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM. + +[assembly: Guid("1594aae8-0e24-442b-9201-430ce9ee4d2e")] + +[assembly: InternalsVisibleTo("Tests.Microsoft.Quantum.Qir.Tools")] + +// This is required to mock internals in tests. +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] diff --git a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs new file mode 100644 index 00000000000..5c995bd7d0a --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public interface IQirDriverGenerator + { + Task GenerateAsync(EntryPointOperation entryPoint, Stream stream); + + string GetCommandLineArguments(EntryPointOperation entryPoint); + } +} diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs new file mode 100644 index 00000000000..e09ac1196c1 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public class QirFullStateDriverGenerator: IQirDriverGenerator + { + public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) + { + await Task.Run(() => QirDriverGeneration.GenerateQirDriverCpp(entryPoint, stream)); + } + + public string GetCommandLineArguments(EntryPointOperation entryPoint) + { + return QirDriverGeneration.GenerateCommandLineArguments(entryPoint.Arguments); + } + } +} diff --git a/src/Qir/Controller/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs similarity index 54% rename from src/Qir/Controller/Executable/ClangClient.cs rename to src/Qir/Execution/Tools/Executable/ClangClient.cs index 81bd435aff4..d4a204642a2 100644 --- a/src/Qir/Controller/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.CommandLine.Invocation; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; -namespace Microsoft.Quantum.Qir.Executable +namespace Microsoft.Quantum.Qir.Tools.Executable { - public class ClangClient : IClangClient + internal class ClangClient : IClangClient { private const string LinkFlag = " -l "; private readonly ILogger logger; @@ -23,13 +23,19 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, // string.Join does not automatically prepend the delimiter, so it is included again in the string here. var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; - var arguments = $"-v {inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath}"; + var arguments = $"{inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath}"; logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); - var result = await Process.ExecuteAsync( - "clang", - arguments, - stdOut: s => { logger.LogInfo("clang: " + s); }, - stdErr: s => { logger.LogError("clang: " + s); }); + var taskCompletionSource = new TaskCompletionSource(); + using var process = new Process(); + process.StartInfo = new ProcessStartInfo + { + FileName = "clang", + Arguments = arguments, + }; + process.EnableRaisingEvents = true; + process.Exited += (sender, args) => { taskCompletionSource.SetResult(true); }; + process.Start(); + await taskCompletionSource.Task; } } } diff --git a/src/Qir/Controller/Executable/IClangClient.cs b/src/Qir/Execution/Tools/Executable/IClangClient.cs similarity index 80% rename from src/Qir/Controller/Executable/IClangClient.cs rename to src/Qir/Execution/Tools/Executable/IClangClient.cs index 7e7a8e1c95d..f5a1bb38135 100644 --- a/src/Qir/Controller/Executable/IClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/IClangClient.cs @@ -3,12 +3,12 @@ using System.Threading.Tasks; -namespace Microsoft.Quantum.Qir.Executable +namespace Microsoft.Quantum.Qir.Tools.Executable { /// /// Wraps the 'clang' tool used for compilation. /// - public interface IClangClient + internal interface IClangClient { Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string includePath, string outputPath); } diff --git a/src/Qir/Execution/Tools/Executable/IQirExecutable.cs b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs new file mode 100644 index 00000000000..6dc5914b5ea --- /dev/null +++ b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Tools.Executable +{ + public interface IQirExecutable + { + /// + /// Builds the executable. + /// + /// Entry point operation. + /// Directory containing libraries to link. + /// Directory containing files to include. + /// + Task BuildAsync(EntryPointOperation entryPoint, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory); + + /// + /// Runs the executable. + /// + /// Entry point operation. + /// Stream to which output will be written. + /// + Task RunAsync(EntryPointOperation entryPoint, Stream output); + } +} diff --git a/src/Qir/Controller/Executable/IQirExecutableGenerator.cs b/src/Qir/Execution/Tools/Executable/IQirExecutableGenerator.cs similarity index 75% rename from src/Qir/Controller/Executable/IQirExecutableGenerator.cs rename to src/Qir/Execution/Tools/Executable/IQirExecutableGenerator.cs index e8ce44f7b7a..3ddb310f98e 100644 --- a/src/Qir/Controller/Executable/IQirExecutableGenerator.cs +++ b/src/Qir/Execution/Tools/Executable/IQirExecutableGenerator.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -namespace Microsoft.Quantum.Qir.Executable +namespace Microsoft.Quantum.Qir.Tools.Executable { - public interface IQirExecutableGenerator + internal interface IQirExecutableGenerator { /// /// Generates a quantum simulation program executable. @@ -15,7 +16,8 @@ public interface IQirExecutableGenerator /// Location of the source files. /// Location of the libraries that must be linked. /// Location of the headers that must be included. + /// Libraries to link. /// - public Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory); + public Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, IList linkLibraries); } } diff --git a/src/Qir/Execution/Tools/Executable/IQuantumExecutableRunner.cs b/src/Qir/Execution/Tools/Executable/IQuantumExecutableRunner.cs new file mode 100644 index 00000000000..292cb394737 --- /dev/null +++ b/src/Qir/Execution/Tools/Executable/IQuantumExecutableRunner.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Tools.Executable +{ + internal interface IQuantumExecutableRunner + { + /// + /// Runs a quantum program executable with the given arguments. + /// + /// Location of the executable to run. + /// Stream to write program output. + /// Arguments to supply the program with. + /// + Task RunExecutableAsync(FileInfo executableFile, Stream stream, string arguments); + } +} diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs new file mode 100644 index 00000000000..265006d2034 --- /dev/null +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Tools.Driver; +using Microsoft.Quantum.Qir.Utility; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Tools.Executable +{ + /// + /// Base for creating and running QIR-based executables. + /// + public abstract class QirExecutable : IQirExecutable + { + private const string DriverFileName = "driver"; + private const string BytecodeFileName = "qir.bc"; + + public virtual string SourceDirectoryPath => "src"; + public abstract string DriverFileExtension { get; } + + protected FileInfo ExecutableFile { get; } + + private readonly byte[] qirBytecode; + private readonly ILogger logger; + private readonly IQuantumExecutableRunner runner; + private readonly IQirDriverGenerator driverGenerator; + private readonly IQirExecutableGenerator executableGenerator; + + public QirExecutable(FileInfo executableFile, byte[] qirBytecode, IQirDriverGenerator driverGenerator, ILogger logger = null) + : this(executableFile, + qirBytecode, + logger ?? new Logger(new Clock()), + driverGenerator, + new QirExecutableGenerator(new ClangClient(logger), logger), + new QuantumExecutableRunner(logger)) + { + } + + internal QirExecutable(FileInfo executableFile, byte[] qirBytecode, ILogger logger, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner runner) + { + ExecutableFile = executableFile; + this.qirBytecode = qirBytecode; + this.logger = logger; + this.runner = runner; + this.driverGenerator = driverGenerator; + this.executableGenerator = executableGenerator; + } + + public async Task BuildAsync(EntryPointOperation entryPoint, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) + { + var sourceDirectory = new DirectoryInfo(SourceDirectoryPath); + if (sourceDirectory.Exists) + { + sourceDirectory.Delete(true); + } + + sourceDirectory.Create(); + logger.LogInfo($"Created source directory at {sourceDirectory.FullName}."); + + // Create driver. + var driverFileNameWithExtension = Path.ChangeExtension(DriverFileName, DriverFileExtension); + var driverFile = new FileInfo(Path.Combine(sourceDirectory.FullName, driverFileNameWithExtension)); + using (var driverFileStream = driverFile.OpenWrite()) + { + await driverGenerator.GenerateAsync(entryPoint, driverFileStream); + } + logger.LogInfo($"Created driver file at {driverFile.FullName}."); + + // Create bytecode file. + var bytecodeFile = new FileInfo(Path.Combine(sourceDirectory.FullName, BytecodeFileName)); + using (var bytecodeFileStream = bytecodeFile.OpenWrite()) + { + await bytecodeFileStream.WriteAsync(qirBytecode); + } + logger.LogInfo($"Created bytecode file at {bytecodeFile.FullName}."); + + await executableGenerator.GenerateExecutableAsync(ExecutableFile, sourceDirectory, libraryDirectory, includeDirectory, LinkLibraries); + } + + public async Task RunAsync(EntryPointOperation entryPoint, Stream output) + { + var stringArguments = driverGenerator.GetCommandLineArguments(entryPoint); + await runner.RunExecutableAsync(ExecutableFile, output, stringArguments); + } + + public abstract IList LinkLibraries { get; } + } +} diff --git a/src/Qir/Controller/Executable/QirExecutableGenerator.cs b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs similarity index 80% rename from src/Qir/Controller/Executable/QirExecutableGenerator.cs rename to src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs index 9445f300115..80eaf8a768a 100644 --- a/src/Qir/Controller/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs @@ -1,20 +1,16 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; -namespace Microsoft.Quantum.Qir.Executable +namespace Microsoft.Quantum.Qir.Tools.Executable { - public class QirExecutableGenerator : IQirExecutableGenerator + internal class QirExecutableGenerator : IQirExecutableGenerator { - private static readonly string[] LibrariesToLink = { - "Microsoft.Quantum.Qir.Runtime", - "Microsoft.Quantum.Qir.QSharp.Foundation", - "Microsoft.Quantum.Qir.QSharp.Core" - }; private readonly IClangClient clangClient; private readonly ILogger logger; @@ -24,7 +20,7 @@ public QirExecutableGenerator(IClangClient clangClient, ILogger logger) this.logger = logger; } - public async Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) + public async Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, IList linkLibraries) { // Wrap in a Task.Run because FileInfo methods are not asynchronous. await Task.Run(async () => @@ -42,7 +38,7 @@ await Task.Run(async () => } var inputFiles = sourceDirectory.GetFiles().Select(fileInfo => fileInfo.FullName).ToArray(); - await clangClient.CreateExecutableAsync(inputFiles, LibrariesToLink, libraryDirectory.FullName, includeDirectory.FullName, executableFile.FullName); + await clangClient.CreateExecutableAsync(inputFiles, linkLibraries.ToArray(), libraryDirectory.FullName, includeDirectory.FullName, executableFile.FullName); }); } diff --git a/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs new file mode 100644 index 00000000000..03362d370a6 --- /dev/null +++ b/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using Microsoft.Quantum.Qir.Tools.Driver; +using Microsoft.Quantum.Qir.Utility; + +namespace Microsoft.Quantum.Qir.Tools.Executable +{ + /// + /// Class to create and run QIR-based executables that use the full-state simulator. + /// + public class QirFullStateExecutable : QirExecutable + { + public QirFullStateExecutable(FileInfo executableFile, byte[] qirBytecode, ILogger logger = null) + : base(executableFile, + qirBytecode, + new QirFullStateDriverGenerator(), + logger) + { + } + + public override IList LinkLibraries => new List { + "Microsoft.Quantum.Qir.Runtime", + "Microsoft.Quantum.Qir.QSharp.Foundation", + "Microsoft.Quantum.Qir.QSharp.Core" + }; + + public override string DriverFileExtension => "cpp"; + } +} diff --git a/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs b/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs new file mode 100644 index 00000000000..987d6212799 --- /dev/null +++ b/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Utility; + +namespace Microsoft.Quantum.Qir.Tools.Executable +{ + internal class QuantumExecutableRunner : IQuantumExecutableRunner + { + private readonly ILogger logger; + + public QuantumExecutableRunner(ILogger logger) + { + this.logger = logger; + } + + public async Task RunExecutableAsync(FileInfo executableFile, Stream stream, string arguments) + { + logger.LogInfo($"Invoking executable {executableFile.FullName} with the following arguments: {arguments}"); + using var process = new Process(); + process.StartInfo = new ProcessStartInfo + { + FileName = executableFile.FullName, + Arguments = arguments, + RedirectStandardOutput = true, + }; + + process.EnableRaisingEvents = true; + process.Start(); + var output = await process.StandardOutput.ReadToEndAsync(); + process.WaitForExit(); + using var streamWriter = new StreamWriter(stream); + await streamWriter.WriteAsync(output); + logger.LogInfo($"Executable has finished running. Result code: {process.ExitCode}"); + } + } +} diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index 5ad95e9541e..06ca9571b79 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -11,7 +11,7 @@ - + - + diff --git a/src/Qir/Execution/Tools/QirExecutable.cs b/src/Qir/Execution/Tools/QirExecutable.cs deleted file mode 100644 index de641f4b174..00000000000 --- a/src/Qir/Execution/Tools/QirExecutable.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; - -namespace Microsoft.Quantum.Qir.Tools -{ - /// - /// Base for creating and running QIR-based executables. - /// - public abstract class QirExecutable - { - private readonly EntryPointOperation EntryPointOperation; - private readonly byte[] QirBytecode; - - /// - /// Constructor for the QirExecutable class. - /// - /// Object that provides data to specify which entry-point to use for building and running a QIR-based executable. - /// QIR bytecode used to build the executable. - public QirExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) - { - this.EntryPointOperation = entryPoint; - this.QirBytecode = qirBytecode; - } - - /// - /// Creates a QIR-based executable. - /// - /// Directory where the libraries to link to are located. - /// Directory where the headers needed for compilation are located. - /// File to write the executable to. - public Task BuildAsync(DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, FileInfo executable) - { - throw new NotImplementedException(); - } - - // TODO: How arguments are passed to this API will change. - public Task RunAsync(FileInfo executable, DirectoryInfo librariesDirectory, IList arguments) - { - throw new NotImplementedException(); - } - - // TODO: To be used by BuildAsync. - protected abstract Task GenerateDriverAsync(Stream driver); - - // TODO: To be used by RunAsync. - // TODO: How arguments are passed to this API will change. - protected abstract string GetCommandLineArguments(IList arguments); - - // TODO: To be used by BuildAsync. - protected abstract IList GetLinkLibraries(); - } -} diff --git a/src/Qir/Execution/Tools/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/QirFullStateExecutable.cs deleted file mode 100644 index 882572810bc..00000000000 --- a/src/Qir/Execution/Tools/QirFullStateExecutable.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; - -namespace Microsoft.Quantum.Qir.Tools -{ - /// - /// Class to create and run QIR-based executables that use the full-state simulator. - /// - public class QirFullStateExecutable : QirExecutable - { - /// - public QirFullStateExecutable(EntryPointOperation entryPoint, byte[] qirBytecode) : - base(entryPoint, qirBytecode) - { - } - - protected override Task GenerateDriverAsync(Stream driver) - { - throw new NotImplementedException(); - } - - // TODO: How arguments are passed to this API will change. - protected override string GetCommandLineArguments(IList arguments) - { - throw new NotImplementedException(); - } - - protected override IList GetLinkLibraries() - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Qir/Controller/Utility/Clock.cs b/src/Qir/Execution/Tools/Utility/Clock.cs similarity index 100% rename from src/Qir/Controller/Utility/Clock.cs rename to src/Qir/Execution/Tools/Utility/Clock.cs diff --git a/src/Qir/Controller/Utility/IClock.cs b/src/Qir/Execution/Tools/Utility/IClock.cs similarity index 100% rename from src/Qir/Controller/Utility/IClock.cs rename to src/Qir/Execution/Tools/Utility/IClock.cs diff --git a/src/Qir/Controller/Utility/ILogger.cs b/src/Qir/Execution/Tools/Utility/ILogger.cs similarity index 100% rename from src/Qir/Controller/Utility/ILogger.cs rename to src/Qir/Execution/Tools/Utility/ILogger.cs diff --git a/src/Qir/Controller/Utility/Logger.cs b/src/Qir/Execution/Tools/Utility/Logger.cs similarity index 100% rename from src/Qir/Controller/Utility/Logger.cs rename to src/Qir/Execution/Tools/Utility/Logger.cs From 3b3aff0245433d8bf4b4f2155a2d71bf31abb171 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 12:46:19 -0700 Subject: [PATCH 050/145] Add QirExe test project --- .gitignore | 3 +++ Simulation.sln | 19 +++++++++++++++ .../TestProjects/QirExe/Main.qs | 8 +++++++ .../TestProjects/QirExe/QirExe.csproj | 24 +++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs create mode 100644 src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj diff --git a/.gitignore b/.gitignore index 5b33b48524e..f9e97c26a30 100644 --- a/.gitignore +++ b/.gitignore @@ -336,6 +336,9 @@ ASALocalRun/ # MFractors (Xamarin productivity tool) working folder .mfractor/ + /src/Simulation/Simulators.Tests/TestProjects/QSharpExe/built +/src/Simulation/Simulators.Tests/TestProjects/QirExe/qir /src/Simulation/Simulators.Tests/TestProjects/TargetedExe/built + dbw_test diff --git a/Simulation.sln b/Simulation.sln index 9a65f34a9db..b56355e831b 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -113,6 +113,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandaloneInputReference", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qir-standalone-input-reference", "src\Qir\Samples\StandaloneInputReference\qsharp\qir-standalone-input-reference.csproj", "{D7D34736-A719-4B45-A33F-2723F59EC29D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QirExe", "src\Simulation\Simulators.Tests\TestProjects\QirExe\QirExe.csproj", "{A0B98D0E-FC28-4FD8-8806-4825B9F5489D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -749,6 +751,22 @@ Global {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|x64.ActiveCfg = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|x64.Build.0 = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|Any CPU.Build.0 = Release|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|x64.ActiveCfg = Release|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Release|x64.Build.0 = Release|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -802,6 +820,7 @@ Global {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {A7DB7367-9FD6-4164-8263-A05077BE54AB} = {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} {D7D34736-A719-4B45-A33F-2723F59EC29D} = {A7DB7367-9FD6-4164-8263-A05077BE54AB} + {A0B98D0E-FC28-4FD8-8806-4825B9F5489D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs b/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs new file mode 100644 index 00000000000..682a9b131dc --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs @@ -0,0 +1,8 @@ +namespace QirExe { + open Microsoft.Quantum.Intrinsic; + + @EntryPoint() + operation Main() : Unit { + Message("Hello, world!"); + } +} diff --git a/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj new file mode 100644 index 00000000000..f507980d701 --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj @@ -0,0 +1,24 @@ + + + Exe + netcoreapp3.1 + + + + false + true + false + + + + + + + + + + + + + + From ea9e214c8d65a7231d3d39f9dda8db5fb1c627ef Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 14:36:16 -0700 Subject: [PATCH 051/145] Pass QIR resource name to Azure.Submit --- src/Simulation/CSharpGeneration/EntryPoint.fs | 5 +- .../Microsoft.Quantum.CSharpGeneration.fsproj | 2 +- src/Simulation/EntryPointDriver/Azure.cs | 48 +++++++++++-------- src/Simulation/EntryPointDriver/Driver.cs | 9 ++-- .../EntryPointDriver/DriverSettings.cs | 18 +++---- 5 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 03349ea29e8..eba3a6d4319 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -106,12 +106,15 @@ let private submitMethod context entryPoint = let callableName, _, _ = callableTypeNames context entryPoint let parseResultParamName = "parseResult" let settingsParamName = "settings" + let args = [ + ident settingsParamName :> ExpressionSyntax + literal DotnetCoreDll.QirResourceName ident callableName <|.|> ident "Info" ident "this" <.> (ident "CreateArgument", [ident parseResultParamName]) - ident settingsParamName :> ExpressionSyntax ] + arrow_method "System.Threading.Tasks.Task" "Submit" ``<<`` [] ``>>`` ``(`` [ diff --git a/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj b/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj index 7c473347ac0..73277d29a19 100644 --- a/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj +++ b/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj @@ -22,7 +22,7 @@ - + diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 9f33f7baec5..d9e0fcd4528 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -1,18 +1,20 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Azure.Quantum; using Microsoft.Azure.Quantum.Exceptions; +using Microsoft.Azure.Quantum; +using static Microsoft.Quantum.EntryPointDriver.Driver; using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Common.Exceptions; using Microsoft.Quantum.Simulation.Core; -using static Microsoft.Quantum.EntryPointDriver.Driver; +using System.Linq; +using System.Threading.Tasks; +using System; namespace Microsoft.Quantum.EntryPointDriver { + using Environment = System.Environment; + /// /// Provides entry point submission to Azure Quantum. /// @@ -23,29 +25,33 @@ public static class Azure /// /// The entry point's argument type. /// The entry point's return type. + /// The submission settings. + /// The name of the QIR bitcode assembly resource. /// The information about the entry point. /// The input argument tuple to the entry point. - /// The submission settings. /// The exit code. - public static async Task Submit(EntryPointInfo info, TIn input, AzureSettings settings) + public static async Task Submit( + AzureSettings settings, string qirResourceName, EntryPointInfo info, TIn input) { + // TODO + Console.WriteLine($"qirResourceName: {qirResourceName}"); + if (settings.Verbose) { - Console.WriteLine(settings); - Console.WriteLine(); + Console.Write(settings + Environment.NewLine + Environment.NewLine); } - var machine = CreateMachine(settings); - if (machine is null) + switch (CreateMachine(settings)) { - DisplayWithColor(ConsoleColor.Red, Console.Error, - $"The target '{settings.Target}' was not recognized."); - return 1; + case null: + DisplayWithColor( + ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' was not recognized."); + return 1; + case var machine: + return settings.DryRun + ? Validate(machine, info, input) + : await SubmitJob(settings, machine, info, input); } - - return settings.DryRun - ? Validate(machine, info, input) - : await SubmitJob(machine, info, input, settings); } /// @@ -53,13 +59,13 @@ public static async Task Submit(EntryPointInfo info, /// /// The input type. /// The output type. + /// The submission settings. /// The quantum machine target. /// The information about the entry point. /// The input argument tuple to the entry point. - /// The submission settings. /// The exit code. private static async Task SubmitJob( - IQuantumMachine machine, EntryPointInfo info, TIn input, AzureSettings settings) + AzureSettings settings, IQuantumMachine machine, EntryPointInfo info, TIn input) { try { diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 7997a87db01..374b6a6d8f3 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -468,7 +468,7 @@ private Task Submit(ParseResult parseResult, AzureSettings azureSettings, I DryRun = DefaultIfShadowed(entryPoint, DryRunOption, azureSettings.DryRun), Verbose = DefaultIfShadowed(entryPoint, VerboseOption, azureSettings.Verbose) }); - + /// /// A modification of the command-line class. /// @@ -493,10 +493,11 @@ protected override string ArgumentDescriptor(IArgument argument) /// /// Struct for housing a command with its validators. /// - private struct CommandWithValidators + private readonly struct CommandWithValidators { - public Command Command; - public Validators Validators; + public Command Command { get; } + + public Validators Validators { get; } /// /// Basic constructor. diff --git a/src/Simulation/EntryPointDriver/DriverSettings.cs b/src/Simulation/EntryPointDriver/DriverSettings.cs index cd2402b12d8..f3f86302800 100644 --- a/src/Simulation/EntryPointDriver/DriverSettings.cs +++ b/src/Simulation/EntryPointDriver/DriverSettings.cs @@ -12,7 +12,7 @@ public sealed class DriverSettings /// /// The aliases for the simulator command-line option. /// - internal IImmutableList SimulatorOptionAliases { get; } + internal ImmutableList SimulatorOptionAliases { get; } /// /// The name of the quantum simulator. @@ -40,13 +40,10 @@ public sealed class DriverSettings internal string DefaultExecutionTarget { get; } /// - /// Creates an instance of the default simulator if it is a custom simulator. + /// A function that returns a new instance of the default custom simulator, or throws + /// if the default simulator is not a custom simulator. /// - /// An instance of the default custom simulator. - /// - /// Thrown if the default simulator is not a custom simulator. - /// - internal Func CreateDefaultCustomSimulator; + internal Func CreateDefaultCustomSimulator { get; } /// /// Creates a new driver settings instance. @@ -57,9 +54,12 @@ public sealed class DriverSettings /// The name of the resources estimator. /// The name of the default simulator to use. /// The name of the default execution target to use. - /// The function for creating a new instance of the default simulator if it is a custom simulator. + /// + /// A function that returns a new instance of the default custom simulator, or throws + /// if the default simulator is not a custom simulator. + /// public DriverSettings( - IImmutableList simulatorOptionAliases, + ImmutableList simulatorOptionAliases, string quantumSimulatorName, string toffoliSimulatorName, string resourcesEstimatorName, From bba492b9783c4c09bb9b01648680277511267ede Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 15:09:26 -0700 Subject: [PATCH 052/145] Pass QIR resource stream to Azure.Submit --- src/Simulation/CSharpGeneration/EntryPoint.fs | 7 ++++++- src/Simulation/EntryPointDriver/Azure.cs | 10 ++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index eba3a6d4319..0894fb52031 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -107,10 +107,15 @@ let private submitMethod context entryPoint = let parseResultParamName = "parseResult" let settingsParamName = "settings" + let qirResourceStream = + ident "global::System.Reflection.Assembly" + <.> (ident "GetExecutingAssembly", []) + <.> (ident "GetManifestResourceStream", [literal DotnetCoreDll.QirResourceName]) + let args = [ ident settingsParamName :> ExpressionSyntax - literal DotnetCoreDll.QirResourceName + qirResourceStream ident callableName <|.|> ident "Info" ident "this" <.> (ident "CreateArgument", [ident parseResultParamName]) ] diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index d9e0fcd4528..96acc13929d 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -7,9 +7,10 @@ using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Common.Exceptions; using Microsoft.Quantum.Simulation.Core; +using System; +using System.IO; using System.Linq; using System.Threading.Tasks; -using System; namespace Microsoft.Quantum.EntryPointDriver { @@ -26,16 +27,13 @@ public static class Azure /// The entry point's argument type. /// The entry point's return type. /// The submission settings. - /// The name of the QIR bitcode assembly resource. + /// The QIR bitcode stream. /// The information about the entry point. /// The input argument tuple to the entry point. /// The exit code. public static async Task Submit( - AzureSettings settings, string qirResourceName, EntryPointInfo info, TIn input) + AzureSettings settings, Stream? qir, EntryPointInfo info, TIn input) { - // TODO - Console.WriteLine($"qirResourceName: {qirResourceName}"); - if (settings.Verbose) { Console.Write(settings + Environment.NewLine + Environment.NewLine); From 66c4dbe56c194e1b5f5ab62ed90e9ce40f979203 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 15:45:40 -0700 Subject: [PATCH 053/145] Add IQirSubmitter mock --- .../EntryPointDriver.Tests/Program.fs | 4 - ....Microsoft.Quantum.EntryPointDriver.fsproj | 4 - .../EntryPointDriver.Tests/Tests.fs | 62 +++--- src/Simulation/EntryPointDriver/Azure.cs | 5 +- .../Mocks/ErrorQuantumMachine.cs | 86 ++++++++ .../EntryPointDriver/Mocks/ExampleJob.cs | 30 +++ .../Mocks/NoOpQirSubmitter.cs | 26 +++ .../Mocks/NoOpQuantumMachine.cs | 86 ++++++++ .../EntryPointDriver/TestMachines.cs | 196 ------------------ 9 files changed, 262 insertions(+), 237 deletions(-) delete mode 100644 src/Simulation/EntryPointDriver.Tests/Program.fs create mode 100644 src/Simulation/EntryPointDriver/Mocks/ErrorQuantumMachine.cs create mode 100644 src/Simulation/EntryPointDriver/Mocks/ExampleJob.cs create mode 100644 src/Simulation/EntryPointDriver/Mocks/NoOpQirSubmitter.cs create mode 100644 src/Simulation/EntryPointDriver/Mocks/NoOpQuantumMachine.cs delete mode 100644 src/Simulation/EntryPointDriver/TestMachines.cs diff --git a/src/Simulation/EntryPointDriver.Tests/Program.fs b/src/Simulation/EntryPointDriver.Tests/Program.fs deleted file mode 100644 index 58e40047174..00000000000 --- a/src/Simulation/EntryPointDriver.Tests/Program.fs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -module Program = let [] main _ = 0 diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj index e78068c09ba..fceae9c9b05 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj +++ b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj @@ -1,9 +1,7 @@ - netcoreapp3.1 false - false Microsoft.Quantum.EntryPointDriver.Tests x64 @@ -19,7 +17,6 @@ PreserveNewest - @@ -34,5 +31,4 @@ - diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index 9ca3ad61330..43871481a96 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -201,8 +201,8 @@ let private submitWithoutTarget = "--workspace" "myWorkspace" ] -/// Standard command-line arguments for the "submit" command using the "test.nothing" target. -let private submitWithNothingTarget = submitWithoutTarget @ ["--target"; "test.nothing"] +/// Standard command-line arguments for the "submit" command using the "test.noop" target. +let private submitWithNoOpTarget = submitWithoutTarget @ ["--target"; "test.noop"] /// Standard command-line arguments for the "submit" command using the "test.error" target. let private submitWithErrorTarget = submitWithoutTarget @ ["--target"; "test.error"] @@ -471,14 +471,14 @@ let ``Shadows --version`` () = let ``Shadows --target`` () = let given = test "Shadows --target" given ["--target"; "foo"] |> yields "foo" - given submitWithNothingTarget + given submitWithNoOpTarget |> failsWith "The required option --target conflicts with an entry point parameter name." [] let ``Shadows --shots`` () = let given = test "Shadows --shots" given ["--shots"; "7"] |> yields "7" - given (submitWithNothingTarget @ ["--shots"; "7"]) + given (submitWithNoOpTarget @ ["--shots"; "7"]) |> yields "Warning: Option --shots is overridden by an entry point parameter name. Using default value 500. https://www.example.com/00000000-0000-0000-0000-0000000000000" @@ -545,22 +545,22 @@ let ``Supports default custom simulator`` () = [] let ``Submit can submit a job`` () = let given = test "Returns Unit" - given submitWithNothingTarget + given submitWithNoOpTarget |> yields "https://www.example.com/00000000-0000-0000-0000-0000000000000" [] let ``Submit can show only the ID`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ ["--output"; "id"]) |> yields "00000000-0000-0000-0000-0000000000000" + given (submitWithNoOpTarget @ ["--output"; "id"]) |> yields "00000000-0000-0000-0000-0000000000000" [] let ``Submit uses default values`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ ["--verbose"]) + given (submitWithNoOpTarget @ ["--verbose"]) |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.nothing + Target: test.noop Storage: AAD Token: Base URI: @@ -575,12 +575,12 @@ let ``Submit uses default values`` () = [] let ``Submit uses default values with default target`` () = - let given = testWithTarget "test.nothing" "Returns Unit" + let given = testWithTarget "test.noop" "Returns Unit" given (submitWithoutTarget @ ["--verbose"]) |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.nothing + Target: test.noop Storage: AAD Token: Base URI: @@ -596,7 +596,7 @@ let ``Submit uses default values with default target`` () = [] let ``Submit allows overriding default values`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ [ + given (submitWithNoOpTarget @ [ "--verbose" "--storage" "myStorage" @@ -612,7 +612,7 @@ let ``Submit allows overriding default values`` () = |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.nothing + Target: test.noop Storage: myStorage AAD Token: myToken Base URI: myBaseUri @@ -628,7 +628,7 @@ let ``Submit allows overriding default values`` () = [] let ``Submit allows overriding default values with default target`` () = let given = testWithTarget "foo.target" "Returns Unit" - given (submitWithNothingTarget @ [ + given (submitWithNoOpTarget @ [ "--verbose" "--storage" "myStorage" @@ -644,7 +644,7 @@ let ``Submit allows overriding default values with default target`` () = |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.nothing + Target: test.noop Storage: myStorage AAD Token: myToken Base URI: myBaseUri @@ -660,7 +660,7 @@ let ``Submit allows overriding default values with default target`` () = [] let ``Submit does not allow to include mutually exclusive options`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ [ + given (submitWithNoOpTarget @ [ "--base-uri" "myBaseUri" "--location" @@ -671,7 +671,7 @@ let ``Submit does not allow to include mutually exclusive options`` () = [] let ``Submit allows to include --base-uri option when --location is not present`` () = let given = testWithTarget "foo.target" "Returns Unit" - given (submitWithNothingTarget @ [ + given (submitWithNoOpTarget @ [ "--verbose" "--base-uri" "myBaseUri" @@ -679,7 +679,7 @@ let ``Submit allows to include --base-uri option when --location is not present` |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.nothing + Target: test.noop Storage: AAD Token: Base URI: myBaseUri @@ -695,7 +695,7 @@ let ``Submit allows to include --base-uri option when --location is not present` [] let ``Submit allows to include --location option when --base-uri is not present`` () = let given = testWithTarget "foo.target" "Returns Unit" - given (submitWithNothingTarget @ [ + given (submitWithNoOpTarget @ [ "--verbose" "--location" "myLocation" @@ -703,7 +703,7 @@ let ``Submit allows to include --location option when --base-uri is not present` |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.nothing + Target: test.noop Storage: AAD Token: Base URI: @@ -719,7 +719,7 @@ let ``Submit allows to include --location option when --base-uri is not present` [] let ``Submit allows spaces for the --location option`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ [ + given (submitWithNoOpTarget @ [ "--verbose" "--location" "My Location" @@ -727,7 +727,7 @@ let ``Submit allows spaces for the --location option`` () = |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.nothing + Target: test.noop Storage: AAD Token: Base URI: @@ -743,7 +743,7 @@ let ``Submit allows spaces for the --location option`` () = [] let ``Submit does not allow an invalid value for the --location option`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ [ + given (submitWithNoOpTarget @ [ "--location" "my!nv@lidLocation" ]) @@ -752,10 +752,10 @@ let ``Submit does not allow an invalid value for the --location option`` () = [] let ``Submit requires a positive number of shots`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ ["--shots"; "1"]) + given (submitWithNoOpTarget @ ["--shots"; "1"]) |> yields "https://www.example.com/00000000-0000-0000-0000-0000000000000" - given (submitWithNothingTarget @ ["--shots"; "0"]) |> fails - given (submitWithNothingTarget @ ["--shots"; "-1"]) |> fails + given (submitWithNoOpTarget @ ["--shots"; "0"]) |> fails + given (submitWithNoOpTarget @ ["--shots"; "-1"]) |> fails [] let ``Submit fails with unknown target`` () = @@ -765,7 +765,7 @@ let ``Submit fails with unknown target`` () = [] let ``Submit supports dry run option`` () = let given = test "Returns Unit" - given (submitWithNothingTarget @ ["--dry-run"]) |> yields "✔️ The program is valid!" + given (submitWithNoOpTarget @ ["--dry-run"]) |> yields "✔️ The program is valid!" given (submitWithErrorTarget @ ["--dry-run"]) |> failsWith "❌ The program is invalid. @@ -783,8 +783,8 @@ let ``Submit has required options`` () = // Try every possible combination of arguments. The command should succeed only when all of the arguments are // included. - let commandName = List.head submitWithNothingTarget - let allArgs = submitWithNothingTarget |> List.tail |> List.chunkBySize 2 + let commandName = List.head submitWithNoOpTarget + let allArgs = submitWithNoOpTarget |> List.tail |> List.chunkBySize 2 for args in powerSet allArgs do given (commandName :: List.concat args) |> if List.length args = List.length allArgs @@ -931,7 +931,7 @@ let ``Supports submitting multiple entry points`` () = "--workspace" "myWorkspace" "--target" - "test.nothing" + "test.noop" ] let given = test "Multiple entry points" let succeeds = yields "https://www.example.com/00000000-0000-0000-0000-0000000000000" @@ -952,7 +952,7 @@ let ``Supports submitting multiple entry points with different parameters`` () = "--workspace" "myWorkspace" "--target" - "test.nothing" + "test.noop" ] let entryPoint1Args = ["-n"; "42.5"] let entryPoint2Args = ["-s"; "Hello, World!"] @@ -975,5 +975,5 @@ let ``Supports submitting multiple entry points with different parameters`` () = given (["submit"; "EntryPointTest3.MultipleEntryPoints3"] @ entryPoint3Args @ options) |> succeeds given (["submit"; "EntryPointTest3.MultipleEntryPoints3"] @ options) |> fails - given submitWithNothingTarget |> fails + given submitWithNoOpTarget |> fails given [] |> fails diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 96acc13929d..5c62653a608 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -4,6 +4,7 @@ using Microsoft.Azure.Quantum.Exceptions; using Microsoft.Azure.Quantum; using static Microsoft.Quantum.EntryPointDriver.Driver; +using Microsoft.Quantum.EntryPointDriver.Mocks; using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Common.Exceptions; using Microsoft.Quantum.Simulation.Core; @@ -169,8 +170,8 @@ private static void DisplayError(string summary, string message) private static IQuantumMachine? CreateMachine(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null."), - NothingMachine.TargetId => new NothingMachine(), - ErrorMachine.TargetId => new ErrorMachine(), + NoOpQuantumMachine.TargetId => new NoOpQuantumMachine(), + ErrorQuantumMachine.TargetId => new ErrorQuantumMachine(), _ => QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage) }; diff --git a/src/Simulation/EntryPointDriver/Mocks/ErrorQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mocks/ErrorQuantumMachine.cs new file mode 100644 index 00000000000..90a0a8523c0 --- /dev/null +++ b/src/Simulation/EntryPointDriver/Mocks/ErrorQuantumMachine.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Azure.Quantum.Exceptions; +using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Simulation.Core; +using System; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.EntryPointDriver.Mocks +{ + /// + /// A quantum machine that always has an error. + /// + internal class ErrorQuantumMachine : IQuantumMachine + { + /// + /// The target ID for the error quantum machine. + /// + internal const string TargetId = "test.error"; + + public string ProviderId => nameof(ErrorQuantumMachine); + + public string Target => TargetId; + + public Task> ExecuteAsync( + EntryPointInfo info, TInput input) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, TInput input, IQuantumMachineSubmissionContext submissionContext) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, TInput input, IQuantumMachineExecutionContext executionContext) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineExecutionContext executionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachineExecutionContext executionContext) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachineExecutionContext executionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + throw new NotSupportedException(); + + public Task SubmitAsync( + EntryPointInfo info, TInput input) => + throw new AzureQuantumException("This quantum machine always has an error."); + + public Task SubmitAsync( + EntryPointInfo info, TInput input, IQuantumMachineSubmissionContext submissionContext) => + SubmitAsync(info, input); + + public Task SubmitAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + SubmitAsync(info, input); + + public (bool IsValid, string Message) Validate( + EntryPointInfo info, TInput input) => + (false, "This quantum machine always has an error."); + } +} diff --git a/src/Simulation/EntryPointDriver/Mocks/ExampleJob.cs b/src/Simulation/EntryPointDriver/Mocks/ExampleJob.cs new file mode 100644 index 00000000000..1cc396e9dd0 --- /dev/null +++ b/src/Simulation/EntryPointDriver/Mocks/ExampleJob.cs @@ -0,0 +1,30 @@ +using Microsoft.Quantum.Runtime; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.EntryPointDriver.Mocks +{ + /// + /// A quantum machine job with default properties to use as an example. + /// + internal class ExampleJob : IQuantumMachineJob + { + public string Id => "00000000-0000-0000-0000-0000000000000"; + + public string Status => "NotImplemented"; + + public bool InProgress => false; + + public bool Succeeded => false; + + public bool Failed => true; + + public Uri Uri => new Uri($"https://www.example.com/{Id}"); + + public Task CancelAsync(CancellationToken cancellationToken = default) => throw new NotSupportedException(); + + public Task RefreshAsync(CancellationToken cancellationToken = default) => + throw new NotSupportedException(); + } +} diff --git a/src/Simulation/EntryPointDriver/Mocks/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mocks/NoOpQirSubmitter.cs new file mode 100644 index 00000000000..6ee624930d9 --- /dev/null +++ b/src/Simulation/EntryPointDriver/Mocks/NoOpQirSubmitter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Quantum.Runtime; + +namespace Microsoft.Quantum.EntryPointDriver.Mocks +{ + /// + /// A QIR submitter that does nothing. + /// + internal class NoOpQirSubmitter : IQirSubmitter + { + /// + /// The target ID for the no-op QIR submitter. + /// + internal const string TargetId = "test.qir.noop"; + + public string ProviderId => nameof(NoOpQirSubmitter); + + public string Target => TargetId; + + public Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments) => + Task.FromResult(new ExampleJob()); + } +} diff --git a/src/Simulation/EntryPointDriver/Mocks/NoOpQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mocks/NoOpQuantumMachine.cs new file mode 100644 index 00000000000..590548b96ed --- /dev/null +++ b/src/Simulation/EntryPointDriver/Mocks/NoOpQuantumMachine.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Simulation.Core; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.EntryPointDriver.Mocks +{ + /// + /// A quantum machine that does nothing. + /// + internal class NoOpQuantumMachine : IQuantumMachine + { + /// + /// The target ID for the no-op quantum machine. + /// + internal const string TargetId = "test.noop"; + + public string ProviderId => nameof(NoOpQuantumMachine); + + public string Target => TargetId; + + public Task> ExecuteAsync( + EntryPointInfo info, TInput input) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, TInput input, IQuantumMachineSubmissionContext submissionContext) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, TInput input, IQuantumMachineExecutionContext executionContext) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineExecutionContext executionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachineExecutionContext executionContext) => + throw new NotSupportedException(); + + public Task> ExecuteAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachineExecutionContext executionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + throw new NotSupportedException(); + + public Task SubmitAsync( + EntryPointInfo info, TInput input) => + Task.FromResult(new ExampleJob()); + + public Task SubmitAsync( + EntryPointInfo info, TInput input, IQuantumMachineSubmissionContext submissionContext) => + SubmitAsync(info, input); + + public Task SubmitAsync( + EntryPointInfo info, + TInput input, + IQuantumMachineSubmissionContext submissionContext, + IQuantumMachine.ConfigureJob configureJobCallback) => + SubmitAsync(info, input); + + public (bool IsValid, string Message) Validate( + EntryPointInfo info, TInput input) => + (true, string.Empty); + } +} diff --git a/src/Simulation/EntryPointDriver/TestMachines.cs b/src/Simulation/EntryPointDriver/TestMachines.cs deleted file mode 100644 index 32465534dc8..00000000000 --- a/src/Simulation/EntryPointDriver/TestMachines.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Azure.Quantum.Exceptions; -using Microsoft.Quantum.Runtime; -using Microsoft.Quantum.Simulation.Core; - -namespace Microsoft.Quantum.EntryPointDriver -{ - /// - /// A quantum machine that does nothing. - /// - internal class NothingMachine : IQuantumMachine - { - /// - /// The target ID for the nothing machine. - /// - internal const string TargetId = "test.nothing"; - - public string ProviderId { get; } = nameof(NothingMachine); - - public string Target { get; } = TargetId; - - public Task> ExecuteAsync( - EntryPointInfo info, TInput input) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineExecutionContext executionContext) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineExecutionContext executionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachineExecutionContext executionContext) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachineExecutionContext executionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - throw new NotSupportedException(); - - public Task SubmitAsync( - EntryPointInfo info, TInput input) => - Task.FromResult(new DefaultJob()); - - public Task SubmitAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext) => - SubmitAsync(info, input); - - public Task SubmitAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - SubmitAsync(info, input); - - public (bool IsValid, string Message) Validate( - EntryPointInfo info, TInput input) => (true, string.Empty); - - /// - /// A quantum machine job with default properties. - /// - private class DefaultJob : IQuantumMachineJob - { - public string Id { get; } = "00000000-0000-0000-0000-0000000000000"; - - public string Status { get; } = "NotImplemented"; - - public bool InProgress { get; } = false; - - public bool Succeeded { get; } = false; - - public bool Failed { get; } = true; - - public Uri Uri => new Uri($"https://www.example.com/{Id}"); - - public Task CancelAsync(CancellationToken cancellationToken = default) => throw new NotSupportedException(); - - public Task RefreshAsync(CancellationToken cancellationToken = default) => - throw new NotSupportedException(); - } - } - - /// - /// A quantum machine that always has an error. - /// - internal class ErrorMachine : IQuantumMachine - { - /// - /// The target ID for the error machine. - /// - internal const string TargetId = "test.error"; - - public string ProviderId { get; } = nameof(ErrorMachine); - - public string Target { get; } = TargetId; - - public Task> ExecuteAsync( - EntryPointInfo info, TInput input) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineExecutionContext executionContext) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineExecutionContext executionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachineExecutionContext executionContext) => - throw new NotSupportedException(); - - public Task> ExecuteAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachineExecutionContext executionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - throw new NotSupportedException(); - - public Task SubmitAsync( - EntryPointInfo info, TInput input) => - throw new AzureQuantumException("This quantum machine always has an error."); - - public Task SubmitAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext) => - SubmitAsync(info, input); - - public Task SubmitAsync( - EntryPointInfo info, - TInput input, - IQuantumMachineSubmissionContext submissionContext, - IQuantumMachine.ConfigureJob configureJobCallback) => - SubmitAsync(info, input); - - public (bool IsValid, string Message) Validate( - EntryPointInfo info, TInput input) => - (false, "This quantum machine always has an error."); - } -} From d0bad64a3fcb4709df23e205b5f42603cde7aa85 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 15:50:41 -0700 Subject: [PATCH 054/145] Rename namespace --- src/Simulation/EntryPointDriver/Azure.cs | 2 +- .../{Mocks => Mock}/ErrorQuantumMachine.cs | 2 +- .../EntryPointDriver/{Mocks => Mock}/ExampleJob.cs | 7 +++++-- .../EntryPointDriver/{Mocks => Mock}/NoOpQirSubmitter.cs | 6 ++++-- .../EntryPointDriver/{Mocks => Mock}/NoOpQuantumMachine.cs | 3 +-- 5 files changed, 12 insertions(+), 8 deletions(-) rename src/Simulation/EntryPointDriver/{Mocks => Mock}/ErrorQuantumMachine.cs (98%) rename src/Simulation/EntryPointDriver/{Mocks => Mock}/ExampleJob.cs (83%) rename src/Simulation/EntryPointDriver/{Mocks => Mock}/NoOpQirSubmitter.cs (84%) rename src/Simulation/EntryPointDriver/{Mocks => Mock}/NoOpQuantumMachine.cs (97%) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 5c62653a608..aefc3fb9f84 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -4,7 +4,7 @@ using Microsoft.Azure.Quantum.Exceptions; using Microsoft.Azure.Quantum; using static Microsoft.Quantum.EntryPointDriver.Driver; -using Microsoft.Quantum.EntryPointDriver.Mocks; +using Microsoft.Quantum.EntryPointDriver.Mock; using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Common.Exceptions; using Microsoft.Quantum.Simulation.Core; diff --git a/src/Simulation/EntryPointDriver/Mocks/ErrorQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs similarity index 98% rename from src/Simulation/EntryPointDriver/Mocks/ErrorQuantumMachine.cs rename to src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs index 90a0a8523c0..33147da0895 100644 --- a/src/Simulation/EntryPointDriver/Mocks/ErrorQuantumMachine.cs +++ b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs @@ -7,7 +7,7 @@ using System; using System.Threading.Tasks; -namespace Microsoft.Quantum.EntryPointDriver.Mocks +namespace Microsoft.Quantum.EntryPointDriver.Mock { /// /// A quantum machine that always has an error. diff --git a/src/Simulation/EntryPointDriver/Mocks/ExampleJob.cs b/src/Simulation/EntryPointDriver/Mock/ExampleJob.cs similarity index 83% rename from src/Simulation/EntryPointDriver/Mocks/ExampleJob.cs rename to src/Simulation/EntryPointDriver/Mock/ExampleJob.cs index 1cc396e9dd0..ec5ac784977 100644 --- a/src/Simulation/EntryPointDriver/Mocks/ExampleJob.cs +++ b/src/Simulation/EntryPointDriver/Mock/ExampleJob.cs @@ -1,9 +1,12 @@ -using Microsoft.Quantum.Runtime; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Quantum.Runtime; using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.Quantum.EntryPointDriver.Mocks +namespace Microsoft.Quantum.EntryPointDriver.Mock { /// /// A quantum machine job with default properties to use as an example. diff --git a/src/Simulation/EntryPointDriver/Mocks/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs similarity index 84% rename from src/Simulation/EntryPointDriver/Mocks/NoOpQirSubmitter.cs rename to src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs index 6ee624930d9..0e622bd68b6 100644 --- a/src/Simulation/EntryPointDriver/Mocks/NoOpQirSubmitter.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs @@ -1,10 +1,12 @@ -using System; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Runtime; -namespace Microsoft.Quantum.EntryPointDriver.Mocks +namespace Microsoft.Quantum.EntryPointDriver.Mock { /// /// A QIR submitter that does nothing. diff --git a/src/Simulation/EntryPointDriver/Mocks/NoOpQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs similarity index 97% rename from src/Simulation/EntryPointDriver/Mocks/NoOpQuantumMachine.cs rename to src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs index 590548b96ed..db860ba46f3 100644 --- a/src/Simulation/EntryPointDriver/Mocks/NoOpQuantumMachine.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs @@ -4,10 +4,9 @@ using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Core; using System; -using System.Threading; using System.Threading.Tasks; -namespace Microsoft.Quantum.EntryPointDriver.Mocks +namespace Microsoft.Quantum.EntryPointDriver.Mock { /// /// A quantum machine that does nothing. From 62c83f1ecb2abaab1d61ad9a0f028dfcc957d629 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 15:54:01 -0700 Subject: [PATCH 055/145] Update QIR submitter target ID --- src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs index 0e622bd68b6..2d486e9ed13 100644 --- a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs @@ -16,7 +16,7 @@ internal class NoOpQirSubmitter : IQirSubmitter /// /// The target ID for the no-op QIR submitter. /// - internal const string TargetId = "test.qir.noop"; + internal const string TargetId = "test.noop"; public string ProviderId => nameof(NoOpQirSubmitter); From 3dbfe5dc91a50fbd9ce3b172efe4d1270310567e Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 16:24:44 -0700 Subject: [PATCH 056/145] Update compiler packages --- global.json | 2 +- .../CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index 758d19df817..bdae43d0162 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Quantum.Sdk": "0.15.210425903-alpha" + "Microsoft.Quantum.Sdk": "0.16.210426173-alpha" } } diff --git a/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj b/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj index 73277d29a19..88472e7499c 100644 --- a/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj +++ b/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj @@ -22,7 +22,7 @@ - + From 755169ef0900c42821c7b1fc138ed64dad91160b Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 16:41:06 -0700 Subject: [PATCH 057/145] Add arguments to QirExe entry point --- src/Simulation/CSharpGeneration/EntryPoint.fs | 5 ++++- src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 0894fb52031..ff422dc5fba 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -75,17 +75,20 @@ let private customSimulatorFactory name = let private createArgument context entryPoint = let inTypeName = SimulationCode.roslynTypeName context entryPoint.Signature.ArgumentType let parseResultName = "parseResult" + let valueForArg (name, typeName) = ident parseResultName <.> (sprintf "ValueForOption<%s>" typeName |> ident, [optionName name]) + let argTuple = SimulationCode.mapArgumentTuple valueForArg context entryPoint.ArgumentTuple entryPoint.Signature.ArgumentType + arrow_method inTypeName "CreateArgument" ``<<`` [] ``>>`` ``(`` [param parseResultName ``of`` (``type`` "System.CommandLine.Parsing.ParseResult")] ``)`` - [``public``] + [``private``] (Some (``=>`` argTuple)) /// A tuple of the callable's name, argument type name, and return type name. diff --git a/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs b/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs index 682a9b131dc..6c7e71aa26a 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs +++ b/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs @@ -2,7 +2,8 @@ open Microsoft.Quantum.Intrinsic; @EntryPoint() - operation Main() : Unit { + operation Main(x : Int, (y : Int, z : Int)) : Unit { Message("Hello, world!"); + Message($"({x}, ({y}, {z}))"); } } From 60ed5983b8207b69d5a4d6c755508122319fcf6e Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 26 Apr 2021 17:44:39 -0700 Subject: [PATCH 058/145] Add separate submit method for QIR --- src/Simulation/CSharpGeneration/EntryPoint.fs | 23 +++++-- src/Simulation/EntryPointDriver/Azure.cs | 64 ++++++++++++------- 2 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index ff422dc5fba..6c06fcf342e 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -110,19 +110,30 @@ let private submitMethod context entryPoint = let parseResultParamName = "parseResult" let settingsParamName = "settings" - let qirResourceStream = + let qsArgs = + [ + ident settingsParamName :> ExpressionSyntax + ident callableName <|.|> ident "Info" + ident "this" <.> (ident "CreateArgument", [ident parseResultParamName]) + ] + + let qirStream = ident "global::System.Reflection.Assembly" <.> (ident "GetExecutingAssembly", []) <.> (ident "GetManifestResourceStream", [literal DotnetCoreDll.QirResourceName]) - let args = + let qirArgs = [ ident settingsParamName :> ExpressionSyntax - qirResourceStream - ident callableName <|.|> ident "Info" - ident "this" <.> (ident "CreateArgument", [ident parseResultParamName]) + qirStream + string entryPoint.FullName |> literal + // TODO + upcast ident "global::System.Collections.Immutable.ImmutableList.Empty" ] + let hasQir = context.assemblyConstants.ContainsKey "QirOutputPath" + let submit = if hasQir then ident "SubmitQir", qirArgs else ident "SubmitQSharp", qsArgs + arrow_method "System.Threading.Tasks.Task" "Submit" ``<<`` [] ``>>`` ``(`` [ @@ -131,7 +142,7 @@ let private submitMethod context entryPoint = ] ``)`` [``public``] - (Some (``=>`` (ident (driverNamespace + ".Azure") <.> (ident "Submit", args)))) + (Some (``=>`` (ident (driverNamespace + ".Azure") <.> submit))) /// Generates the Simulate method for an entry point class. let private simulateMethod context entryPoint = diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index aefc3fb9f84..d2815e9f27c 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -9,6 +9,7 @@ using Microsoft.Quantum.Simulation.Common.Exceptions; using Microsoft.Quantum.Simulation.Core; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -23,17 +24,16 @@ namespace Microsoft.Quantum.EntryPointDriver public static class Azure { /// - /// Submits the entry point to Azure Quantum. + /// Submits a Q# entry point to Azure Quantum. /// /// The entry point's argument type. /// The entry point's return type. - /// The submission settings. - /// The QIR bitcode stream. + /// The Azure submission settings. /// The information about the entry point. /// The input argument tuple to the entry point. /// The exit code. - public static async Task Submit( - AzureSettings settings, Stream? qir, EntryPointInfo info, TIn input) + public static async Task SubmitQSharp( + AzureSettings settings, EntryPointInfo info, TIn input) { if (settings.Verbose) { @@ -53,6 +53,24 @@ public static async Task Submit( } } + /// + /// Submits a QIR entry point to Azure Quantum. + /// + /// The Azure submission settings. + /// The QIR bitcode stream. + /// The entry point name. + /// The arguments to the entry point. + /// The exit code. + public static async Task SubmitQir( + AzureSettings settings, Stream qir, string entryPoint, IReadOnlyList arguments) + { + // TODO + var submitter = new NoOpQirSubmitter(); + var job = await submitter.SubmitAsync(qir, entryPoint, arguments); + DisplayJob(job, settings.Output); + return 0; + } + /// /// Submits a job to Azure Quantum. /// @@ -134,9 +152,9 @@ private static void DisplayJob(IQuantumMachineJob job, OutputFormat format) DisplayWithColor( ConsoleColor.Yellow, Console.Error, - $"The friendly URI for viewing job results could not be obtained.{System.Environment.NewLine}" + - $"Error details: {ex.Message}" + - $"Showing the job ID instead."); + $"The friendly URI for viewing job results could not be obtained.{Environment.NewLine}" + + $"Error details: {ex.Message}{Environment.NewLine}" + + "Showing the job ID instead."); Console.WriteLine(job.Id); } @@ -238,14 +256,14 @@ public sealed class AzureSettings public string? AadToken { get; set; } /// - /// The base URI of the Azure Quantum endpoint. - /// If both and properties are not null, takes precedence. + /// The base URI of the Azure Quantum endpoint. If both and + /// properties are not null, is used. /// public Uri? BaseUri { get; set; } /// - /// The location to use with the default Azure Quantum endpoint. - /// If both and properties are not null, takes precedence. + /// The location to use with the default Azure Quantum endpoint. If both and + /// properties are not null, is used. /// public string? Location { get; set; } @@ -280,28 +298,28 @@ public sealed class AzureSettings /// The based on the settings. internal Workspace CreateWorkspace() { - if (BaseUri != null) + if (!(BaseUri is null)) { return AadToken is null ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: BaseUri) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: BaseUri); + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, BaseUri); } - else if (Location != null) + + if (!(Location is null)) { return AadToken is null ? new Workspace(Subscription, ResourceGroup, Workspace, location: NormalizeLocation(Location)) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, location: NormalizeLocation(Location)); - } - else - { - return AadToken is null - ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: null) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: null); + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, NormalizeLocation(Location)); } + + return AadToken is null + ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: null) + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: null); } public override string ToString() => - string.Join(System.Environment.NewLine, + string.Join( + Environment.NewLine, $"Subscription: {Subscription}", $"Resource Group: {ResourceGroup}", $"Workspace: {Workspace}", From 37491cb6263b6850bfb415b6263f70c0317eda0a Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 27 Apr 2021 15:23:20 -0700 Subject: [PATCH 059/145] Generate QIR argument list --- src/Simulation/CSharpGeneration/EntryPoint.fs | 80 +++++++++++++++---- src/Simulation/EntryPointDriver/Azure.cs | 31 ++++--- .../TestProjects/QirExe/Main.qs | 4 +- 3 files changed, 83 insertions(+), 32 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 6c06fcf342e..ecf4eb9561c 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -12,7 +12,6 @@ open Microsoft.Quantum.QsCompiler.SyntaxTree open Microsoft.Quantum.RoslynWrapper open System - /// An entry point parameter. type private Parameter = { Name : string @@ -104,8 +103,65 @@ let private callableTypeNames context (callable : QsCallable) = let private entryPointClassFullName (entryPoint : QsCallable) = { Namespace = entryPoint.FullName.Namespace; Name = entryPointClassName + entryPoint.FullName.Name } +/// The QIR argument type for the Q# type, or None if the Q# type is not supported in a QIR entry point. +let rec private qirArgumentType (type_ : ResolvedType) = + let case name = "global::Microsoft.Quantum.Runtime.ArgumentType." + name |> ident + + match type_.Resolution with + | Bool -> case "Bool" :> ExpressionSyntax |> Some + | Int -> case "Int" :> ExpressionSyntax |> Some + | Double -> case "Double" :> ExpressionSyntax |> Some + | Pauli -> case "Pauli" :> ExpressionSyntax |> Some + | Range -> case "Range" :> ExpressionSyntax |> Some + | Result -> case "Result" :> ExpressionSyntax |> Some + | String -> case "String" :> ExpressionSyntax |> Some + | ArrayType itemType -> + qirArgumentType itemType |> Option.map (fun itemType -> ``new`` (case "Array") ``(`` [itemType] ``)``) + | _ -> None + +/// The QIR argument value for the Q# type and value expression, or None if the Q# type is not supported in a QIR entry +/// point. +let rec private qirArgumentValue (type_ : ResolvedType) (value : ExpressionSyntax) = + let argumentValueName = "global::Microsoft.Quantum.Runtime.ArgumentValue" + let case name = sprintf "%s.%s" argumentValueName name |> ident + + let arrayValue itemValue itemType = + let values = + ident "global::System.Linq.Enumerable" + <.> (ident "Select", [value; upcast ``() =>`` ["item"] itemValue]) + + let items = + ident "global::System.Collections.Immutable.ImmutableArray" + <.> (sprintf "CreateRange<%s>" argumentValueName |> ident, [values]) + + case "Array" <.> (ident "TryCreate", [items; itemType]) + + match type_.Resolution with + | Bool -> ``new`` (case "Bool") ``(`` [value] ``)`` |> Some + | Int -> ``new`` (case "Int") ``(`` [value] ``)`` |> Some + | Double -> ``new`` (case "Double") ``(`` [value] ``)`` |> Some + | Pauli -> ``new`` (case "Pauli") ``(`` [value] ``)`` |> Some + | Range -> ``new`` (case "Range") ``(`` [value] ``)`` |> Some + | Result -> ``new`` (case "Result") ``(`` [value] ``)`` |> Some + | String -> ``new`` (case "String") ``(`` [value] ``)`` |> Some + | ArrayType itemType -> + Option.map2 arrayValue (ident "item" |> qirArgumentValue itemType) (qirArgumentType itemType) + | _ -> None + +/// The list of QIR arguments for the entry point parameters and the result of parsing the command-line arguments. +let private qirArguments parameters parseResult = + let argument param = + let value = + parseResult <.> (sprintf "ValueForOption<%s>" param.CSharpTypeName |> ident, [optionName param.Name]) + |> qirArgumentValue param.QSharpType + |> Option.defaultWith (fun () -> failwith "Unsupported parameter type.") + + ``new`` (ident "global::Microsoft.Quantum.Runtime.Argument") ``(`` [literal param.Name; value] ``)`` + + ident "global::System.Collections.Immutable.ImmutableList" <.> (ident "Create", parameters |> Seq.map argument) + /// Generates the Submit method for an entry point class. -let private submitMethod context entryPoint = +let private submitMethod context entryPoint parameters = let callableName, _, _ = callableTypeNames context entryPoint let parseResultParamName = "parseResult" let settingsParamName = "settings" @@ -127,8 +183,7 @@ let private submitMethod context entryPoint = ident settingsParamName :> ExpressionSyntax qirStream string entryPoint.FullName |> literal - // TODO - upcast ident "global::System.Collections.Immutable.ImmutableList.Empty" + qirArguments parameters (ident parseResultParamName) ] let hasQir = context.assemblyConstants.ContainsKey "QirOutputPath" @@ -172,25 +227,22 @@ let private simulateMethod context entryPoint = /// The class that adapts the entry point for use with the command-line parsing library and the driver. let private entryPointClass context (entryPoint : QsCallable) = let property name typeName value = ``property-arrow_get`` typeName name [``public``] get (``=>`` value) - let nameProperty = - entryPoint.FullName.ToString() - |> literal - |> property "Name" "string" - let summaryProperty = - (PrintSummary entryPoint.Documentation false).Trim () - |> literal - |> property "Summary" "string" + let nameProperty = string entryPoint.FullName |> literal |> property "Name" "string" + let summaryProperty = (PrintSummary entryPoint.Documentation false).Trim() |> literal |> property "Summary" "string" let parameters = parameters context entryPoint.Documentation entryPoint.ArgumentTuple + let members : MemberDeclarationSyntax list = [ nameProperty summaryProperty parameterOptionsProperty parameters createArgument context entryPoint - submitMethod context entryPoint + submitMethod context entryPoint parameters simulateMethod context entryPoint ] + let baseName = sprintf "%s.IEntryPoint" driverNamespace - ``class`` ((entryPointClassFullName entryPoint).Name) ``<<`` [] ``>>`` + + ``class`` (entryPointClassFullName entryPoint).Name ``<<`` [] ``>>`` ``:`` (Some (simpleBase baseName)) ``,`` [] [``internal``] ``{`` diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index d2815e9f27c..38820f478a7 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -317,22 +317,21 @@ internal Workspace CreateWorkspace() : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: null); } - public override string ToString() => - string.Join( - Environment.NewLine, - $"Subscription: {Subscription}", - $"Resource Group: {ResourceGroup}", - $"Workspace: {Workspace}", - $"Target: {Target}", - $"Storage: {Storage}", - $"AAD Token: {AadToken}", - $"Base URI: {BaseUri}", - $"Location: {Location}", - $"Job Name: {JobName}", - $"Shots: {Shots}", - $"Output: {Output}", - $"Dry Run: {DryRun}", - $"Verbose: {Verbose}"); + public override string ToString() => string.Join( + Environment.NewLine, + $"Subscription: {Subscription}", + $"Resource Group: {ResourceGroup}", + $"Workspace: {Workspace}", + $"Target: {Target}", + $"Storage: {Storage}", + $"AAD Token: {AadToken}", + $"Base URI: {BaseUri}", + $"Location: {Location}", + $"Job Name: {JobName}", + $"Shots: {Shots}", + $"Output: {Output}", + $"Dry Run: {DryRun}", + $"Verbose: {Verbose}"); internal static string NormalizeLocation(string location) => string.Concat(location.Where(c => !char.IsWhiteSpace(c))).ToLower(); diff --git a/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs b/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs index 6c7e71aa26a..6a0e67ab50b 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs +++ b/src/Simulation/Simulators.Tests/TestProjects/QirExe/Main.qs @@ -2,8 +2,8 @@ open Microsoft.Quantum.Intrinsic; @EntryPoint() - operation Main(x : Int, (y : Int, z : Int)) : Unit { + operation Main(xs : Int[], (y : Int, z : Int)) : Unit { Message("Hello, world!"); - Message($"({x}, ({y}, {z}))"); + Message($"({xs}, ({y}, {z}))"); } } From 9275c5a6211a890f8be3e82084086ccdba23bc2c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 29 Apr 2021 14:14:01 -0700 Subject: [PATCH 060/145] Update compiler package version to use new bond schema --- src/Qir/Controller/Controller.cs | 11 +++++++---- src/Qir/Controller/QirController.csproj | 1 - .../test-cases/standalone-input-test.in | Bin 44066 -> 44447 bytes .../QirExecutableTests.cs | 8 ++++---- .../Tests.Microsoft.Quantum.Qir.Tools/Util.cs | 11 +---------- .../Tools/Driver/IQirDriverGenerator.cs | 4 ++-- .../Driver/QirFullStateDriverGenerator.cs | 6 +++--- .../Tools/Executable/IQirExecutable.cs | 6 +++--- .../Tools/Executable/QirExecutable.cs | 6 +++--- .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 4 ++-- 10 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 09a8b1ef8c8..2e6593dde35 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -9,7 +9,7 @@ using Microsoft.Quantum.Qir.Model; using Microsoft.Quantum.Qir.Tools.Executable; using Microsoft.Quantum.Qir.Utility; -using QirExecutionWrapperSerialization = Microsoft.Quantum.QsCompiler.BondSchemas.QirExecutionWrapper.Protocols; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir { @@ -31,14 +31,17 @@ public static async Task ExecuteAsync( // Step 1: Parse input. logger.LogInfo("Parsing input."); using var inputFileStream = inputFile.OpenRead(); - var input = QirExecutionWrapperSerialization.DeserializeFromFastBinary(inputFileStream); + var input = Protocols.DeserializeQirExecutionWrapperFromFastBinary(inputFileStream); // Step 2: Create executable. logger.LogInfo("Creating executable."); + + // For now, only the first execution is used. + var executionInfo = input.Executions[0]; var bytecodeArray = input.QirBytecode.Array.Skip(input.QirBytecode.Offset).Take(input.QirBytecode.Count).ToList().ToArray(); var executableFile = new FileInfo(Path.Combine(BinaryDirectoryPath, ExecutableName)); var executable = new QirFullStateExecutable(executableFile, bytecodeArray, logger); - await executable.BuildAsync(input.EntryPoint, libraryDirectory, includeDirectory); + await executable.BuildAsync(executionInfo.EntryPoint, libraryDirectory, includeDirectory); // Step 3: Run executable. if (outputFile.Exists) @@ -46,7 +49,7 @@ public static async Task ExecuteAsync( outputFile.Delete(); } using var outputStream = outputFile.OpenWrite(); - await executable.RunAsync(input.EntryPoint, outputStream); + await executable.RunAsync(executionInfo, outputStream); } catch (Exception e) { diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index c4398261366..8d0768ebcef 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -22,7 +22,6 @@ - diff --git a/src/Qir/Controller/test-cases/standalone-input-test.in b/src/Qir/Controller/test-cases/standalone-input-test.in index 82a74f144f9776df10dafdcf777f60566c6767c0..d8402d40302c2d3b4fb6a9d439d261cce3fa853e 100644 GIT binary patch delta 1081 zcmaJ=yGjE=6uq;X(d`gU3m%ApMnvczR@tWQF4oW#itWP|Cn^f^)&%%Bf#t%Q<>dQ^8sU5Gfhf|6_k4cFqwSe5dQ z2!zH%OCU8Gp)HOcey=|cv%VLscbQ`CAV25x)1!twXvFgqov#M!z^gtkI@m)iNYHzc zH5&VHG+)@C6~`BL9Xmz>4QTWMI+{m~9n;8+?UI0%?EM%(f;Su#yvtaz25>b{?7WWk zg=EhyddZ1tm`(!ONFV#Z&XMbjZehiybR*!qZiaxK&GV&MC6G%OBJIBKr=7QdCwP%? delta 723 zcmYjPJxc>Y5S_hb&3%Zu;5BJfh(!<-(H{^k`~f!h7YreABy!0KR#({@QfVXDrM9uO z^d~5mmi`ExH@ln5z_EL~Z|1!>v(Mk&%cs`}H3gbZ7Vi)H^W*I@)})9i2+1FfXIE)f z45BuLDr!}mlN+g){xeb5Z4I}2_P@q!Y4=`EkdC;FsGDi)4##BfiELNO?bBypMjJ&RQfxReCE0XRY83manyh)2}WLU~3=~Y&n zI|lL0%b4PepmN}HH#GgZt~Cg2>OsRd?81aqE_hpX0Npjr$rK5E?(IB3BP^1-yo z%xmBo_2+S;TK)qMlVZ*Q diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs index 217a12ca09c..a47b4023b68 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -8,7 +8,7 @@ using Microsoft.Quantum.Qir.Tools.Driver; using Microsoft.Quantum.Qir.Tools.Executable; using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; using Moq; using Xunit; @@ -98,12 +98,12 @@ public async Task TestRun() { // Set up. using var outputStream = new MemoryStream(); - var entryPoint = new EntryPointOperation(); + var execInfo = new ExecutionInformation(); var arguments = "arguments"; - driverGeneratorMock.Setup(obj => obj.GetCommandLineArguments(entryPoint)).Returns(arguments); + driverGeneratorMock.Setup(obj => obj.GetCommandLineArguments(execInfo)).Returns(arguments); // Run executable. - await qirExecutable.Object.RunAsync(entryPoint, outputStream); + await qirExecutable.Object.RunAsync(execInfo, outputStream); // Verify runner was invoked properly. runnerMock.Verify(obj => obj.RunExecutableAsync(executableFile, outputStream, arguments)); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs index 85c1d3a90e6..ab6aee7d8eb 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs @@ -3,7 +3,7 @@ using System.IO; using System.Reflection; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Tests.Microsoft.Quantum.Qir.Tools { @@ -17,14 +17,5 @@ public static void DeleteDirectory(DirectoryInfo directory) } directory.Delete(); } - - - public static bool EntryPointsAreEqual(EntryPointOperation entryPointA, EntryPointOperation entryPointB) - { - var method = typeof(Extensions) - .GetMethod("ValueEquals", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(EntryPointOperation), typeof(EntryPointOperation) }, null); - object[] parameters = { entryPointA, entryPointB }; - return (bool)method.Invoke(null, parameters); - } } } diff --git a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs index 5c995bd7d0a..28c3ef5fc90 100644 --- a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs @@ -3,7 +3,7 @@ using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir.Tools.Driver { @@ -11,6 +11,6 @@ public interface IQirDriverGenerator { Task GenerateAsync(EntryPointOperation entryPoint, Stream stream); - string GetCommandLineArguments(EntryPointOperation entryPoint); + string GetCommandLineArguments(ExecutionInformation executionInformation); } } diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs index e09ac1196c1..20ff9bb5491 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs @@ -4,7 +4,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.QsCompiler; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir.Tools.Driver { @@ -15,9 +15,9 @@ public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) await Task.Run(() => QirDriverGeneration.GenerateQirDriverCpp(entryPoint, stream)); } - public string GetCommandLineArguments(EntryPointOperation entryPoint) + public string GetCommandLineArguments(ExecutionInformation executionInformation) { - return QirDriverGeneration.GenerateCommandLineArguments(entryPoint.Arguments); + return QirDriverGeneration.GenerateCommandLineArguments(executionInformation); } } } diff --git a/src/Qir/Execution/Tools/Executable/IQirExecutable.cs b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs index 6dc5914b5ea..765207e3c99 100644 --- a/src/Qir/Execution/Tools/Executable/IQirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs @@ -3,7 +3,7 @@ using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir.Tools.Executable { @@ -21,9 +21,9 @@ public interface IQirExecutable /// /// Runs the executable. /// - /// Entry point operation. + /// Execution information to run the executable with.. /// Stream to which output will be written. /// - Task RunAsync(EntryPointOperation entryPoint, Stream output); + Task RunAsync(ExecutionInformation executionInformation, Stream output); } } diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs index 265006d2034..a1613c41773 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Microsoft.Quantum.Qir.Tools.Driver; using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir.Tools.Executable { @@ -80,9 +80,9 @@ public async Task BuildAsync(EntryPointOperation entryPoint, DirectoryInfo libra await executableGenerator.GenerateExecutableAsync(ExecutableFile, sourceDirectory, libraryDirectory, includeDirectory, LinkLibraries); } - public async Task RunAsync(EntryPointOperation entryPoint, Stream output) + public async Task RunAsync(ExecutionInformation executionInformation, Stream output) { - var stringArguments = driverGenerator.GetCommandLineArguments(entryPoint); + var stringArguments = driverGenerator.GetCommandLineArguments(executionInformation); await runner.RunExecutableAsync(ExecutableFile, output, stringArguments); } diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index 06ca9571b79..f89615e8dc7 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -11,7 +11,7 @@ - + From a1714d07b2781bd8209601a0a9e9d71c3430aca7 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 30 Apr 2021 11:08:14 -0700 Subject: [PATCH 061/145] Add test case and fix test script --- src/Qir/Controller/test-cases/no-args-test.in | Bin 0 -> 27965 bytes .../Controller/test-cases/no-args-test.out | 2 ++ src/Qir/Controller/test-qir-controller.ps1 | 29 +++++++++--------- 3 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 src/Qir/Controller/test-cases/no-args-test.in create mode 100644 src/Qir/Controller/test-cases/no-args-test.out diff --git a/src/Qir/Controller/test-cases/no-args-test.in b/src/Qir/Controller/test-cases/no-args-test.in new file mode 100644 index 0000000000000000000000000000000000000000..a0a93acfb67da63c7f320d45518c24fb37dd588b GIT binary patch literal 27965 zcmeHQ4_Fgdwx1y(2@sNjq74wj@JE|kw+#pwL^L5_!J;o%yKB34NrWKjBE*0etZgR= z8nmn%Ep6$R?u#yUZJ+zSbn9-lwfiN6Rcg@%|8%Xo-6*J3t;LphTea)EH#3uo1QlB8 z+qRkSGxOu*%)RHHd(OS*-Z?i$gd*W+cqkGUiX@h-&{o&2SXNrPP*+TQ9=}>fR@BZkQXNc_K+kb1pEyk z!ZoFARCck8I9Pi2CbW@1DU=s0VL!8k5Eq2xZHmb2$I@fuJkbN;>Bgo)LuXP-ezdh2 zQ*H_=@8Z24gRAB=;qRj9#zxT;=@eVqYRBS@_}(s1?m8Snl;ED8+!cnGuVFu%(%uL@ z`WiReVxo&TG)FY{7h_!=Vv~Z%4pHx15*lYwSQNP3B}O-eg{C(ni+dOREw4EWX_2z? zHmiG*!$gN$QxHo!9wRijD;iU?)%e^ntUTNDa&mjx9v;%6-pq@QT(+L*QvaUc)NPsd zv&s^-ri_iO5u7A+sCkVj1*u#Z-dLEQT=FWP*K3)tQ`jUeze(ZkQzZYP=^-|I-Qu;_ zy24cRb7<1~joW$QXm7aESR7M+58K?X#x6ELXWOQWOF;^M#_QaWpZwd{m8sER?IWR_{bv|0#71H5hw%p*&Sw09uDqv zg}kUud25?n5HurCG!Z9I(P6a5iSW-OT^fY55^0eksvIIAdMjTw6ZAX06gbBzDB>e! zHY+p-aPc}3dtpKR06JKaC&1Bd3wzhDLax46X~{(n&g)7_MTD#=#|%QE4V|#e$#otj z)@Svz?8_Ae@k6K~$G#=<3c^cN_i~;>rp7obRkM-m@I^aZiAY)K)MJA}jWv~nWHxn@ zbs_8}2>;djukfdmEg`9C$l8S$I+iIY9(aRn>OJQOKT;p)* z2~qHgq=({OcEuu81L2oVsI1-mN=6|I_hW_ie$~#=BW#9V`&OAYsK-yt6ueXR$$e;@8?txuR5H~njXkmEh1F0{`J7- z7~l2W+3!#EHv9=re8TYB^Ljn}69|vtg`7uT;#4^p5~-qNM>LUeMDSfuMU&&}R}PnR zeU(K3O_9D}!zaAu;`(a{3K{ZGBCx=z;_WW~hjF0ua~mv~@_^nsC9ba@UUhi8C6gfN zioqTB&L377I2gtdy}k2+pkp&-_T)E^bAJOO&@qe%g2Ns^!!p=d{#4lT&k`Mha&p&X zF7juDWxl$_!HMuA!rEV36>~!4uMV$mJf9b+qIoARe$RTF^YvC|V1W}RydO}Y?)M#W zz?YZ{dPK)V1`8bj>C4;Q?}hi_T$%#!khA}1ngGt{gb}|CFpRl6ZD2nRP2CxwpSjyZ zvjX(9>(3+T=jz13<`kSU#|Jd0{84Aqx)CJ1< z)g@b?oaeS$7kejjpH$E?2Xg~0bNyaxpk=;%d4$><5(6zW^b1v><{x=F&^#Xcw=i(r zn4&rrsG=Q(gMrF4Kd>c`^PQr==1eIF3smNjyDtU!#T4VDV*!3K;SF|Rb1pwWLUS%h z*92I5hxXJP2*MawC(?T8M4E{+Q4Jj$cz1L>JN%`G5v1G%y9EdT(j~2UY*ewWIc)O% zd)TUwW~40i3$skn8v?(?|uu-+8;6Q;O?4|fN zaccdl)lb=Y(Q(OnTe=2#Ve9V7mS(4J>2L41Io|5nmzVd;XZ|N*-F*&OTI!yzecgrT zj_`=^89DhS=yPx^eI3LG&w~3j9wF{LDXxe?bDLE1Mt5@_!ELDL*0wI^pFxBlV}c<< zFpZxl>2M_+*etG)g?ia6@!hQ4E>&(bE4RD8xz50Sg2!zrv>FWDRR-3|daD7q#&$;u zF4zPoWx{Hiuy0T>s1{7aIukxj0%1!+hgMP{TbHxjlGCHg-ocu=+cL9}mD4>Kvr@x- zqLMqk(rN^sgwyN#agZ!agnMeVZz~OO@T~{oLu6x2WVzteh72eW22-=A6T<9EY2~ zS8p{evKkGRx=L=n##$$`*4eGG2Obn&M1-HJ1^qTbpF(&N7hC|Xz@-T%T#^nDg(ZO~ zOme~_?mwAu4wY1hO5_gJj5bS7w>p(-h{pPOJ-5EKq2CgOIB2Q$aUc(myGqJ6wwf0AVS)=z z!D+SNGg*r3pi@GKGYlpR5L)UdsMTKSAk8zup=VeC%f_ zcc`*^+~zalJ)0v3l+cvUBqfkKn3&P05u8;6)e8Hef`w<*f*}WC;xP(47QaGWAS>t#|C0n9Ka31F$IqVb;2apDLsbrOM4EhOIjqQ)o z0st;8jvzVUPL~P4ACj8lzzviIA2e_-YIr`Vrl5`UvBC#0Fz{m;LxqqBN>FpoYhpTO zOEgfRr5?c?1{P3I-y_JUp_73<0?-ccV|u4RWk0F#t{+JGvqU}ljrl)$b|@sGpm2`J zCjS+;#A%*2S%jyt@scPPwtq)-^q-11P2kAp*UlingsmdmycpcatIhveT4R*`pP=`r z{qzoPerTI1+J1xw5Mytj7$_Sua6X|;&&IjvXL=00=x2H~1dokSf|K)+n(_r3=Oc_y zdWwfLfHjLm2+ypH+pUt(a3>AX_-(2rnz~J;Xcol)UQ>L#&oB`onnu~^pa4JuTDi_6 z2ur4FGjJ~1VrU1tL{QKMMkycsgn@$?LuKGOhGBq#=NN_o8s4xr15+*o2Q>^;6B8$3 zd-p=Tv@rr^0aHEFKLKQjL0uwt1=GFEj*lFv{f`H-~UmDBp;2qeD&#NYtZIH zZS(t-F%CN&k!o=S3Hly6qcPW9lhdiu-6lj2X<6;5 zF}AKI6H4HscGE2O0SYQ-vFBSOqkpGXB$NJN<6OlQG`vDX1Ltc4MFmg|Ae_?_+)FYY zapEa)2=ClpWz*Iu77J0zG?pjjza?RztT(vt|}ro!jQ{`3T#ElVSPJBnO^aY_E z|IOVU>t)2o7tXH8dZ*xj-5;Ee=2z~~%HO&7zBdO}$lshbeBO)*K^_kbeC>rlN~sM zl&3jL@Ia%|q_7<`?A9rkvn$VH>V=OB@(Lp3u{;&x=HweN#caVdx)Rz+og6%BA?>7i zl!l%-FN28_T0AQ0R2k|>2E^qyl2(GUg?lq8%LjHwLyyq)3JBxAmA-(=eERant0Gj2 z0$LI5Ta8GHZ=_wkj@L}XT3+*0; zIQ<|PM`>WJ{hhBJgKHSyqTxroh6%>fl8U_VAeMH|^8{mQ?|M8KOOGa&&h?AQs5L>> z@HN5kSo&QUH+p1XO;88d1a>L2CNSk>c-I8ZO(`}rfk zwitBeUZazf^tx|fGAXKx-j~Fq==t%2N>-)dqbNTfYyrof`(I zGGB(`c?h{6R&#QnRAX*>uOtU^QP4HR2hkipL*<)bAQcJfr}7*`*mX&VSt5^oKg@{Q zpWko)brdIK{u?kCu~Kzi9#sBqk)Mnz$FZ$+v(fKLFO`0J897G~WS=rAfEO4zQckLq zGr;8i4KR6sXMK5pzGOdT+zux1ubs*JYiIKQ?7qA|Z?Yfx0@4HX{=6G;tC8>~U%9(2 zYC3apCj)n@7%BtX8HP3nwlfTE4BYK5@s-QK-4=#wDFLaz$b=i(=UNe#?X%CnUHkj> z_Bx59@YyT)a*n8nH0I5bCf^wpEsh{T`yJV@Tm9_!y0yJGpNGn`tIP~h?1>_@>lesE zpRb<}$1i#{Iph@oWBSwrrE5doKYPSsp{Z1Io!%gH(NH6F9emRLEY9TFf#kaV^auu_ zH%G0sEFtV(kR{~J zcFL)@K4)9EgyQxjn)MWPLg;;PfRJqG+m8QQC7buPoYz9_K392!?`4pafZiiSv&ek( zYC`C8plNJ2Sef$@d^vN6S;fqIK6SK`&Sq0UNP3ngq8BXeVWzGtw$t(gy(0HPWn4?A ziKHsyYz%D4Cwx=}UUmC;hZuNO<>MWqp)0nv(Mp%l(rKZgje#xs3^m{4O@d?cXulXX zH%u16tZSt|FDLq#zrTn@NdJT`cdhhzxq|$%F^hc}7z((w zcrgF%$D054Ls=&U-&c-pA1XNCjy&H6<3&0g{LhXTe`s-0Oa1uAMV1E+`|_WHanX+} zE(-1=2KNzz`-tPekN880r-S1~aJ&eP7vn!(ybShV=yPA+r~N&T#7rHJWi>FzV|V(F z$9fXxpPED;kF`9_qmI}XvLGan$Ff#AyvJi*8Q^%V`h9Z0(P5fB^$@l72(n9$QpaPJ zv%wKpcofmY`4R&uI4T7=UD((YMd#rta~=8fe0eyNqRQzEnN$eL*D`;`5~$Y?ZOWPT z)Nx!t*sd%RAEkFa8K^7*Qjo`wQ3kqZ`*@WMbU}$pULY|A+e}6EK5EfS8lntT7G*Hh zj8^zQD7fc0`ZKS=xhgnU1?Q^qpR0ngZSY*rkL~vXf;o8KJO>ZPFm!ASe=vjoeKGZf z&#B)RV}poJ<8qThUezZc+W{U%QvORo1!}7=VtnvJLf~2WPMge+0RUXfaRiwG?&$(7 zxpBguIjyf(5t1hEm)fU@)U&)r3)%?jSK+OHe2ci}UlCoK-X(tWHh zh|E@DrJHY>{%@@5P`oL7UGz4~PfR(Nqr2SMrrZN}3>+#n&Hf;U*Z7D@d2*sOqrs#) zcxPe%I#a>NqROEcP4|Bo+tmJ=spzY?oh@&fia&`z+Opp?|GyKyY&maIpO=VMTrn;9 zC{g}Ugn8i=e9=P^^G~lO*H6eXFB(i~{p$nfN1mCq^T^N5i?2>Px~9tfix=+tQumBm zGawbM{Ed0ZXLrjdZ#S0@O<9!nwz=ZkJ@se0VcX&LC^%&GGEhb|tL1bt_*<=AQKc{P zelGHUKJ5K`q+pq$u3>?;dZ|vWHP-31RZ4@QN?)d})7Mm&mZr_qEvqp$%+pqDm+F@3 zs_Ou0B);^Kh|>Ze9+59&q=z#{B4&+5oIVm!J`yo|Bx0IuMCypmOiRDTPl1<~E~zPR zC@o!1|6;fiXsou*sIOjHT4vN~>vY4uTc)e61*#oJrJh(}D2GoNbrm|JuDVQDT2`~7 zx^AAn%ve)fQvpi$N%Nq7*@`Nv&nTkWSW^ZHuQ8UE7Sz}2s%t@qf}bsi-P@q5sV>*U z9@bV>H564t`D*oLBMPrI8nq3jlqA|Jy|$K=Vwl8bT0`9mqi!^eRaM$0Rkz?=t_PxO zp{Qm4qUx^~b=)+eBvmn<YZjDWR#!Ewv2`m9z~DyozcSzfUUT&73K(0Rv8Jj@S6-~IsMD2~mX0_!(2nxB z5tyjXcne;yJQV9N!F;uovIUNpX{DtLbQLPE+Xs%sz?-2%dcVGz5b0wO81UXi;Oj<% zQCgwCdSwl;!|TUHvP(ubzMHZ7jX>k(ovQJ6e^>!<%W-W0=){|u#I!M(1mN|KR--U? z!0K;3w~zp^`WGB%{=gV-Z2sWO(V2h77}^SW{YAQ20|4u2+e)(f7d+m559+#^?3rUw z3E=gY{1(NIRwba+VcmbTg0sdTFW?=mynuDI@{+9n1>c4)EUGA|s@2^%0As=+eT5Ei z-v0P!m;|?PIDOs=y>5t2Y=f1z(x@Tm0x${nVUn-)EmAUq8)k6LEHJ8GFpUjL$fTL>fn-)6V? Xy0jEbUOHoqAua7**}ZVj-+TQZ4{$0q literal 0 HcmV?d00001 diff --git a/src/Qir/Controller/test-cases/no-args-test.out b/src/Qir/Controller/test-cases/no-args-test.out new file mode 100644 index 00000000000..be77bba6b31 --- /dev/null +++ b/src/Qir/Controller/test-cases/no-args-test.out @@ -0,0 +1,2 @@ +Success! +() diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index c8dc17ea1aa..c9f20f54250 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -57,6 +57,8 @@ foreach ( $path in $libraryPaths ) # Go through each input file in the test cases folder. Get-ChildItem $testCasesFolder -Filter *.in | Foreach-Object { +Write-Host $_.BaseName + # Get the paths to the output and error files to pass to the QIR controller. $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) @@ -80,22 +82,21 @@ Foreach-Object { else { Write-Host "##[info]Test case '$($_.BaseName)' passed" } - continue; - } - - $expectedError = Get-Content -Path $expectedErrorFile -Raw - $actualError = Get-Content -Path $errorFile -Raw - if (-not ($expectedError -ceq $actualError)) { - Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" - Write-Host "##[info]Expected error:" - Write-Host $expectedError - Write-Host "##[info]Actual error:" - Write-Host $actualError - $script:all_ok = $False - continue } else { - Write-Host "##[info]Test case '$($_.BaseName)' passed" + $expectedError = Get-Content -Path $expectedErrorFile -Raw + $actualError = Get-Content -Path $errorFile -Raw + if (-not ($expectedError -ceq $actualError)) { + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Expected error:" + Write-Host $expectedError + Write-Host "##[info]Actual error:" + Write-Host $actualError + $script:all_ok = $False + } + else { + Write-Host "##[info]Test case '$($_.BaseName)' passed" + } } } From 0e4d33fba4024bd30b343e67d5533fac26f275ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 30 Apr 2021 23:01:25 -0700 Subject: [PATCH 062/145] Move QIR driver generator (#660) * Create base for moving QIR driver generator. * Added QirCppInterop. * Added more structure. * Set test infra. * Changed QirCppInterop.cs to use extension methods. * Full template implemented. * Update test cases. * Implemented initializer. * Use string reader. * Fixed issues by changes in Bond schema. * Moved implementation for GetCommandLineArguments. * Add test cases. * Fix driver compilation issues. * Fixed compilation warnings. * Added test cases. --- .../QirDriverGeneratorTests.cs | 181 ++++++ .../FullStateDriverGenerator/UseBoolArg.cpp | 87 +++ .../UseBoolArrayArg.cpp | 112 ++++ .../FullStateDriverGenerator/UseDoubleArg.cpp | 76 +++ .../UseDoubleArrayArg.cpp | 101 +++ .../UseIntegerArg.cpp | 76 +++ .../UseIntegerArrayArg.cpp | 101 +++ .../FullStateDriverGenerator/UseMiscArgs.cpp | 174 ++++++ .../FullStateDriverGenerator/UseNoArgs.cpp | 65 ++ .../FullStateDriverGenerator/UsePauliArg.cpp | 90 +++ .../UsePauliArrayArg.cpp | 117 ++++ .../FullStateDriverGenerator/UseRangeArg.cpp | 106 ++++ .../UseRangeArrayArg.cpp | 144 +++++ .../FullStateDriverGenerator/UseResultArg.cpp | 87 +++ .../UseResultArrayArg.cpp | 112 ++++ .../FullStateDriverGenerator/UseStringArg.cpp | 81 +++ .../Tests.Microsoft.Quantum.Qir.Tools.csproj | 48 ++ .../Tools/Driver/IQirSimulatorInitializer.cs | 18 + .../Execution/Tools/Driver/QirCppDriver.cs | 576 ++++++++++++++++++ .../Execution/Tools/Driver/QirCppDriver.tt | 246 ++++++++ .../Execution/Tools/Driver/QirCppDriverEx.cs | 20 + .../Tools/Driver/QirCppDriverGenerator.cs | 156 +++++ .../QirCppFullStateSimulatorInitializer.cs | 302 +++++++++ .../QirCppFullStateSimulatorInitializer.tt | 3 + .../Execution/Tools/Driver/QirCppInterop.cs | 137 +++++ .../Driver/QirFullStateDriverGenerator.cs | 14 +- .../QirFullStateSimulatorInitializer.cs | 22 + .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 30 +- 28 files changed, 3275 insertions(+), 7 deletions(-) create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp create mode 100644 src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriver.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriver.tt create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt create mode 100644 src/Qir/Execution/Tools/Driver/QirCppInterop.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs new file mode 100644 index 00000000000..f4f92e66a4e --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -0,0 +1,181 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Xunit; + +using Microsoft.Quantum.Qir.Tools.Driver; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; + +namespace Tests.Microsoft.Quantum.Qir.Tools +{ + public class QirDriverGeneratorTests + { + private static string TestArtifactsDirectory = Path.Combine("TestArtifacts", "FullStateDriverGenerator"); + private static string TestCasesDirectory = Path.Combine("TestCases", "FullStateDriverGenerator"); + private static IDictionary TestCases = + new Dictionary + { + { + "UseNoArgs", + new EntryPointOperation{Name = "UseNoArgs"} + }, + { + "UseBoolArg", + new EntryPointOperation + { + Name = "UseBoolArg", + Parameters = new List{new Parameter{ Name = "BoolArg", Type = DataType.BoolType}} + } + }, + { + "UseBoolArrayArg", + new EntryPointOperation + { + Name = "UseBoolArrayArg", + Parameters = new List{new Parameter{ Name = "BoolArrayArg", Type = DataType.ArrayType, ArrayType = DataType.BoolType}} + } + }, + { + "UseDoubleArg", + new EntryPointOperation + { + Name = "UseDoublArg", + Parameters = new List{new Parameter{ Name = "DoubleArg", Type = DataType.DoubleType}} + } + }, + { + "UseDoubleArrayArg", + new EntryPointOperation + { + Name = "UseDoubleArrayArg", + Parameters = new List{new Parameter{ Name = "DoubleArrayArg", Type = DataType.ArrayType, ArrayType = DataType.DoubleType}} + } + }, + { + "UseIntegerArg", + new EntryPointOperation + { + Name = "UseIntegerArg", + Parameters = new List{new Parameter{ Name = "IntegerArg", Type = DataType.IntegerType}} + } + }, + { + "UseIntegerArrayArg", + new EntryPointOperation + { + Name = "UseIntegerArrayArg", + Parameters = new List{new Parameter{ Name = "IntegerArrayArg", Type = DataType.ArrayType, ArrayType = DataType.IntegerType}} + } + }, + { + "UsePauliArg", + new EntryPointOperation + { + Name = "UsePauliArg", + Parameters = new List{new Parameter{ Name = "PauliArg", Type = DataType.PauliType}} + } + }, + { + "UsePauliArrayArg", + new EntryPointOperation + { + Name = "UsePauliArrayArg", + Parameters = new List{new Parameter{ Name = "PauliArrayArg", Type = DataType.ArrayType, ArrayType = DataType.PauliType}} + } + }, + { + "UseRangeArg", + new EntryPointOperation + { + Name = "UseRangeArg", + Parameters = new List{new Parameter{ Name = "RangeArg", Type = DataType.RangeType}} + } + }, + { + "UseRangeArrayArg", + new EntryPointOperation + { + Name = "UseRangeArrayArg", + Parameters = new List{new Parameter{ Name = "RangeArrayArg", Type = DataType.ArrayType, ArrayType = DataType.RangeType}} + } + }, + { + "UseResultArg", + new EntryPointOperation + { + Name = "UseResultArg", + Parameters = new List{new Parameter{ Name = "ResultArg", Type = DataType.ResultType}} + } + }, + { + "UseResultArrayArg", + new EntryPointOperation + { + Name = "UseResultArrayArg", + Parameters = new List{new Parameter{ Name = "ResultArrayArg", Type = DataType.ArrayType, ArrayType = DataType.ResultType}} + } + }, + { + "UseStringArg", + new EntryPointOperation + { + Name = "UseStringArg", + Parameters = new List{new Parameter{ Name = "StringArg", Type = DataType.StringType}} + } + }, + { + "UseMiscArgs", + new EntryPointOperation + { + Name = "UseMiscArgs", + Parameters = new List{ + new Parameter{ Name = "BoolArg", Type = DataType.BoolType}, + new Parameter{ Name = "IntegerArrayArg", Position = 1, Type = DataType.ArrayType, ArrayType = DataType.IntegerType}, + new Parameter{ Name = "RangeArg", Position = 2, Type = DataType.RangeType}, + new Parameter{ Name = "StringArg", Position = 3, Type = DataType.StringType} + } + } + } + }; + + [Theory] + [InlineData("UseNoArgs")] + [InlineData("UseBoolArg")] + [InlineData("UseBoolArrayArg")] + [InlineData("UseDoubleArg")] + [InlineData("UseDoubleArrayArg")] + [InlineData("UseIntegerArg")] + [InlineData("UseIntegerArrayArg")] + [InlineData("UsePauliArg")] + [InlineData("UsePauliArrayArg")] + [InlineData("UseRangeArg")] + [InlineData("UseRangeArrayArg")] + [InlineData("UseResultArg")] + [InlineData("UseResultArrayArg")] + [InlineData("UseStringArg")] + [InlineData("UseMiscArgs")] + public void GenerateFullStateSimulatorDriver(string testCase) + { + var entryPointOperation = TestCases[testCase]; + var driverGenerator = new QirFullStateDriverGenerator(); + var driverFileName = $"{testCase}.cpp"; + var verificationCppSourceCode = File.ReadAllText(Path.Combine(TestCasesDirectory, driverFileName)); + if (!Directory.Exists(TestArtifactsDirectory)) + { + Directory.CreateDirectory(TestArtifactsDirectory); + } + + var generatedStream = File.Create(Path.Combine(TestArtifactsDirectory, driverFileName)); + driverGenerator.GenerateAsync(entryPointOperation, generatedStream).Wait(); + var generatedStreamReader = new StreamReader(generatedStream, Encoding.UTF8); + var generatedCppSourceCode = generatedStreamReader.ReadToEnd(); + Assert.Equal(verificationCppSourceCode, generatedCppSourceCode); + generatedStream.Close(); + + } + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp new file mode 100644 index 00000000000..ac2d8510044 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Bool type. +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map BoolAsCharMap{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar} +}; + +extern "C" void UseBoolArg( + char BoolArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + char BoolArgCli; + BoolArgCli = InteropFalseAsChar; + app.add_option("--BoolArg", BoolArgCli, "Option to provide a value for the BoolArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(BoolAsCharMap, CLI::ignore_case)); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + char BoolArgInterop = BoolArgCli; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseBoolArg( + BoolArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp new file mode 100644 index 00000000000..49ba88538d7 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp @@ -0,0 +1,112 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// Auxiliary functions for interop with Q# Bool type. +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map BoolAsCharMap{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar} +}; + +extern "C" void UseBoolArrayArg( + InteropArray* BoolArrayArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + vector BoolArrayArgCli; + app.add_option("--BoolArrayArg", BoolArrayArgCli, "Option to provide a value for the BoolArrayArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(BoolAsCharMap, CLI::ignore_case)); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + unique_ptr BoolArrayArgUniquePtr = CreateInteropArray(BoolArrayArgCli); + InteropArray* BoolArrayArgInterop = BoolArrayArgUniquePtr.get(); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseBoolArrayArg( + BoolArrayArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp new file mode 100644 index 00000000000..c07687f1e4e --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +extern "C" void UseDoublArg( + double_t DoubleArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + double_t DoubleArgCli; + DoubleArgCli = 0.0; + app.add_option("--DoubleArg", DoubleArgCli, "Option to provide a value for the DoubleArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + double_t DoubleArgInterop = DoubleArgCli; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseDoublArg( + DoubleArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp new file mode 100644 index 00000000000..707c2095bc9 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp @@ -0,0 +1,101 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +extern "C" void UseDoubleArrayArg( + InteropArray* DoubleArrayArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + vector DoubleArrayArgCli; + app.add_option("--DoubleArrayArg", DoubleArrayArgCli, "Option to provide a value for the DoubleArrayArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + unique_ptr DoubleArrayArgUniquePtr = CreateInteropArray(DoubleArrayArgCli); + InteropArray* DoubleArrayArgInterop = DoubleArrayArgUniquePtr.get(); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseDoubleArrayArg( + DoubleArrayArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp new file mode 100644 index 00000000000..6d4d4614f9a --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +extern "C" void UseIntegerArg( + int64_t IntegerArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + int64_t IntegerArgCli; + IntegerArgCli = 0; + app.add_option("--IntegerArg", IntegerArgCli, "Option to provide a value for the IntegerArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + int64_t IntegerArgInterop = IntegerArgCli; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseIntegerArg( + IntegerArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp new file mode 100644 index 00000000000..e3cc2f8bf60 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp @@ -0,0 +1,101 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +extern "C" void UseIntegerArrayArg( + InteropArray* IntegerArrayArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + vector IntegerArrayArgCli; + app.add_option("--IntegerArrayArg", IntegerArrayArgCli, "Option to provide a value for the IntegerArrayArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + unique_ptr IntegerArrayArgUniquePtr = CreateInteropArray(IntegerArrayArgCli); + InteropArray* IntegerArrayArgInterop = IntegerArrayArgUniquePtr.get(); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseIntegerArrayArg( + IntegerArrayArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp new file mode 100644 index 00000000000..28373859dbf --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp @@ -0,0 +1,174 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} + +// Auxiliary functions for interop with Q# Bool type. +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map BoolAsCharMap{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar} +}; + +// Auxiliary functions for interop with Q# String type. +const char* TranslateStringToCharBuffer(string& s) +{ + return s.c_str(); +} + +extern "C" void UseMiscArgs( + char BoolArg, + InteropArray* IntegerArrayArg, + InteropRange* RangeArg, + const char* StringArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + char BoolArgCli; + BoolArgCli = InteropFalseAsChar; + app.add_option("--BoolArg", BoolArgCli, "Option to provide a value for the BoolArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(BoolAsCharMap, CLI::ignore_case)); + + vector IntegerArrayArgCli; + app.add_option("--IntegerArrayArg", IntegerArrayArgCli, "Option to provide a value for the IntegerArrayArg parameter") + ->required(); + + RangeTuple RangeArgCli; + app.add_option("--RangeArg", RangeArgCli, "Option to provide a value for the RangeArg parameter") + ->required(); + + string StringArgCli; + app.add_option("--StringArg", StringArgCli, "Option to provide a value for the StringArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + char BoolArgInterop = BoolArgCli; + + unique_ptr IntegerArrayArgUniquePtr = CreateInteropArray(IntegerArrayArgCli); + InteropArray* IntegerArrayArgInterop = IntegerArrayArgUniquePtr.get(); + + InteropRange* RangeArgInterop = TranslateRangeTupleToInteropRangePointer(RangeArgCli); + + const char* StringArgInterop = TranslateStringToCharBuffer(StringArgCli); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseMiscArgs( + BoolArgInterop, + IntegerArrayArgInterop, + RangeArgInterop, + StringArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp new file mode 100644 index 00000000000..eb6597a7f4f --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +extern "C" void UseNoArgs( +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseNoArgs( + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp new file mode 100644 index 00000000000..134db56ea44 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Pauli type. +map PauliMap{ + {"PauliI", PauliId::PauliId_I}, + {"PauliX", PauliId::PauliId_X}, + {"PauliY", PauliId::PauliId_Y}, + {"PauliZ", PauliId::PauliId_Z} +}; + +char TranslatePauliToChar(PauliId& pauli) +{ + return static_cast(pauli); +} + +extern "C" void UsePauliArg( + char PauliArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + PauliId PauliArgCli; + PauliArgCli = PauliId::PauliId_I; + app.add_option("--PauliArg", PauliArgCli, "Option to provide a value for the PauliArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(PauliMap, CLI::ignore_case)); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + char PauliArgInterop = TranslatePauliToChar(PauliArgCli); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UsePauliArg( + PauliArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp new file mode 100644 index 00000000000..22b27411fe6 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// Auxiliary functions for interop with Q# Pauli type. +map PauliMap{ + {"PauliI", PauliId::PauliId_I}, + {"PauliX", PauliId::PauliId_X}, + {"PauliY", PauliId::PauliId_Y}, + {"PauliZ", PauliId::PauliId_Z} +}; + +char TranslatePauliToChar(PauliId& pauli) +{ + return static_cast(pauli); +} + +extern "C" void UsePauliArrayArg( + InteropArray* PauliArrayArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + vector PauliArrayArgCli; + app.add_option("--PauliArrayArg", PauliArrayArgCli, "Option to provide a value for the PauliArrayArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(PauliMap, CLI::ignore_case)); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + vector PauliArrayArgIntermediate; + TranslateVector(PauliArrayArgCli, PauliArrayArgIntermediate, TranslatePauliToChar); + unique_ptr PauliArrayArgUniquePtr = CreateInteropArray(PauliArrayArgIntermediate); + InteropArray* PauliArrayArgInterop = PauliArrayArgUniquePtr.get(); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UsePauliArrayArg( + PauliArrayArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp new file mode 100644 index 00000000000..3b89eb0ab7c --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp @@ -0,0 +1,106 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} + +extern "C" void UseRangeArg( + InteropRange* RangeArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + RangeTuple RangeArgCli; + app.add_option("--RangeArg", RangeArgCli, "Option to provide a value for the RangeArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + InteropRange* RangeArgInterop = TranslateRangeTupleToInteropRangePointer(RangeArgCli); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseRangeArg( + RangeArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp new file mode 100644 index 00000000000..354999a5251 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} + +// Auxiliary functions for interop with Q# Range[] type +template +void FreePointerVector(vector& v) +{ + for (auto p : v) + { + delete p; + } +} + +extern "C" void UseRangeArrayArg( + InteropArray* RangeArrayArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + vector RangeArrayArgCli; + app.add_option("--RangeArrayArg", RangeArrayArgCli, "Option to provide a value for the RangeArrayArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + vector RangeArrayArgIntermediate; + TranslateVector(RangeArrayArgCli, RangeArrayArgIntermediate, TranslateRangeTupleToInteropRangePointer); + unique_ptr RangeArrayArgUniquePtr = CreateInteropArray(RangeArrayArgIntermediate); + InteropArray* RangeArrayArgInterop = RangeArrayArgUniquePtr.get(); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseRangeArrayArg( + RangeArrayArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp new file mode 100644 index 00000000000..516888b83b0 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Result type. +const char InteropResultZeroAsChar = 0x0; +const char InteropResultOneAsChar = 0x1; +map ResultAsCharMap{ + {"0", InteropResultZeroAsChar}, + {"Zero", InteropResultZeroAsChar}, + {"1", InteropResultOneAsChar}, + {"One", InteropResultOneAsChar} +}; + +extern "C" void UseResultArg( + char ResultArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + char ResultArgCli; + ResultArgCli = InteropResultZeroAsChar; + app.add_option("--ResultArg", ResultArgCli, "Option to provide a value for the ResultArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(ResultAsCharMap, CLI::ignore_case)); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + char ResultArgInterop = ResultArgCli; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseResultArg( + ResultArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp new file mode 100644 index 00000000000..2f5f36c09e1 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp @@ -0,0 +1,112 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// Auxiliary functions for interop with Q# Result type. +const char InteropResultZeroAsChar = 0x0; +const char InteropResultOneAsChar = 0x1; +map ResultAsCharMap{ + {"0", InteropResultZeroAsChar}, + {"Zero", InteropResultZeroAsChar}, + {"1", InteropResultOneAsChar}, + {"One", InteropResultOneAsChar} +}; + +extern "C" void UseResultArrayArg( + InteropArray* ResultArrayArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + vector ResultArrayArgCli; + app.add_option("--ResultArrayArg", ResultArrayArgCli, "Option to provide a value for the ResultArrayArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(ResultAsCharMap, CLI::ignore_case)); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + unique_ptr ResultArrayArgUniquePtr = CreateInteropArray(ResultArrayArgCli); + InteropArray* ResultArrayArgInterop = ResultArrayArgUniquePtr.get(); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseResultArrayArg( + ResultArrayArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp new file mode 100644 index 00000000000..bdfc37c878b --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# String type. +const char* TranslateStringToCharBuffer(string& s) +{ + return s.c_str(); +} + +extern "C" void UseStringArg( + const char* StringArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + string StringArgCli; + app.add_option("--StringArg", StringArgCli, "Option to provide a value for the StringArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + const char* StringArgInterop = TranslateStringToCharBuffer(StringArgCli); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseStringArg( + StringArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj index 55ffaa29bd4..cd9a3d60202 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj @@ -17,4 +17,52 @@ + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs new file mode 100644 index 00000000000..1ed263c814d --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public interface IQirSimulatorInitializer + { + public string Generate(); + + public IList Headers { get; } + + public IList LinkLibraries { get; } + } +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs new file mode 100644 index 00000000000..807f959095b --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -0,0 +1,576 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 16.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + using System.IO; + using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; + using System; + + /// + /// Class to produce the template output + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public partial class QirCppDriver : QirCppDriverBase + { + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write(@"//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include ""CLI11.hpp"" + +#include ""QirRuntime.hpp"" +#include ""QirContext.hpp"" + +"); + foreach (var header in SimulatorInitializer.Headers) { + this.Write("#include \""); + this.Write(this.ToStringHelper.ToStringWithCulture(header)); + this.Write("\"\r\n"); + } + this.Write("\r\nusing namespace Microsoft::Quantum;\r\nusing namespace std;\r\n"); + if (EntryPoint.ContainsArgumentType(DataType.ArrayType)) { + this.Write(@" +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} +"); + } + if (EntryPoint.ContainsArgumentType(DataType.RangeType) || EntryPoint.ContainsArrayType(DataType.RangeType)) { + this.Write(@" +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} +"); + } + if (EntryPoint.ContainsArrayType(DataType.RangeType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Range[] type\r\ntemplate\r\n" + + "void FreePointerVector(vector& v)\r\n{\r\n for (auto p : v)\r\n {\r\n d" + + "elete p;\r\n }\r\n}\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.BoolType) || EntryPoint.ContainsArrayType(DataType.BoolType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Bool type.\r\nconst char InteropFalseA" + + "sChar = 0x0;\r\nconst char InteropTrueAsChar = 0x1;\r\nmap "); + this.Write(this.ToStringHelper.ToStringWithCulture(QirCppInterop.CliOptionTransformerMapName(DataType.BoolType))); + this.Write("{\r\n {\"0\", InteropFalseAsChar},\r\n {\"false\", InteropFalseAsChar},\r\n {\"1\", " + + "InteropTrueAsChar},\r\n {\"true\", InteropTrueAsChar}\r\n};\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.PauliType) || EntryPoint.ContainsArrayType(DataType.PauliType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Pauli type.\r\nmap "); + this.Write(this.ToStringHelper.ToStringWithCulture(QirCppInterop.CliOptionTransformerMapName(DataType.PauliType))); + this.Write("{\r\n {\"PauliI\", PauliId::PauliId_I},\r\n {\"PauliX\", PauliId::PauliId_X},\r\n " + + "{\"PauliY\", PauliId::PauliId_Y},\r\n {\"PauliZ\", PauliId::PauliId_Z}\r\n};\r\n\r\nchar " + + "TranslatePauliToChar(PauliId& pauli)\r\n{\r\n return static_cast(pauli);\r\n}" + + "\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.ResultType) || EntryPoint.ContainsArrayType(DataType.ResultType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Result type.\r\nconst char InteropResu" + + "ltZeroAsChar = 0x0;\r\nconst char InteropResultOneAsChar = 0x1;\r\nmap" + + " "); + this.Write(this.ToStringHelper.ToStringWithCulture(QirCppInterop.CliOptionTransformerMapName(DataType.ResultType))); + this.Write("{\r\n {\"0\", InteropResultZeroAsChar},\r\n {\"Zero\", InteropResultZeroAsChar},\r\n " + + " {\"1\", InteropResultOneAsChar},\r\n {\"One\", InteropResultOneAsChar}\r\n};\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.StringType) || EntryPoint.ContainsArrayType(DataType.StringType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# String type.\r\nconst char* TranslateS" + + "tringToCharBuffer(string& s)\r\n{\r\n return s.c_str();\r\n}\r\n"); + } + this.Write("\r\nextern \"C\" void "); + this.Write(this.ToStringHelper.ToStringWithCulture(EntryPoint.Name)); + this.Write("(\r\n"); + for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.Name)); + this.Write(this.ToStringHelper.ToStringWithCulture((isLastArg) ? "" : ",")); + this.Write("\r\n"); + } + this.Write("); // QIR interop function.\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n CLI::App " + + "app(\"QIR Standalone Entry Point\");\r\n\r\n // Initialize simulator.\r\n"); + var initializerReader = new StringReader(SimulatorInitializer.Generate()); + string line; + while((line = initializerReader.ReadLine()) != null) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(line)); + this.Write("\r\n"); + } + this.Write(@" + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + ""--simulation-output"", + simulationOutputFile, + ""File where the output produced during the simulation is written""); + +"); + if (EntryPoint.Parameters.Count > 0) { + this.Write(" // Add a command line option for each entry-point parameter.\r\n"); + } + foreach (var arg in EntryPoint.Parameters) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(";\r\n"); + if (arg.CliOptionVariableDefaultValue() != null) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableDefaultValue())); + this.Write(";\r\n"); + } + this.Write(" app.add_option(\""); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionName())); + this.Write("\", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(", \""); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionDescription())); + this.Write("\")\r\n ->required()"); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionTransformerMapName() != null ? "" : ";")); + this.Write("\r\n"); + if (arg.CliOptionTransformerMapName() != null) { + this.Write(" ->transform(CLI::CheckedTransformer("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionTransformerMapName())); + this.Write(", CLI::ignore_case));\r\n"); + } + this.Write("\r\n"); + } + this.Write(" // After all the options have been added, parse arguments from the command li" + + "ne.\r\n CLI11_PARSE(app, argc, argv);\r\n\r\n"); + if (EntryPoint.Parameters.Count > 0) { + this.Write(" // Cast parsed arguments to its interop types.\r\n"); + } + foreach (var arg in EntryPoint.Parameters) { + if (arg.Type == DataType.ArrayType) { + var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); + if (arrayInteropTranslator == null) { + this.Write(" unique_ptr "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName())); + this.Write(" = CreateInteropArray("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(");\r\n"); + } + else { + var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); + var arrayInteropType = QirCppInterop.InteropType(arg.ArrayType); + this.Write(" vector<"); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayInteropType)); + this.Write("> "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); + this.Write(";\r\n TranslateVector<"); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayCliOptionType)); + this.Write(", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayInteropType)); + this.Write(">("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); + this.Write(", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayInteropTranslator)); + this.Write(");\r\n unique_ptr "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName())); + this.Write(" = CreateInteropArray("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); + this.Write(");\r\n"); + } + this.Write(" InteropArray* "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName())); + this.Write(".get();\r\n"); + } + else { + var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); + if (interopTranslator == null) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(";\r\n"); + } + else { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(interopTranslator)); + this.Write("("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(");\r\n"); + } + } + this.Write("\r\n"); + } + this.Write(@" // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + "); + this.Write(this.ToStringHelper.ToStringWithCulture(EntryPoint.Name)); + this.Write("(\r\n"); + for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(this.ToStringHelper.ToStringWithCulture((isLastArg) ? "" : ",")); + this.Write("\r\n"); + } + this.Write(" );\r\n\r\n // Flush the output of the simulation.\r\n simulatorOutputStream->" + + "flush();\r\n if (simulationOutputFileStream.is_open())\r\n {\r\n simulati" + + "onOutputFileStream.close();\r\n }\r\n\r\n return 0;\r\n}\r\n"); + return this.GenerationEnvironment.ToString(); + } + } + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public class QirCppDriverBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion + } + #endregion +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt new file mode 100644 index 00000000000..a99fa9716e7 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -0,0 +1,246 @@ +<#@ template language="C#" linePragmas="false" #> +<#@ import namespace="System.IO" #> +<#@ import namespace="Microsoft.Quantum.QsCompiler.BondSchemas.Execution" #> +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +<# foreach (var header in SimulatorInitializer.Headers) { #> +#include "<#= header #>" +<# } #> + +using namespace Microsoft::Quantum; +using namespace std; +<# if (EntryPoint.ContainsArgumentType(DataType.ArrayType)) { #> + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.RangeType) || EntryPoint.ContainsArrayType(DataType.RangeType)) { #> + +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} +<# } #> +<# if (EntryPoint.ContainsArrayType(DataType.RangeType)) { #> + +// Auxiliary functions for interop with Q# Range[] type +template +void FreePointerVector(vector& v) +{ + for (auto p : v) + { + delete p; + } +} +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.BoolType) || EntryPoint.ContainsArrayType(DataType.BoolType)) { #> + +// Auxiliary functions for interop with Q# Bool type. +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map <#= QirCppInterop.CliOptionTransformerMapName(DataType.BoolType) #>{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar} +}; +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.PauliType) || EntryPoint.ContainsArrayType(DataType.PauliType)) { #> + +// Auxiliary functions for interop with Q# Pauli type. +map <#= QirCppInterop.CliOptionTransformerMapName(DataType.PauliType) #>{ + {"PauliI", PauliId::PauliId_I}, + {"PauliX", PauliId::PauliId_X}, + {"PauliY", PauliId::PauliId_Y}, + {"PauliZ", PauliId::PauliId_Z} +}; + +char TranslatePauliToChar(PauliId& pauli) +{ + return static_cast(pauli); +} +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.ResultType) || EntryPoint.ContainsArrayType(DataType.ResultType)) { #> + +// Auxiliary functions for interop with Q# Result type. +const char InteropResultZeroAsChar = 0x0; +const char InteropResultOneAsChar = 0x1; +map <#= QirCppInterop.CliOptionTransformerMapName(DataType.ResultType) #>{ + {"0", InteropResultZeroAsChar}, + {"Zero", InteropResultZeroAsChar}, + {"1", InteropResultOneAsChar}, + {"One", InteropResultOneAsChar} +}; +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.StringType) || EntryPoint.ContainsArrayType(DataType.StringType)) { #> + +// Auxiliary functions for interop with Q# String type. +const char* TranslateStringToCharBuffer(string& s) +{ + return s.c_str(); +} +<# } #> + +extern "C" void <#= EntryPoint.Name #>( +<# for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); #> + <#= arg.InteropType() #> <#= arg.Name #><#= (isLastArg) ? "" : "," #> +<# } #> +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. +<# var initializerReader = new StringReader(SimulatorInitializer.Generate()); + string line; + while((line = initializerReader.ReadLine()) != null) { #> + <#= line #> +<# } #> + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + +<# if (EntryPoint.Parameters.Count > 0) { #> + // Add a command line option for each entry-point parameter. +<# } #> +<# foreach (var arg in EntryPoint.Parameters) { #> + <#= arg.CliOptionType() #> <#= arg.CliOptionVariableName() #>; +<# if (arg.CliOptionVariableDefaultValue() != null) { #> + <#= arg.CliOptionVariableName() #> = <#= arg.CliOptionVariableDefaultValue() #>; +<# } #> + app.add_option("<#= arg.CliOptionName() #>", <#= arg.CliOptionVariableName() #>, "<#= arg.CliOptionDescription() #>") + ->required()<#= arg.CliOptionTransformerMapName() != null ? "" : ";" #> +<# if (arg.CliOptionTransformerMapName() != null) { #> + ->transform(CLI::CheckedTransformer(<#= arg.CliOptionTransformerMapName() #>, CLI::ignore_case)); +<# } #> + +<# } #> + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + +<# if (EntryPoint.Parameters.Count > 0) { #> + // Cast parsed arguments to its interop types. +<# } #> +<# foreach (var arg in EntryPoint.Parameters) { #> +<# if (arg.Type == DataType.ArrayType) { + var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); #> +<# if (arrayInteropTranslator == null) { #> + unique_ptr <#= arg.UniquePtrVariableName() #> = CreateInteropArray(<#= arg.CliOptionVariableName() #>); +<# } #> +<# else { + var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); + var arrayInteropType = QirCppInterop.InteropType(arg.ArrayType); #> + vector<<#= arrayInteropType #>> <#= arg.IntermediateVariableName() #>; + TranslateVector<<#= arrayCliOptionType #>, <#= arrayInteropType #>>(<#= arg.CliOptionVariableName() #>, <#= arg.IntermediateVariableName() #>, <#= arrayInteropTranslator #>); + unique_ptr <#= arg.UniquePtrVariableName() #> = CreateInteropArray(<#= arg.IntermediateVariableName() #>); +<# } #> + InteropArray* <#= arg.InteropVariableName() #> = <#= arg.UniquePtrVariableName() #>.get(); +<# } #> +<# else { + var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); #> +<# if (interopTranslator == null) { #> + <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = <#= arg.CliOptionVariableName() #>; +<# } #> +<# else { #> + <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = <#= interopTranslator #>(<#= arg.CliOptionVariableName() #>); +<# } #> +<# } #> + +<# } #> + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + <#= EntryPoint.Name #>( +<# for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); #> + <#= arg.InteropVariableName() #><#= (isLastArg) ? "" : "," #> +<# } #> + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs new file mode 100644 index 00000000000..7c05fba2b3e --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public partial class QirCppDriver + { + public readonly EntryPointOperation EntryPoint; + + public readonly IQirSimulatorInitializer SimulatorInitializer; + + public QirCppDriver(EntryPointOperation entryPoint, IQirSimulatorInitializer simulatorInitializer) + { + EntryPoint = entryPoint; + SimulatorInitializer = simulatorInitializer; + } + } +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs new file mode 100644 index 00000000000..a9a8233464b --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public class QirCppDriverGenerator : IQirDriverGenerator + { + private readonly IQirSimulatorInitializer SimulatorInitalizer; + + private delegate string StringConversion(ArgumentValue value); + + public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) + { + SimulatorInitalizer = simulatorInitializer; + } + + public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream) + { + var qirCppDriver = new QirCppDriver(entryPointOperation, SimulatorInitalizer); + var cppSource = qirCppDriver.TransformText(); + await stream.WriteAsync(Encoding.UTF8.GetBytes(cppSource)); + await stream.FlushAsync(); + stream.Position = 0; + } + + public string GetCommandLineArguments(ExecutionInformation executionInformation) + { + // Sort arguments by position. + var sortedArguments = executionInformation.EntryPoint.Parameters.OrderBy(arg => arg.Position); + var argumentBuilder = new StringBuilder(); + foreach (var arg in sortedArguments) + { + if (argumentBuilder.Length != 0) + { + argumentBuilder.Append(' '); + } + + argumentBuilder.Append($"--{arg.Name}").Append(' ').Append(GetArgumentValueString(arg, executionInformation.ArgumentValues[arg.Name])); + } + + return argumentBuilder.ToString(); + } + + private static string GetArgumentValueString(Parameter argument, ArgumentValue argumentValue) + { + // Today, only the first argument value in the array will be used. + return argument.Type switch + { + DataType.BoolType => GetBoolValueString(argumentValue), + DataType.DoubleType => GetDoubleValueString(argumentValue), + DataType.IntegerType => GetIntegerValueString(argumentValue), + DataType.PauliType => GetPauliValueString(argumentValue), + DataType.RangeType => GetRangeValueString(argumentValue), + DataType.ResultType => GetResultValueString(argumentValue), + DataType.StringType => GetStringValueString(argumentValue), + DataType.ArrayType => GetArrayValueString(argument.ArrayType, argumentValue.Array), + _ => throw new ArgumentException($"Unsupported data type {argument.Type}") + }; + } + + private static string GetArrayValueString(DataType? arrayType, IList arrayValue) + { + static string ConvertArray(IList list, StringConversion conversion) => + string.Join(' ', list.Select(item => conversion.Invoke(item))); + + return arrayType switch + { + DataType.BoolType => ConvertArray(arrayValue, GetBoolValueString), + DataType.DoubleType => ConvertArray(arrayValue, GetDoubleValueString), + DataType.IntegerType => ConvertArray(arrayValue, GetIntegerValueString), + DataType.PauliType => ConvertArray(arrayValue, GetPauliValueString), + DataType.RangeType => ConvertArray(arrayValue, GetRangeValueString), + DataType.ResultType => ConvertArray(arrayValue, GetResultValueString), + DataType.StringType => ConvertArray(arrayValue, GetStringValueString), + _ => throw new ArgumentException($"Unsupported array data type {arrayType}") + }; + } + + private static string GetResultValueString(ArgumentValue value) + { + if (value?.Result == null) + { + throw new ArgumentNullException("Cannot convert null result value to string."); + } + return value.Result == ResultValue.One ? "1" : "0"; + } + + private static string GetRangeValueString(ArgumentValue value) + { + if (value?.Range == null) + { + throw new ArgumentNullException("Cannot convert null range value to string."); + } + var rangeValue = value.Range; + return $"{rangeValue.Start} {rangeValue.Step} {rangeValue.End}"; + } + + private static string GetStringValueString(ArgumentValue value) + { + if (value?.String == null) + { + throw new ArgumentNullException("Cannot convert null string value to string."); + } + + return $"\"{value.String}\""; + } + + private static string GetBoolValueString(ArgumentValue value) + { + if (value?.Bool == null) + { + throw new ArgumentNullException("Cannot convert null bool value to string."); + } + + return value.Bool.ToString().ToLower(); + } + + private static string GetPauliValueString(ArgumentValue value) + { + if (value?.Pauli == null) + { + throw new ArgumentNullException("Cannot convert null pauli value to string."); + } + + return value.Pauli.ToString().ToLower(); + } + + private static string GetDoubleValueString(ArgumentValue value) + { + if (value?.Double == null) + { + throw new ArgumentNullException("Cannot convert null double value to string."); + } + + return value.Double.ToString().ToLower(); + } + + private static string GetIntegerValueString(ArgumentValue value) + { + if (value?.Integer == null) + { + throw new ArgumentNullException("Cannot convert null integer value to string."); + } + + return value.Integer.ToString().ToLower(); + } + } +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs new file mode 100644 index 00000000000..44939338006 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs @@ -0,0 +1,302 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 16.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + using System; + + /// + /// Class to produce the template output + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public partial class QirCppFullStateSimulatorInitializer : QirCppFullStateSimulatorInitializerBase + { + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write("unique_ptr sim = CreateFullstateSimulator();\r\nQirContextScope qir" + + "ctx(sim.get(), false /*trackAllocatedObjects*/);"); + return this.GenerationEnvironment.ToString(); + } + } + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public class QirCppFullStateSimulatorInitializerBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion + } + #endregion +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt new file mode 100644 index 00000000000..275994cf4af --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt @@ -0,0 +1,3 @@ +<#@ template language="C#" linePragmas="false" #> +unique_ptr sim = CreateFullstateSimulator(); +QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); \ No newline at end of file diff --git a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs new file mode 100644 index 00000000000..b4da38b9676 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; + +#nullable enable + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + internal static class QirCppInterop + { + public static string? CliOptionTransformerMapName(DataType? dataType) => + dataType switch + { + DataType.BoolType => "BoolAsCharMap", + DataType.IntegerType => null, + DataType.DoubleType => null, + DataType.PauliType => "PauliMap", + DataType.RangeType => null, + DataType.ResultType => "ResultAsCharMap", + DataType.StringType => null, + DataType.ArrayType => null, + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + + public static string CliOptionType(DataType? dataType) => + dataType switch + { + DataType.BoolType => "char", + DataType.IntegerType => "int64_t", + DataType.DoubleType => "double_t", + DataType.PauliType => "PauliId", + DataType.RangeType => "RangeTuple", + DataType.ResultType => "char", + DataType.StringType => "string", + DataType.ArrayType => throw new NotSupportedException($"{DataType.ArrayType} does not match to a specific CLI option variable type"), + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + + public static string? CliOptionTypeToInteropTypeTranslator(DataType? dataType) => + dataType switch + { + DataType.BoolType => null, + DataType.IntegerType => null, + DataType.DoubleType => null, + DataType.PauliType => "TranslatePauliToChar", + DataType.RangeType => "TranslateRangeTupleToInteropRangePointer", + DataType.ResultType => null, + DataType.StringType => "TranslateStringToCharBuffer", + DataType.ArrayType => throw new NotSupportedException($"{DataType.ArrayType} does not match to a specific CLI option variable type"), + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + + public static string? CliOptionVariableDefaultValue(DataType? dataType) => + dataType switch + { + DataType.BoolType => "InteropFalseAsChar", + DataType.IntegerType => "0", + DataType.DoubleType => "0.0", + DataType.PauliType => "PauliId::PauliId_I", + DataType.RangeType => null, + DataType.ResultType => "InteropResultZeroAsChar", + DataType.StringType => null, + DataType.ArrayType => null, + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + + public static string InteropType(DataType? dataType) => + dataType switch + { + DataType.BoolType => "char", + DataType.IntegerType => "int64_t", + DataType.DoubleType => "double_t", + DataType.PauliType => "char", + DataType.RangeType => "InteropRange*", + DataType.ResultType => "char", + DataType.StringType => "const char*", + DataType.ArrayType => "InteropArray*", + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + } + + internal static class ArgumentCppExtensions + { + public static string CliOptionDescription(this Parameter @this) => + $"Option to provide a value for the {@this.Name} parameter"; + + public static string CliOptionName(this Parameter @this) + { + if (String.IsNullOrEmpty(@this.Name)) + { + throw new InvalidOperationException($"Invalid parameter name '{@this.Name}'"); + } + + return @this.Name.Length == 1 ? $"-{@this.Name}" : $"--{@this.Name}"; + } + + public static string? CliOptionTransformerMapName(this Parameter @this) => + @this.Type switch + { + DataType.ArrayType => QirCppInterop.CliOptionTransformerMapName(@this.ArrayType), + _ => QirCppInterop.CliOptionTransformerMapName(@this.Type) + }; + + public static string CliOptionType(this Parameter @this) => + @this.Type switch + { + DataType.ArrayType => $"vector<{QirCppInterop.CliOptionType(@this.ArrayType)}>", + _ => QirCppInterop.CliOptionType(@this.Type) + }; + + public static string CliOptionVariableName(this Parameter @this) => $"{@this.Name}Cli"; + + public static string? CliOptionVariableDefaultValue(this Parameter @this) => + QirCppInterop.CliOptionVariableDefaultValue(@this.Type); + + public static string IntermediateVariableName(this Parameter @this) => $"{@this.Name}Intermediate"; + + public static string InteropVariableName(this Parameter @this) => $"{@this.Name}Interop"; + + public static string InteropType(this Parameter @this) => QirCppInterop.InteropType(@this.Type); + + public static string UniquePtrVariableName(this Parameter @this) => $"{@this.Name}UniquePtr"; + } + + internal static class EntryPointOperationCppExtension + { + public static bool ContainsArgumentType(this EntryPointOperation @this, DataType type) => + @this.Parameters.Where(arg => arg.Type == type).Any(); + + public static bool ContainsArrayType(this EntryPointOperation @this, DataType type) => + @this.Parameters.Where(arg => arg.ArrayType == type).Any(); + } +} diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs index 20ff9bb5491..8f98b4a80f9 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs @@ -10,14 +10,16 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public class QirFullStateDriverGenerator: IQirDriverGenerator { - public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) + private readonly QirCppDriverGenerator DriverGenerator; + public QirFullStateDriverGenerator() { - await Task.Run(() => QirDriverGeneration.GenerateQirDriverCpp(entryPoint, stream)); + DriverGenerator = new QirCppDriverGenerator(new QirFullStateSimulatorInitializer()); } - public string GetCommandLineArguments(ExecutionInformation executionInformation) - { - return QirDriverGeneration.GenerateCommandLineArguments(executionInformation); - } + public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) => + await DriverGenerator.GenerateAsync(entryPoint, stream); + + public string GetCommandLineArguments(ExecutionInformation executionInformation) => + DriverGenerator.GetCommandLineArguments(executionInformation); } } diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs new file mode 100644 index 00000000000..12bea984368 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public class QirFullStateSimulatorInitializer : IQirSimulatorInitializer + { + public string Generate() => new QirCppFullStateSimulatorInitializer().TransformText(); + + public IList Headers => new List { + "SimFactory.hpp" + }; + + public IList LinkLibraries => new List(); + } +} diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index f89615e8dc7..323a5fa3a1b 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -13,5 +13,33 @@ - + + + + TextTemplatingFilePreprocessor + QirCppDriver.cs + + + TextTemplatingFilePreprocessor + QirCppFullStateSimulatorInitializer.cs + + + + + + + + + + True + True + QirCppDriver.tt + + + False + True + QirCppFullStateSimulatorInitializer.tt + + + From 2357512c23fd0ff4b3a4b582a0df7fd0d31eef63 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Mon, 3 May 2021 10:05:49 -0700 Subject: [PATCH 063/145] Fix test script --- src/Qir/Controller/test-qir-controller.ps1 | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index c9f20f54250..c97499f0d4f 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -57,9 +57,9 @@ foreach ( $path in $libraryPaths ) # Go through each input file in the test cases folder. Get-ChildItem $testCasesFolder -Filter *.in | Foreach-Object { -Write-Host $_.BaseName # Get the paths to the output and error files to pass to the QIR controller. + $testPassed = $True $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile --includeDirectory $includeDirectory --libraryDirectory $libraryDirectory @@ -77,13 +77,10 @@ Write-Host $_.BaseName Write-Host $expectedOutput Write-Host "##[info]Actual output:" Write-Host $actualOutput - $script:all_ok = $False - } - else { - Write-Host "##[info]Test case '$($_.BaseName)' passed" + $testPassed = $False } } - else { + if ((Test-Path $expectedErrorFile)) { $expectedError = Get-Content -Path $expectedErrorFile -Raw $actualError = Get-Content -Path $errorFile -Raw if (-not ($expectedError -ceq $actualError)) { @@ -92,12 +89,16 @@ Write-Host $_.BaseName Write-Host $expectedError Write-Host "##[info]Actual error:" Write-Host $actualError - $script:all_ok = $False - } - else { - Write-Host "##[info]Test case '$($_.BaseName)' passed" + $testPassed = $False } } + + if ($testPassed) { + Write-Host "##[info]Test case '$($_.BaseName)' passed" + } + else { + $script:all_ok = $False + } } if (-not $all_ok) { From f368a230776f7b85b8822e0587d473f60fdac2a8 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 11:03:47 -0700 Subject: [PATCH 064/145] Add Azure.QirSubmitter method --- src/Simulation/EntryPointDriver/Azure.cs | 75 ++++++++++++++++-------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 38820f478a7..5953ccf5938 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Microsoft.Azure.Quantum.Exceptions; using Microsoft.Azure.Quantum; +using Microsoft.Azure.Quantum.Exceptions; using static Microsoft.Quantum.EntryPointDriver.Driver; using Microsoft.Quantum.EntryPointDriver.Mock; using Microsoft.Quantum.Runtime; @@ -37,14 +37,15 @@ public static async Task SubmitQSharp( { if (settings.Verbose) { + Console.WriteLine("Submitting Q# entry point."); Console.Write(settings + Environment.NewLine + Environment.NewLine); } - switch (CreateMachine(settings)) + switch (QSharpMachine(settings)) { case null: DisplayWithColor( - ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' was not recognized."); + ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); return 1; case var machine: return settings.DryRun @@ -64,11 +65,29 @@ public static async Task SubmitQSharp( public static async Task SubmitQir( AzureSettings settings, Stream qir, string entryPoint, IReadOnlyList arguments) { - // TODO - var submitter = new NoOpQirSubmitter(); - var job = await submitter.SubmitAsync(qir, entryPoint, arguments); - DisplayJob(job, settings.Output); - return 0; + if (settings.Verbose) + { + Console.WriteLine("Submitting QIR entry point."); + Console.Write(settings + Environment.NewLine + Environment.NewLine); + } + + switch (QirSubmitter(settings)) + { + case null: + DisplayWithColor( + ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); + return 1; + case var submitter: + if (settings.DryRun) + { + // TODO + Console.WriteLine("Dry run is not supported for QIR submissions."); + } + + var job = await submitter.SubmitAsync(qir, entryPoint, arguments); + DisplayJob(job, settings.Output); + return 0; + } } /// @@ -86,26 +105,25 @@ private static async Task SubmitJob( { try { - var job = await machine.SubmitAsync(info, input, new SubmissionContext - { - FriendlyName = settings.JobName, - Shots = settings.Shots - }); + var job = await machine.SubmitAsync( + info, + input, + new SubmissionContext { FriendlyName = settings.JobName, Shots = settings.Shots }); + DisplayJob(job, settings.Output); return 0; } catch (AzureQuantumException ex) { DisplayError( - "Something went wrong when submitting the program to the Azure Quantum service.", + "Something went wrong when submitting the program to the Azure Quantum service.", ex.Message); return 1; } catch (QuantumProcessorTranslationException ex) { DisplayError( - "Something went wrong when performing translation to the intermediate representation used by the " + - "target quantum machine.", + "Something went wrong when performing translation to the intermediate representation used by the target quantum machine.", ex.Message); return 1; } @@ -126,8 +144,7 @@ private static int Validate(IQuantumMachine machine, EntryPointInfo - /// Creates a quantum machine based on the Azure Quantum submission settings. + /// Returns a Q# machine. /// /// The Azure Quantum submission settings. - /// Thrown if .Target is null. /// A quantum machine. - private static IQuantumMachine? CreateMachine(AzureSettings settings) => settings.Target switch + /// .Target is null. + private static IQuantumMachine? QSharpMachine(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null."), NoOpQuantumMachine.TargetId => new NoOpQuantumMachine(), @@ -193,6 +209,19 @@ private static void DisplayError(string summary, string message) _ => QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage) }; + /// + /// Returns a QIR submitter. + /// + /// The Azure Quantum submission settings. + /// A QIR submitter. + /// .Target is null. + private static IQirSubmitter? QirSubmitter(AzureSettings settings) => settings.Target switch + { + null => throw new ArgumentNullException(nameof(settings), "Target is null"), + NoOpQirSubmitter.TargetId => new NoOpQirSubmitter(), + _ => null // TODO + }; + /// /// The quantum machine submission context. /// From 99d492e62d28bcf51ed3a23d7976f8d0d2be43da Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 11:07:12 -0700 Subject: [PATCH 065/145] Remove dry run message --- src/Simulation/EntryPointDriver/Azure.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 5953ccf5938..3dd24804a25 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -78,12 +78,6 @@ public static async Task SubmitQir( ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); return 1; case var submitter: - if (settings.DryRun) - { - // TODO - Console.WriteLine("Dry run is not supported for QIR submissions."); - } - var job = await submitter.SubmitAsync(qir, entryPoint, arguments); DisplayJob(job, settings.Output); return 0; From 9334d115ec5143fb492319a81a8d8bdf9e2e373d Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 11:39:02 -0700 Subject: [PATCH 066/145] Add new line before verbose settings --- src/Simulation/EntryPointDriver/Azure.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 3dd24804a25..5807268b8db 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -37,8 +37,8 @@ public static async Task SubmitQSharp( { if (settings.Verbose) { - Console.WriteLine("Submitting Q# entry point."); - Console.Write(settings + Environment.NewLine + Environment.NewLine); + Console.WriteLine("Submitting Q# entry point." + Environment.NewLine); + Console.WriteLine(settings + Environment.NewLine); } switch (QSharpMachine(settings)) @@ -67,8 +67,8 @@ public static async Task SubmitQir( { if (settings.Verbose) { - Console.WriteLine("Submitting QIR entry point."); - Console.Write(settings + Environment.NewLine + Environment.NewLine); + Console.WriteLine("Submitting QIR entry point." + Environment.NewLine); + Console.WriteLine(settings + Environment.NewLine); } switch (QirSubmitter(settings)) From 11aef1876a64be6cdd6de4cc74cd043dcb1bf531 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 12:23:26 -0700 Subject: [PATCH 067/145] Add SubmitsQir test --- src/Simulation/Simulators.Tests/CoreTests.cs | 69 +++++++++++++++++-- .../Tests.Microsoft.Quantum.Simulators.csproj | 1 + 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 2a337c041f7..01b17e5eaa1 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -1,23 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Text; using Microsoft.Quantum.Core; using Microsoft.Quantum.QsCompiler; using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators; using Microsoft.Quantum.Tests.CoreOperations; - +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; using Xunit; using Xunit.Abstractions; namespace Microsoft.Quantum.Simulation.Simulators.Tests { + using Environment = System.Environment; + public class CoreTests { private readonly ITestOutputHelper output; @@ -58,6 +59,62 @@ public void BasicExecutionTargetedExe() Assert.Equal("TargetedExe", output.ToString().Trim()); } + [Fact] + public void SubmitsQir() + { + var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var assembly = Path.Combine(directory!, "QirExe.dll"); + var args = string.Join( + ' ', + assembly, + "submit", + "--xs", + "0", + "1", + "2", + "-y", + "3", + "-z", + "4", + "--subscription", + "foo", + "--resource-group", + "bar", + "--workspace", + "baz", + "--target", + "test.noop", + "--verbose"); + + ProcessRunner.Run("dotnet", args, out var output, out var error, out var status, out var ex); + + Assert.Null(ex); + Assert.Equal(0, status); + Assert.Empty(error.ToString()); + Assert.Equal( + string.Join( + Environment.NewLine, + "Submitting QIR entry point.", + "", + "Subscription: foo", + "Resource Group: bar", + "Workspace: baz", + "Target: test.noop", + "Storage: ", + "AAD Token: ", + "Base URI: ", + "Location: ", + "Job Name: ", + "Shots: 500", + "Output: FriendlyUri", + "Dry Run: False", + "Verbose: True", + "", + "https://www.example.com/00000000-0000-0000-0000-0000000000000", + ""), + output.ToString()); + } + [Fact] public void Borrowing() { diff --git a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj index ac3080e9409..74f96b4f89b 100644 --- a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj @@ -17,6 +17,7 @@ false + From ea111910f16e45b764431a25323a0d5dfb956cd3 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 13:24:14 -0700 Subject: [PATCH 068/145] Simplify test project execution --- src/Simulation/Simulators.Tests/CoreTests.cs | 4 ++-- .../TestProjects/QSharpExe/QSharpExe.csproj | 17 ------------- .../TargetedExe/TargetedExe.csproj | 17 ------------- .../Tests.Microsoft.Quantum.Simulators.csproj | 24 ++++--------------- 4 files changed, 7 insertions(+), 55 deletions(-) diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 01b17e5eaa1..638150c41bb 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -32,7 +32,7 @@ public CoreTests(ITestOutputHelper output) public void BasicExecution() { var asmPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var exe = Path.Combine(asmPath, "TestExe", "QSharpExe.dll"); + var exe = Path.Combine(asmPath!, "QSharpExe.dll"); ProcessRunner.Run("dotnet", exe, out var _, out StringBuilder error, out int exitCode, out Exception ex); Assert.Null(ex); @@ -49,7 +49,7 @@ public void BasicExecution() public void BasicExecutionTargetedExe() { var asmPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var exe = Path.Combine(asmPath, "TestTargetedExe", "TargetedExe.dll"); + var exe = Path.Combine(asmPath!, "TargetedExe", "TargetedExe.dll"); ProcessRunner.Run("dotnet", exe, out StringBuilder output, out StringBuilder error, out int exitCode, out Exception ex); diff --git a/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj index 25aca4168f0..4e559bd056b 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj @@ -1,5 +1,4 @@ - Exe netcoreapp3.1 @@ -20,20 +19,4 @@ - - - - <_ExeDir>$(MSBuildThisFileDirectory)built - - - - - - - - <_ExeFiles Include="$(OutputPath)*" /> - - - - diff --git a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj index cf3c8556408..20965292c18 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj @@ -1,5 +1,4 @@ - Exe netcoreapp3.1 @@ -21,20 +20,4 @@ - - - - <_ExeDir>$(MSBuildThisFileDirectory)built - - - - - - - - <_ExeFiles Include="$(OutputPath)*" /> - - - - diff --git a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj index 74f96b4f89b..85d9efe3ae7 100644 --- a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj @@ -1,5 +1,4 @@ - @@ -9,30 +8,17 @@ - - - false - - - false - + + + - - <_ExeDir>$(MSBuildThisFileDirectory)TestProjects\QSharpExe\built\ - <_TargetedExeDir>$(MSBuildThisFileDirectory)TestProjects\TargetedExe\built\ - - <_ExeFiles Include="$(_ExeDir)*" /> - <_TargetedExeFiles Include="$(_TargetedExeDir)*" /> + - - - - + - From 3ef7322e07a10a9e22c16e66435497c9f5e3fdf4 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 13:32:51 -0700 Subject: [PATCH 069/145] Revert unnecessary changes --- src/Simulation/EntryPointDriver/Azure.cs | 30 ++++++++++--------- src/Simulation/EntryPointDriver/Driver.cs | 7 ++--- .../EntryPointDriver/DriverSettings.cs | 18 +++++------ 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 5807268b8db..9d882042dd8 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -117,7 +117,8 @@ private static async Task SubmitJob( catch (QuantumProcessorTranslationException ex) { DisplayError( - "Something went wrong when performing translation to the intermediate representation used by the target quantum machine.", + "Something went wrong when performing translation to the intermediate representation used by the " + + "target quantum machine.", ex.Message); return 1; } @@ -279,14 +280,14 @@ public sealed class AzureSettings public string? AadToken { get; set; } /// - /// The base URI of the Azure Quantum endpoint. If both and - /// properties are not null, is used. + /// The base URI of the Azure Quantum endpoint. + /// If both and properties are not null, takes precedence. /// public Uri? BaseUri { get; set; } /// - /// The location to use with the default Azure Quantum endpoint. If both and - /// properties are not null, is used. + /// The location to use with the default Azure Quantum endpoint. + /// If both and properties are not null, takes precedence. /// public string? Location { get; set; } @@ -321,23 +322,24 @@ public sealed class AzureSettings /// The based on the settings. internal Workspace CreateWorkspace() { - if (!(BaseUri is null)) + if (BaseUri != null) { return AadToken is null ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: BaseUri) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, BaseUri); + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: BaseUri); } - - if (!(Location is null)) + else if (Location != null) { return AadToken is null ? new Workspace(Subscription, ResourceGroup, Workspace, location: NormalizeLocation(Location)) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, NormalizeLocation(Location)); + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, location: NormalizeLocation(Location)); + } + else + { + return AadToken is null + ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: null) + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: null); } - - return AadToken is null - ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: null) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: null); } public override string ToString() => string.Join( diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 374b6a6d8f3..1e4cc04762a 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -493,11 +493,10 @@ protected override string ArgumentDescriptor(IArgument argument) /// /// Struct for housing a command with its validators. /// - private readonly struct CommandWithValidators + private struct CommandWithValidators { - public Command Command { get; } - - public Validators Validators { get; } + public Command Command; + public Validators Validators; /// /// Basic constructor. diff --git a/src/Simulation/EntryPointDriver/DriverSettings.cs b/src/Simulation/EntryPointDriver/DriverSettings.cs index f3f86302800..cd2402b12d8 100644 --- a/src/Simulation/EntryPointDriver/DriverSettings.cs +++ b/src/Simulation/EntryPointDriver/DriverSettings.cs @@ -12,7 +12,7 @@ public sealed class DriverSettings /// /// The aliases for the simulator command-line option. /// - internal ImmutableList SimulatorOptionAliases { get; } + internal IImmutableList SimulatorOptionAliases { get; } /// /// The name of the quantum simulator. @@ -40,10 +40,13 @@ public sealed class DriverSettings internal string DefaultExecutionTarget { get; } /// - /// A function that returns a new instance of the default custom simulator, or throws - /// if the default simulator is not a custom simulator. + /// Creates an instance of the default simulator if it is a custom simulator. /// - internal Func CreateDefaultCustomSimulator { get; } + /// An instance of the default custom simulator. + /// + /// Thrown if the default simulator is not a custom simulator. + /// + internal Func CreateDefaultCustomSimulator; /// /// Creates a new driver settings instance. @@ -54,12 +57,9 @@ public sealed class DriverSettings /// The name of the resources estimator. /// The name of the default simulator to use. /// The name of the default execution target to use. - /// - /// A function that returns a new instance of the default custom simulator, or throws - /// if the default simulator is not a custom simulator. - /// + /// The function for creating a new instance of the default simulator if it is a custom simulator. public DriverSettings( - ImmutableList simulatorOptionAliases, + IImmutableList simulatorOptionAliases, string quantumSimulatorName, string toffoliSimulatorName, string resourcesEstimatorName, From 9e3f7d7d2037732de99096869dd180aecd731c0c Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 13:56:57 -0700 Subject: [PATCH 070/145] Update TargetedExe folder name --- src/Simulation/Simulators.Tests/CoreTests.cs | 2 +- .../Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 638150c41bb..47ec685a459 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -49,7 +49,7 @@ public void BasicExecution() public void BasicExecutionTargetedExe() { var asmPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var exe = Path.Combine(asmPath!, "TargetedExe", "TargetedExe.dll"); + var exe = Path.Combine(asmPath, "TestTargetedExe", "TargetedExe.dll"); ProcessRunner.Run("dotnet", exe, out StringBuilder output, out StringBuilder error, out int exitCode, out Exception ex); diff --git a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj index 85d9efe3ae7..2dc2c33c1f5 100644 --- a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj @@ -19,6 +19,6 @@ - + From fb42cb0ad0c29122b5a16c9840284b892e021bd5 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 14:53:18 -0700 Subject: [PATCH 071/145] Fix test project output copying --- src/Simulation/Simulators.Tests/CoreTests.cs | 6 +++--- .../Tests.Microsoft.Quantum.Simulators.csproj | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 47ec685a459..376f0039ee7 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -32,7 +32,7 @@ public CoreTests(ITestOutputHelper output) public void BasicExecution() { var asmPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var exe = Path.Combine(asmPath!, "QSharpExe.dll"); + var exe = Path.Combine(asmPath!, "TestProjects", "QSharpExe", "QSharpExe.dll"); ProcessRunner.Run("dotnet", exe, out var _, out StringBuilder error, out int exitCode, out Exception ex); Assert.Null(ex); @@ -49,7 +49,7 @@ public void BasicExecution() public void BasicExecutionTargetedExe() { var asmPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var exe = Path.Combine(asmPath, "TestTargetedExe", "TargetedExe.dll"); + var exe = Path.Combine(asmPath!, "TestProjects", "TargetedExe", "TargetedExe.dll"); ProcessRunner.Run("dotnet", exe, out StringBuilder output, out StringBuilder error, out int exitCode, out Exception ex); @@ -63,7 +63,7 @@ public void BasicExecutionTargetedExe() public void SubmitsQir() { var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var assembly = Path.Combine(directory!, "QirExe.dll"); + var assembly = Path.Combine(directory!, "TestProjects", "QirExe", "QirExe.dll"); var args = string.Join( ' ', assembly, diff --git a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj index 2dc2c33c1f5..1dd2049718f 100644 --- a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj @@ -10,15 +10,23 @@ - - + + + + + + + - + + + + From ab4644b9780fe85a201ce44d25689e672a1b445a Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 15:31:35 -0700 Subject: [PATCH 072/145] Update verbose test output --- .../EntryPointDriver.Tests/Tests.fs | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index 43871481a96..9365da3b516 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -557,7 +557,9 @@ let ``Submit can show only the ID`` () = let ``Submit uses default values`` () = let given = test "Returns Unit" given (submitWithNoOpTarget @ ["--verbose"]) - |> yields "Subscription: mySubscription + |> yields "Submitting Q# entry point. + + Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -577,7 +579,9 @@ let ``Submit uses default values`` () = let ``Submit uses default values with default target`` () = let given = testWithTarget "test.noop" "Returns Unit" given (submitWithoutTarget @ ["--verbose"]) - |> yields "Subscription: mySubscription + |> yields "Submitting Q# entry point. + + Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -609,7 +613,9 @@ let ``Submit allows overriding default values`` () = "--shots" "750" ]) - |> yields "Subscription: mySubscription + |> yields "Submitting Q# entry point. + + Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -641,7 +647,9 @@ let ``Submit allows overriding default values with default target`` () = "--shots" "750" ]) - |> yields "Subscription: mySubscription + |> yields "Submitting Q# entry point. + + Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -676,7 +684,9 @@ let ``Submit allows to include --base-uri option when --location is not present` "--base-uri" "myBaseUri" ]) - |> yields "Subscription: mySubscription + |> yields "Submitting Q# entry point. + + Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -700,7 +710,9 @@ let ``Submit allows to include --location option when --base-uri is not present` "--location" "myLocation" ]) - |> yields "Subscription: mySubscription + |> yields "Submitting Q# entry point. + + Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -724,7 +736,9 @@ let ``Submit allows spaces for the --location option`` () = "--location" "My Location" ]) - |> yields "Subscription: mySubscription + |> yields "Submitting Q# entry point. + + Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -760,7 +774,7 @@ let ``Submit requires a positive number of shots`` () = [] let ``Submit fails with unknown target`` () = let given = test "Returns Unit" - given (submitWithoutTarget @ ["--target"; "foo"]) |> failsWith "The target 'foo' was not recognized." + given (submitWithoutTarget @ ["--target"; "foo"]) |> failsWith "The target 'foo' is not recognized." [] let ``Submit supports dry run option`` () = From 923d25f157f4d0fb0b318abc4bc852ab92ce3468 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 15:40:27 -0700 Subject: [PATCH 073/145] Lazy Q#/QIR submit codegen --- src/Simulation/CSharpGeneration/EntryPoint.fs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index ecf4eb9561c..6f77288bf67 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -167,6 +167,7 @@ let private submitMethod context entryPoint parameters = let settingsParamName = "settings" let qsArgs = + lazy [ ident settingsParamName :> ExpressionSyntax ident callableName <|.|> ident "Info" @@ -174,20 +175,22 @@ let private submitMethod context entryPoint parameters = ] let qirStream = + lazy ident "global::System.Reflection.Assembly" <.> (ident "GetExecutingAssembly", []) <.> (ident "GetManifestResourceStream", [literal DotnetCoreDll.QirResourceName]) let qirArgs = + lazy [ ident settingsParamName :> ExpressionSyntax - qirStream + qirStream.Value string entryPoint.FullName |> literal qirArguments parameters (ident parseResultParamName) ] let hasQir = context.assemblyConstants.ContainsKey "QirOutputPath" - let submit = if hasQir then ident "SubmitQir", qirArgs else ident "SubmitQSharp", qsArgs + let submit = if hasQir then ident "SubmitQir", qirArgs.Value else ident "SubmitQSharp", qsArgs.Value arrow_method "System.Threading.Tasks.Task" "Submit" ``<<`` [] ``>>`` ``(`` From 68eea900ebe991f6156bb74caaf19b3bc76fa4b3 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 17:18:01 -0700 Subject: [PATCH 074/145] Fall back to IQuantumMachine if IQirSubmitter not available --- src/Simulation/CSharpGeneration/EntryPoint.fs | 53 ++++--- src/Simulation/EntryPointDriver/Azure.cs | 145 +++++++++++++----- 2 files changed, 135 insertions(+), 63 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 6f77288bf67..26ffa7a378d 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -23,7 +23,7 @@ type private Parameter = let entryPointClassName = "__QsEntryPoint__" /// The namespace containing the non-generated parts of the entry point driver. -let private driverNamespace = "Microsoft.Quantum.EntryPointDriver" +let private driverNamespace = "global::Microsoft.Quantum.EntryPointDriver" /// A sequence of all of the named parameters in the argument tuple and their respective C# and Q# types. let rec private parameters context doc = function @@ -87,7 +87,7 @@ let private createArgument context entryPoint = arrow_method inTypeName "CreateArgument" ``<<`` [] ``>>`` ``(`` [param parseResultName ``of`` (``type`` "System.CommandLine.Parsing.ParseResult")] ``)`` - [``private``] + [``private``; ``static``] (Some (``=>`` argTuple)) /// A tuple of the callable's name, argument type name, and return type name. @@ -162,36 +162,43 @@ let private qirArguments parameters parseResult = /// Generates the Submit method for an entry point class. let private submitMethod context entryPoint parameters = - let callableName, _, _ = callableTypeNames context entryPoint + let callableName, argTypeName, returnTypeName = callableTypeNames context entryPoint let parseResultParamName = "parseResult" let settingsParamName = "settings" - let qsArgs = - lazy - [ - ident settingsParamName :> ExpressionSyntax - ident callableName <|.|> ident "Info" - ident "this" <.> (ident "CreateArgument", [ident parseResultParamName]) - ] + let qsSubmission = + ``new`` (generic (driverNamespace + ".QSharpSubmission") ``<<`` [argTypeName; returnTypeName] ``>>``) + ``(`` + [ + ident callableName <|.|> ident "Info" + invoke (ident "CreateArgument") ``(`` [ident parseResultParamName] ``)`` + ] + ``)`` let qirStream = lazy - ident "global::System.Reflection.Assembly" - <.> (ident "GetExecutingAssembly", []) - <.> (ident "GetManifestResourceStream", [literal DotnetCoreDll.QirResourceName]) + ident "global::System.Reflection.Assembly" + <.> (ident "GetExecutingAssembly", []) + <.> (ident "GetManifestResourceStream", [literal DotnetCoreDll.QirResourceName]) - let qirArgs = + let qirSubmission = lazy + ``new`` (driverNamespace + ".QirSubmission" |> ``type``) + ``(`` + [ + qirStream.Value + string entryPoint.FullName |> literal + ident parseResultParamName |> qirArguments parameters + ] + ``)`` + + let args = [ ident settingsParamName :> ExpressionSyntax - qirStream.Value - string entryPoint.FullName |> literal - qirArguments parameters (ident parseResultParamName) + qsSubmission + if context.assemblyConstants.ContainsKey "QirOutputPath" then qirSubmission.Value else ``null`` ] - let hasQir = context.assemblyConstants.ContainsKey "QirOutputPath" - let submit = if hasQir then ident "SubmitQir", qirArgs.Value else ident "SubmitQSharp", qsArgs.Value - arrow_method "System.Threading.Tasks.Task" "Submit" ``<<`` [] ``>>`` ``(`` [ @@ -200,7 +207,7 @@ let private submitMethod context entryPoint parameters = ] ``)`` [``public``] - (Some (``=>`` (ident (driverNamespace + ".Azure") <.> submit))) + (Some (``=>`` (ident (driverNamespace + ".Azure") <.> (ident "Submit", args)))) /// Generates the Simulate method for an entry point class. let private simulateMethod context entryPoint = @@ -209,13 +216,15 @@ let private simulateMethod context entryPoint = let parseResultParamName = "parseResult" let settingsParamName = "settings" let simulatorParamName = "simulator" + let args = [ ident "this" :> ExpressionSyntax - ident "this" <.> (ident "CreateArgument", [ident parseResultParamName]) + invoke (ident "CreateArgument") ``(`` [ident parseResultParamName] ``)`` ident settingsParamName :> ExpressionSyntax ident simulatorParamName :> ExpressionSyntax ] + arrow_method "System.Threading.Tasks.Task" "Simulate" ``<<`` [] ``>>`` ``(`` [ diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 9d882042dd8..9f47c7f8b6c 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -9,7 +9,7 @@ using Microsoft.Quantum.Simulation.Common.Exceptions; using Microsoft.Quantum.Simulation.Core; using System; -using System.Collections.Generic; +using System.Collections.Immutable; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -23,17 +23,45 @@ namespace Microsoft.Quantum.EntryPointDriver /// public static class Azure { + /// + /// Submits an entry point to Azure Quantum. If is non-null and a QIR submitter + /// is available for the target in , the QIR entry point is submitted. Otherwise, the + /// Q# entry point is submitted. + /// + /// The Azure submission settings. + /// A Q# entry point submission. + /// A QIR entry point submission. + /// The entry point argument type. + /// The entry point return type. + /// The exit code. + public static Task Submit( + AzureSettings settings, QSharpSubmission qsSubmission, QirSubmission? qirSubmission) + { + if (!(qirSubmission is null) && QirSubmitter(settings) is { } submitter) + { + return SubmitQir(settings, submitter, qirSubmission); + } + + if (QSharpMachine(settings) is { } machine) + { + return SubmitQSharp(settings, machine, qsSubmission); + } + + DisplayWithColor(ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); + return Task.FromResult(1); + } + /// /// Submits a Q# entry point to Azure Quantum. /// /// The entry point's argument type. /// The entry point's return type. /// The Azure submission settings. - /// The information about the entry point. - /// The input argument tuple to the entry point. + /// The quantum machine used for submission. + /// The Q# entry point submission. /// The exit code. - public static async Task SubmitQSharp( - AzureSettings settings, EntryPointInfo info, TIn input) + private static async Task SubmitQSharp( + AzureSettings settings, IQuantumMachine machine, QSharpSubmission submission) { if (settings.Verbose) { @@ -41,29 +69,18 @@ public static async Task SubmitQSharp( Console.WriteLine(settings + Environment.NewLine); } - switch (QSharpMachine(settings)) - { - case null: - DisplayWithColor( - ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); - return 1; - case var machine: - return settings.DryRun - ? Validate(machine, info, input) - : await SubmitJob(settings, machine, info, input); - } + return settings.DryRun ? Validate(machine, submission) : await SubmitJob(settings, machine, submission); } /// /// Submits a QIR entry point to Azure Quantum. /// /// The Azure submission settings. - /// The QIR bitcode stream. - /// The entry point name. - /// The arguments to the entry point. + /// The QIR entry point submitter. + /// The QIR entry point submission. /// The exit code. - public static async Task SubmitQir( - AzureSettings settings, Stream qir, string entryPoint, IReadOnlyList arguments) + private static async Task SubmitQir( + AzureSettings settings, IQirSubmitter submitter, QirSubmission submission) { if (settings.Verbose) { @@ -71,17 +88,9 @@ public static async Task SubmitQir( Console.WriteLine(settings + Environment.NewLine); } - switch (QirSubmitter(settings)) - { - case null: - DisplayWithColor( - ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); - return 1; - case var submitter: - var job = await submitter.SubmitAsync(qir, entryPoint, arguments); - DisplayJob(job, settings.Output); - return 0; - } + var job = await submitter.SubmitAsync(submission.QirStream, submission.EntryPointName, submission.Arguments); + DisplayJob(job, settings.Output); + return 0; } /// @@ -91,17 +100,16 @@ public static async Task SubmitQir( /// The output type. /// The submission settings. /// The quantum machine target. - /// The information about the entry point. - /// The input argument tuple to the entry point. + /// The entry point submission. /// The exit code. private static async Task SubmitJob( - AzureSettings settings, IQuantumMachine machine, EntryPointInfo info, TIn input) + AzureSettings settings, IQuantumMachine machine, QSharpSubmission submission) { try { var job = await machine.SubmitAsync( - info, - input, + submission.EntryPointInfo, + submission.Argument, new SubmissionContext { FriendlyName = settings.JobName, Shots = settings.Shots }); DisplayJob(job, settings.Output); @@ -130,12 +138,11 @@ private static async Task SubmitJob( /// The input type. /// The output type. /// The quantum machine target. - /// The information about the entry point. - /// The input argument tuple to the entry point. + /// The entry point submission. /// The exit code. - private static int Validate(IQuantumMachine machine, EntryPointInfo info, TIn input) + private static int Validate(IQuantumMachine machine, QSharpSubmission submission) { - var (isValid, message) = machine.Validate(info, input); + var (isValid, message) = machine.Validate(submission.EntryPointInfo, submission.Argument); Console.WriteLine(isValid ? "✔️ The program is valid!" : "❌ The program is invalid."); if (!string.IsNullOrWhiteSpace(message)) { @@ -228,6 +235,62 @@ private sealed class SubmissionContext : IQuantumMachineSubmissionContext } } + /// + /// A Q# entry point submission. + /// + /// The entry point argument type. + /// The entry point return type. + public sealed class QSharpSubmission + { + /// + /// The entry point info. + /// + internal EntryPointInfo EntryPointInfo { get; } + + /// + /// The entry point argument. + /// + internal TIn Argument { get; } + + /// + /// Creates a Q# entry point submission. + /// + /// The entry point info. + /// The entry point argument. + public QSharpSubmission(EntryPointInfo entryPointInfo, TIn argument) => + (this.EntryPointInfo, this.Argument) = (entryPointInfo, argument); + } + + /// + /// A QIR entry point submission. + /// + public sealed class QirSubmission + { + /// + /// The QIR bitcode stream. + /// + internal Stream QirStream { get; } + + /// + /// The entry point name. + /// + internal string EntryPointName { get; } + + /// + /// The entry point arguments. + /// + internal ImmutableList Arguments { get; } + + /// + /// Creates a QIR entry point submission. + /// + /// The QIR bitcode stream. + /// The entry point name. + /// The entry point arguments. + public QirSubmission(Stream qirStream, string entryPointName, ImmutableList arguments) => + (this.QirStream, this.EntryPointName, this.Arguments) = (qirStream, entryPointName, arguments); + } + /// /// The information to show in the output after the job is submitted. /// From 06e9f9fe066a363558efed1eba6de6f3c379d160 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 3 May 2021 17:31:07 -0700 Subject: [PATCH 075/145] Split out Azure files --- src/Simulation/CSharpGeneration/EntryPoint.fs | 8 +- .../EntryPointDriver/{ => Azure}/Azure.cs | 196 +----------------- .../EntryPointDriver/Azure/AzureSettings.cs | 126 +++++++++++ .../EntryPointDriver/Azure/OutputFormat.cs | 21 ++ .../Azure/QSharpSubmission.cs | 33 +++ .../EntryPointDriver/Azure/QirSubmission.cs | 39 ++++ src/Simulation/EntryPointDriver/Driver.cs | 1 + .../EntryPointDriver/IEntryPoint.cs | 1 + 8 files changed, 226 insertions(+), 199 deletions(-) rename src/Simulation/EntryPointDriver/{ => Azure}/Azure.cs (60%) create mode 100644 src/Simulation/EntryPointDriver/Azure/AzureSettings.cs create mode 100644 src/Simulation/EntryPointDriver/Azure/OutputFormat.cs create mode 100644 src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs create mode 100644 src/Simulation/EntryPointDriver/Azure/QirSubmission.cs diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 26ffa7a378d..107a5ef6271 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -167,7 +167,7 @@ let private submitMethod context entryPoint parameters = let settingsParamName = "settings" let qsSubmission = - ``new`` (generic (driverNamespace + ".QSharpSubmission") ``<<`` [argTypeName; returnTypeName] ``>>``) + ``new`` (generic (driverNamespace + ".Azure.QSharpSubmission") ``<<`` [argTypeName; returnTypeName] ``>>``) ``(`` [ ident callableName <|.|> ident "Info" @@ -183,7 +183,7 @@ let private submitMethod context entryPoint parameters = let qirSubmission = lazy - ``new`` (driverNamespace + ".QirSubmission" |> ``type``) + ``new`` (driverNamespace + ".Azure.QirSubmission" |> ``type``) ``(`` [ qirStream.Value @@ -203,11 +203,11 @@ let private submitMethod context entryPoint parameters = ``(`` [ param parseResultParamName ``of`` (``type`` "System.CommandLine.Parsing.ParseResult") - param settingsParamName ``of`` (``type`` (driverNamespace + ".AzureSettings")) + param settingsParamName ``of`` (``type`` (driverNamespace + ".Azure.AzureSettings")) ] ``)`` [``public``] - (Some (``=>`` (ident (driverNamespace + ".Azure") <.> (ident "Submit", args)))) + (Some (``=>`` (ident (driverNamespace + ".Azure.Azure") <.> (ident "Submit", args)))) /// Generates the Simulate method for an entry point class. let private simulateMethod context entryPoint = diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs similarity index 60% rename from src/Simulation/EntryPointDriver/Azure.cs rename to src/Simulation/EntryPointDriver/Azure/Azure.cs index 9f47c7f8b6c..38347c14ec4 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -7,14 +7,10 @@ using Microsoft.Quantum.EntryPointDriver.Mock; using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Common.Exceptions; -using Microsoft.Quantum.Simulation.Core; using System; -using System.Collections.Immutable; -using System.IO; -using System.Linq; using System.Threading.Tasks; -namespace Microsoft.Quantum.EntryPointDriver +namespace Microsoft.Quantum.EntryPointDriver.Azure { using Environment = System.Environment; @@ -234,194 +230,4 @@ private sealed class SubmissionContext : IQuantumMachineSubmissionContext public int Shots { get; set; } } } - - /// - /// A Q# entry point submission. - /// - /// The entry point argument type. - /// The entry point return type. - public sealed class QSharpSubmission - { - /// - /// The entry point info. - /// - internal EntryPointInfo EntryPointInfo { get; } - - /// - /// The entry point argument. - /// - internal TIn Argument { get; } - - /// - /// Creates a Q# entry point submission. - /// - /// The entry point info. - /// The entry point argument. - public QSharpSubmission(EntryPointInfo entryPointInfo, TIn argument) => - (this.EntryPointInfo, this.Argument) = (entryPointInfo, argument); - } - - /// - /// A QIR entry point submission. - /// - public sealed class QirSubmission - { - /// - /// The QIR bitcode stream. - /// - internal Stream QirStream { get; } - - /// - /// The entry point name. - /// - internal string EntryPointName { get; } - - /// - /// The entry point arguments. - /// - internal ImmutableList Arguments { get; } - - /// - /// Creates a QIR entry point submission. - /// - /// The QIR bitcode stream. - /// The entry point name. - /// The entry point arguments. - public QirSubmission(Stream qirStream, string entryPointName, ImmutableList arguments) => - (this.QirStream, this.EntryPointName, this.Arguments) = (qirStream, entryPointName, arguments); - } - - /// - /// The information to show in the output after the job is submitted. - /// - public enum OutputFormat - { - /// - /// Show a friendly message with a URI that can be used to see the job results. - /// - FriendlyUri, - - /// - /// Show only the job ID. - /// - Id - } - - /// - /// Settings for a submission to Azure Quantum. - /// - public sealed class AzureSettings - { - /// - /// The subscription ID. - /// - public string? Subscription { get; set; } - - /// - /// The resource group name. - /// - public string? ResourceGroup { get; set; } - - /// - /// The workspace name. - /// - public string? Workspace { get; set; } - - /// - /// The target device ID. - /// - public string? Target { get; set; } - - /// - /// The storage account connection string. - /// - public string? Storage { get; set; } - - /// - /// The Azure Active Directory authentication token. - /// - public string? AadToken { get; set; } - - /// - /// The base URI of the Azure Quantum endpoint. - /// If both and properties are not null, takes precedence. - /// - public Uri? BaseUri { get; set; } - - /// - /// The location to use with the default Azure Quantum endpoint. - /// If both and properties are not null, takes precedence. - /// - public string? Location { get; set; } - - /// - /// The name of the submitted job. - /// - public string? JobName { get; set; } - - /// - /// The number of times the program is executed on the target machine. - /// - public int Shots { get; set; } - - /// - /// The information to show in the output after the job is submitted. - /// - public OutputFormat Output { get; set; } - - /// - /// Validate the program and options, but do not submit to Azure Quantum. - /// - public bool DryRun { get; set; } - - /// - /// Show additional information about the submission. - /// - public bool Verbose { get; set; } - - /// - /// Creates a based on the settings. - /// - /// The based on the settings. - internal Workspace CreateWorkspace() - { - if (BaseUri != null) - { - return AadToken is null - ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: BaseUri) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: BaseUri); - } - else if (Location != null) - { - return AadToken is null - ? new Workspace(Subscription, ResourceGroup, Workspace, location: NormalizeLocation(Location)) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, location: NormalizeLocation(Location)); - } - else - { - return AadToken is null - ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: null) - : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: null); - } - } - - public override string ToString() => string.Join( - Environment.NewLine, - $"Subscription: {Subscription}", - $"Resource Group: {ResourceGroup}", - $"Workspace: {Workspace}", - $"Target: {Target}", - $"Storage: {Storage}", - $"AAD Token: {AadToken}", - $"Base URI: {BaseUri}", - $"Location: {Location}", - $"Job Name: {JobName}", - $"Shots: {Shots}", - $"Output: {Output}", - $"Dry Run: {DryRun}", - $"Verbose: {Verbose}"); - - internal static string NormalizeLocation(string location) => - string.Concat(location.Where(c => !char.IsWhiteSpace(c))).ToLower(); - } } diff --git a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs new file mode 100644 index 00000000000..82d3e994aa3 --- /dev/null +++ b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Azure.Quantum; +using System; +using System.Linq; + +namespace Microsoft.Quantum.EntryPointDriver.Azure +{ + /// + /// Settings for a submission to Azure Quantum. + /// + public sealed class AzureSettings + { + /// + /// The subscription ID. + /// + public string? Subscription { get; set; } + + /// + /// The resource group name. + /// + public string? ResourceGroup { get; set; } + + /// + /// The workspace name. + /// + public string? Workspace { get; set; } + + /// + /// The target device ID. + /// + public string? Target { get; set; } + + /// + /// The storage account connection string. + /// + public string? Storage { get; set; } + + /// + /// The Azure Active Directory authentication token. + /// + public string? AadToken { get; set; } + + /// + /// The base URI of the Azure Quantum endpoint. If both and + /// properties are not null, takes precedence. + /// + public Uri? BaseUri { get; set; } + + /// + /// The location to use with the default Azure Quantum endpoint. If both and + /// properties are not null, takes precedence. + /// + public string? Location { get; set; } + + /// + /// The name of the submitted job. + /// + public string? JobName { get; set; } + + /// + /// The number of times the program is executed on the target machine. + /// + public int Shots { get; set; } + + /// + /// The information to show in the output after the job is submitted. + /// + public OutputFormat Output { get; set; } + + /// + /// Validate the program and options, but do not submit to Azure Quantum. + /// + public bool DryRun { get; set; } + + /// + /// Show additional information about the submission. + /// + public bool Verbose { get; set; } + + /// + /// Creates a based on the settings. + /// + /// The based on the settings. + internal Workspace CreateWorkspace() + { + if (BaseUri != null) + { + return AadToken is null + ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: BaseUri) + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, BaseUri); + } + + if (Location != null) + { + return AadToken is null + ? new Workspace(Subscription, ResourceGroup, Workspace, location: NormalizeLocation(Location)) + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, NormalizeLocation(Location)); + } + + return AadToken is null + ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: null) + : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, baseUri: null); + } + + public override string ToString() => string.Join( + System.Environment.NewLine, + $"Subscription: {Subscription}", + $"Resource Group: {ResourceGroup}", + $"Workspace: {Workspace}", + $"Target: {Target}", + $"Storage: {Storage}", + $"AAD Token: {AadToken}", + $"Base URI: {BaseUri}", + $"Location: {Location}", + $"Job Name: {JobName}", + $"Shots: {Shots}", + $"Output: {Output}", + $"Dry Run: {DryRun}", + $"Verbose: {Verbose}"); + + internal static string NormalizeLocation(string location) => + string.Concat(location.Where(c => !char.IsWhiteSpace(c))).ToLower(); + } +} diff --git a/src/Simulation/EntryPointDriver/Azure/OutputFormat.cs b/src/Simulation/EntryPointDriver/Azure/OutputFormat.cs new file mode 100644 index 00000000000..2602a2a96af --- /dev/null +++ b/src/Simulation/EntryPointDriver/Azure/OutputFormat.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.EntryPointDriver.Azure +{ + /// + /// The information to show in the output after the job is submitted. + /// + public enum OutputFormat + { + /// + /// Show a friendly message with a URI that can be used to see the job results. + /// + FriendlyUri, + + /// + /// Show only the job ID. + /// + Id + } +} diff --git a/src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs b/src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs new file mode 100644 index 00000000000..da6663218f7 --- /dev/null +++ b/src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Quantum.Simulation.Core; + +namespace Microsoft.Quantum.EntryPointDriver.Azure +{ + /// + /// A Q# entry point submission. + /// + /// The entry point argument type. + /// The entry point return type. + public sealed class QSharpSubmission + { + /// + /// The entry point info. + /// + internal EntryPointInfo EntryPointInfo { get; } + + /// + /// The entry point argument. + /// + internal TIn Argument { get; } + + /// + /// Creates a Q# entry point submission. + /// + /// The entry point info. + /// The entry point argument. + public QSharpSubmission(EntryPointInfo entryPointInfo, TIn argument) => + (this.EntryPointInfo, this.Argument) = (entryPointInfo, argument); + } +} diff --git a/src/Simulation/EntryPointDriver/Azure/QirSubmission.cs b/src/Simulation/EntryPointDriver/Azure/QirSubmission.cs new file mode 100644 index 00000000000..b8d491e290a --- /dev/null +++ b/src/Simulation/EntryPointDriver/Azure/QirSubmission.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Quantum.Runtime; +using System.Collections.Immutable; +using System.IO; + +namespace Microsoft.Quantum.EntryPointDriver.Azure +{ + /// + /// A QIR entry point submission. + /// + public sealed class QirSubmission + { + /// + /// The QIR bitcode stream. + /// + internal Stream QirStream { get; } + + /// + /// The entry point name. + /// + internal string EntryPointName { get; } + + /// + /// The entry point arguments. + /// + internal ImmutableList Arguments { get; } + + /// + /// Creates a QIR entry point submission. + /// + /// The QIR bitcode stream. + /// The entry point name. + /// The entry point arguments. + public QirSubmission(Stream qirStream, string entryPointName, ImmutableList arguments) => + (this.QirStream, this.EntryPointName, this.Arguments) = (qirStream, entryPointName, arguments); + } +} diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 1e4cc04762a..66b957ab41a 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Microsoft.Quantum.EntryPointDriver.Azure; using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Simulation/EntryPointDriver/IEntryPoint.cs b/src/Simulation/EntryPointDriver/IEntryPoint.cs index 67964abb05d..16e2241feff 100644 --- a/src/Simulation/EntryPointDriver/IEntryPoint.cs +++ b/src/Simulation/EntryPointDriver/IEntryPoint.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Microsoft.Quantum.EntryPointDriver.Azure; using System.Collections.Generic; using System.CommandLine; using System.CommandLine.Parsing; From f85fef524cfe50afa72e1ec7076740112664af02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Mon, 3 May 2021 21:20:24 -0700 Subject: [PATCH 076/145] Ignore line breaks for testing purposes. (#671) --- .../QirDriverGeneratorTests.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs index f4f92e66a4e..92d8daaa744 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -142,6 +142,9 @@ public class QirDriverGeneratorTests } }; + private static string RemoveLineEndings(string str) => + str.Replace("\r\n", string.Empty).Replace("\n", string.Empty).Replace("\r", string.Empty); + [Theory] [InlineData("UseNoArgs")] [InlineData("UseBoolArg")] @@ -163,7 +166,7 @@ public void GenerateFullStateSimulatorDriver(string testCase) var entryPointOperation = TestCases[testCase]; var driverGenerator = new QirFullStateDriverGenerator(); var driverFileName = $"{testCase}.cpp"; - var verificationCppSourceCode = File.ReadAllText(Path.Combine(TestCasesDirectory, driverFileName)); + var verificationCppSourceCode = RemoveLineEndings(File.ReadAllText(Path.Combine(TestCasesDirectory, driverFileName))); if (!Directory.Exists(TestArtifactsDirectory)) { Directory.CreateDirectory(TestArtifactsDirectory); @@ -172,7 +175,7 @@ public void GenerateFullStateSimulatorDriver(string testCase) var generatedStream = File.Create(Path.Combine(TestArtifactsDirectory, driverFileName)); driverGenerator.GenerateAsync(entryPointOperation, generatedStream).Wait(); var generatedStreamReader = new StreamReader(generatedStream, Encoding.UTF8); - var generatedCppSourceCode = generatedStreamReader.ReadToEnd(); + var generatedCppSourceCode = RemoveLineEndings(generatedStreamReader.ReadToEnd()); Assert.Equal(verificationCppSourceCode, generatedCppSourceCode); generatedStream.Close(); From fd0a3914659ca3db5774eac95f77bd2bc1c06546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 4 May 2021 08:07:13 -0700 Subject: [PATCH 077/145] Fix runtime libs folder in test. --- src/Qir/Controller/test-qir-controller.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index c8dc17ea1aa..aaed81416b3 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -11,7 +11,7 @@ $testCasesFolder = (Join-Path $PSScriptRoot "test-cases") $testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") $includeDirectory = (Join-Path $testArtifactsFolder "include") $headerPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Common\externals\CLI11"), (Join-Path $PSScriptRoot "..\..\Qir\Runtime\public")) -$libraryPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Runtime\build\$buildConfiguration\bin"), (Join-Path $PSScriptRoot "..\..\Simulation\Simulators\bin\$buildConfiguration\netstandard2.1")) +$libraryPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Runtime\bin\$buildConfiguration\bin"), (Join-Path $PSScriptRoot "..\..\Simulation\Simulators\bin\$buildConfiguration\netstandard2.1")) $includeDirectory = (Join-Path $testArtifactsFolder "include") $libraryDirectory = (Join-Path $testArtifactsFolder "library") From d77bc4d2073f1b695ea2d11ab321d27b578fd605 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 4 May 2021 09:43:50 -0700 Subject: [PATCH 078/145] Update AzureSettings.cs --- src/Simulation/EntryPointDriver/Azure/AzureSettings.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs index 82d3e994aa3..d6693b10047 100644 --- a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs +++ b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs @@ -7,6 +7,8 @@ namespace Microsoft.Quantum.EntryPointDriver.Azure { + using Environment = System.Environment; + /// /// Settings for a submission to Azure Quantum. /// @@ -85,14 +87,14 @@ public sealed class AzureSettings /// The based on the settings. internal Workspace CreateWorkspace() { - if (BaseUri != null) + if (!(BaseUri is null)) { return AadToken is null ? new Workspace(Subscription, ResourceGroup, Workspace, baseUri: BaseUri) : new Workspace(Subscription, ResourceGroup, Workspace, AadToken, BaseUri); } - if (Location != null) + if (!(Location is null)) { return AadToken is null ? new Workspace(Subscription, ResourceGroup, Workspace, location: NormalizeLocation(Location)) @@ -105,7 +107,7 @@ internal Workspace CreateWorkspace() } public override string ToString() => string.Join( - System.Environment.NewLine, + Environment.NewLine, $"Subscription: {Subscription}", $"Resource Group: {ResourceGroup}", $"Workspace: {Workspace}", From f1d9efcead3fbabe22a32881f605b9af18bcad0c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 4 May 2021 12:10:43 -0700 Subject: [PATCH 079/145] Add clang arguments --- src/Qir/Controller/test-qir-controller.ps1 | 7 ++----- src/Qir/Execution/Tools/Executable/ClangClient.cs | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index 7687f5d7ce7..24cd3b108ae 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -18,9 +18,6 @@ $libraryDirectory = (Join-Path $testArtifactsFolder "library") if (($IsWindows) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Win")))) { Write-Host "On Windows build using Clang" - $env:CC = "clang.exe" - $env:CXX = "clang++.exe" - $env:RC = "clang++.exe" if (!(Get-Command clang -ErrorAction SilentlyContinue) -and (choco find --idonly -l llvm) -contains "llvm") { # LLVM was installed by Chocolatey, so add the install location to the path. @@ -40,7 +37,7 @@ foreach ( $path in $headerPaths ) { Get-ChildItem $path -File | Foreach-Object { - Copy-Item $_ -Destination (Join-Path $includeDirectory $_.Name) + Copy-Item $_.FullName -Destination (Join-Path $includeDirectory $_.Name) } } @@ -50,7 +47,7 @@ foreach ( $path in $libraryPaths ) { Get-ChildItem $path -File | Foreach-Object { - Copy-Item $_ -Destination (Join-Path $libraryDirectory $_.Name) + Copy-Item $_.FullName -Destination (Join-Path $libraryDirectory $_.Name) } } diff --git a/src/Qir/Execution/Tools/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs index d4a204642a2..d8a1b245166 100644 --- a/src/Qir/Execution/Tools/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -23,7 +23,7 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, // string.Join does not automatically prepend the delimiter, so it is included again in the string here. var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; - var arguments = $"{inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath}"; + var arguments = $"{inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath} -std=c++17 -v"; logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); var taskCompletionSource = new TaskCompletionSource(); using var process = new Process(); From dcb81308fa06b263f915d6606abf63b65721edbc Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 4 May 2021 12:18:52 -0700 Subject: [PATCH 080/145] Show error for dry run --- .../EntryPointDriver/Azure/Azure.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 38347c14ec4..849c36b75a9 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -84,8 +84,17 @@ private static async Task SubmitQir( Console.WriteLine(settings + Environment.NewLine); } - var job = await submitter.SubmitAsync(submission.QirStream, submission.EntryPointName, submission.Arguments); - DisplayJob(job, settings.Output); + if (settings.DryRun) + { + DisplayError("Dry run is not supported with QIR submission.", null); + } + else + { + var job = + await submitter.SubmitAsync(submission.QirStream, submission.EntryPointName, submission.Arguments); + DisplayJob(job, settings.Output); + } + return 0; } @@ -187,10 +196,13 @@ private static void DisplayJob(IQuantumMachineJob job, OutputFormat format) /// /// A summary of the error. /// The full error message. - private static void DisplayError(string summary, string message) + private static void DisplayError(string summary, string? message) { DisplayWithColor(ConsoleColor.Red, Console.Error, summary); - Console.Error.WriteLine(Environment.NewLine + message); + if (!string.IsNullOrWhiteSpace(message)) + { + Console.Error.WriteLine(Environment.NewLine + message); + } } /// From d8aa688d4170cd21dab90c96ab8b91495edf1b12 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 4 May 2021 12:40:52 -0700 Subject: [PATCH 081/145] Handle errors in QIR submission --- .../EntryPointDriver.Tests/Tests.fs | 2 +- .../EntryPointDriver/Azure/Azure.cs | 38 ++++++++----------- .../Mock/ErrorQuantumMachine.cs | 2 +- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index 9365da3b516..303e28ce90a 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -811,7 +811,7 @@ let ``Submit catches exceptions`` () = given submitWithErrorTarget |> failsWith "Something went wrong when submitting the program to the Azure Quantum service. - This quantum machine always has an error." + This machine always has an error." // Help diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 849c36b75a9..e90be11339f 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -59,13 +59,18 @@ public static Task Submit( private static async Task SubmitQSharp( AzureSettings settings, IQuantumMachine machine, QSharpSubmission submission) { + Task SubmitJob() => machine.SubmitAsync( + submission.EntryPointInfo, + submission.Argument, + new SubmissionContext { FriendlyName = settings.JobName, Shots = settings.Shots }); + if (settings.Verbose) { Console.WriteLine("Submitting Q# entry point." + Environment.NewLine); Console.WriteLine(settings + Environment.NewLine); } - return settings.DryRun ? Validate(machine, submission) : await SubmitJob(settings, machine, submission); + return settings.DryRun ? Validate(machine, submission) : await DisplayJobOrError(settings, SubmitJob()); } /// @@ -87,37 +92,25 @@ private static async Task SubmitQir( if (settings.DryRun) { DisplayError("Dry run is not supported with QIR submission.", null); - } - else - { - var job = - await submitter.SubmitAsync(submission.QirStream, submission.EntryPointName, submission.Arguments); - DisplayJob(job, settings.Output); + return 1; } - return 0; + return await DisplayJobOrError( + settings, + submitter.SubmitAsync(submission.QirStream, submission.EntryPointName, submission.Arguments)); } /// - /// Submits a job to Azure Quantum. + /// Displays the submitted job information or an error message. /// - /// The input type. - /// The output type. /// The submission settings. - /// The quantum machine target. - /// The entry point submission. + /// The submitted job task. /// The exit code. - private static async Task SubmitJob( - AzureSettings settings, IQuantumMachine machine, QSharpSubmission submission) + private static async Task DisplayJobOrError(AzureSettings settings, Task job) { try { - var job = await machine.SubmitAsync( - submission.EntryPointInfo, - submission.Argument, - new SubmissionContext { FriendlyName = settings.JobName, Shots = settings.Shots }); - - DisplayJob(job, settings.Output); + DisplayJob(await job, settings.Output); return 0; } catch (AzureQuantumException ex) @@ -130,8 +123,7 @@ private static async Task SubmitJob( catch (QuantumProcessorTranslationException ex) { DisplayError( - "Something went wrong when performing translation to the intermediate representation used by the " + - "target quantum machine.", + "Something went wrong when performing translation to the intermediate representation used by the target quantum machine.", ex.Message); return 1; } diff --git a/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs index 33147da0895..8be69b89968 100644 --- a/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs +++ b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs @@ -66,7 +66,7 @@ public Task> ExecuteAsync( public Task SubmitAsync( EntryPointInfo info, TInput input) => - throw new AzureQuantumException("This quantum machine always has an error."); + Task.FromException(new AzureQuantumException("This machine always has an error.")); public Task SubmitAsync( EntryPointInfo info, TInput input, IQuantumMachineSubmissionContext submissionContext) => From 6fcef3e9c9f6f4f1bff036458f8f362867027206 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 4 May 2021 14:31:46 -0700 Subject: [PATCH 082/145] Use clang++ --- src/Qir/Execution/Tools/Executable/ClangClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Execution/Tools/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs index d8a1b245166..8140e243514 100644 --- a/src/Qir/Execution/Tools/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -29,7 +29,7 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, using var process = new Process(); process.StartInfo = new ProcessStartInfo { - FileName = "clang", + FileName = "clang++", Arguments = arguments, }; process.EnableRaisingEvents = true; From b70ef1fdb39f6a861bbe605db03170eb8063c5d4 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 4 May 2021 14:57:38 -0700 Subject: [PATCH 083/145] Set environment variables --- src/Qir/Execution/Tools/Executable/ClangClient.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Qir/Execution/Tools/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs index 8140e243514..0279e8cdf53 100644 --- a/src/Qir/Execution/Tools/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; using System.Diagnostics; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; @@ -27,6 +28,8 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); var taskCompletionSource = new TaskCompletionSource(); using var process = new Process(); + Environment.SetEnvironmentVariable("DYLD_LIBRARY_PATH", libraryPath); + Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", libraryPath); process.StartInfo = new ProcessStartInfo { FileName = "clang++", From e3745c9fd54f496f29db13a42282731fc542239c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 4 May 2021 16:04:28 -0700 Subject: [PATCH 084/145] Add native simulator to library directory --- src/Qir/Controller/test-qir-controller.ps1 | 2 +- src/Qir/Execution/Tools/Executable/ClangClient.cs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 index 24cd3b108ae..85c4edcbf7b 100644 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ b/src/Qir/Controller/test-qir-controller.ps1 @@ -11,7 +11,7 @@ $testCasesFolder = (Join-Path $PSScriptRoot "test-cases") $testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") $includeDirectory = (Join-Path $testArtifactsFolder "include") $headerPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Common\externals\CLI11"), (Join-Path $PSScriptRoot "..\..\Qir\Runtime\public")) -$libraryPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Runtime\bin\$buildConfiguration\bin"), (Join-Path $PSScriptRoot "..\..\Simulation\Simulators\bin\$buildConfiguration\netstandard2.1")) +$libraryPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Runtime\bin\$buildConfiguration\bin"), (Join-Path $PSScriptRoot "..\..\Simulation\Simulators\bin\$buildConfiguration\netstandard2.1"), $Env:NATIVE_SIMULATOR) $includeDirectory = (Join-Path $testArtifactsFolder "include") $libraryDirectory = (Join-Path $testArtifactsFolder "library") diff --git a/src/Qir/Execution/Tools/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs index 0279e8cdf53..9e59464d5ca 100644 --- a/src/Qir/Execution/Tools/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Diagnostics; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; @@ -28,13 +27,13 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); var taskCompletionSource = new TaskCompletionSource(); using var process = new Process(); - Environment.SetEnvironmentVariable("DYLD_LIBRARY_PATH", libraryPath); - Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", libraryPath); process.StartInfo = new ProcessStartInfo { FileName = "clang++", Arguments = arguments, }; + process.StartInfo.EnvironmentVariables.Add("DYLD_LIBRARY_PATH", libraryPath); + process.StartInfo.EnvironmentVariables.Add("LD_LIBRARY_PATH", libraryPath); process.EnableRaisingEvents = true; process.Exited += (sender, args) => { taskCompletionSource.SetResult(true); }; process.Start(); From 9bdaade2891cd8276107d03b98a986e511586aa3 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 4 May 2021 16:13:43 -0700 Subject: [PATCH 085/145] Add SubmissionOptions to IQirSubmitter --- .../Core/Submitters/IQirSubmitter.cs | 4 ++- .../Core/Submitters/SubmissionOptions.cs | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/Simulation/Core/Submitters/SubmissionOptions.cs diff --git a/src/Simulation/Core/Submitters/IQirSubmitter.cs b/src/Simulation/Core/Submitters/IQirSubmitter.cs index f18c171c6f0..d4f5591b662 100644 --- a/src/Simulation/Core/Submitters/IQirSubmitter.cs +++ b/src/Simulation/Core/Submitters/IQirSubmitter.cs @@ -20,7 +20,9 @@ public interface IQirSubmitter : IAzureSubmitter /// The QIR program as a byte stream. /// The fully-qualified name of the entry point to execute. /// The arguments to the entry point in the order in which they are declared. + /// Additional options for the submission. /// The submitted job. - Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments); + Task SubmitAsync( + Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options); } } diff --git a/src/Simulation/Core/Submitters/SubmissionOptions.cs b/src/Simulation/Core/Submitters/SubmissionOptions.cs new file mode 100644 index 00000000000..69f80301857 --- /dev/null +++ b/src/Simulation/Core/Submitters/SubmissionOptions.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +namespace Microsoft.Quantum.Runtime +{ + /// + /// Options for a job submitted to Azure Quantum. + /// + public class SubmissionOptions + { + /// + /// A name describing the job. + /// + public string FriendlyName { get; } + + /// + /// The number of times the program will be executed. + /// + public int Shots { get; } + + /// + /// Creates a new set of submission options. + /// + /// A name describing the job. + /// The number of times the program will be executed. + public SubmissionOptions(string friendlyName, int shots) => + (this.FriendlyName, this.Shots) = (friendlyName, shots); + } +} From 7e9521f310f758ee48fb9fed8eff506bfc4d7a3b Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 4 May 2021 16:29:15 -0700 Subject: [PATCH 086/145] Change the way environment variables are set --- src/Qir/Execution/Tools/Executable/ClangClient.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Qir/Execution/Tools/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs index 9e59464d5ca..0279e8cdf53 100644 --- a/src/Qir/Execution/Tools/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; using System.Diagnostics; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; @@ -27,13 +28,13 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); var taskCompletionSource = new TaskCompletionSource(); using var process = new Process(); + Environment.SetEnvironmentVariable("DYLD_LIBRARY_PATH", libraryPath); + Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", libraryPath); process.StartInfo = new ProcessStartInfo { FileName = "clang++", Arguments = arguments, }; - process.StartInfo.EnvironmentVariables.Add("DYLD_LIBRARY_PATH", libraryPath); - process.StartInfo.EnvironmentVariables.Add("LD_LIBRARY_PATH", libraryPath); process.EnableRaisingEvents = true; process.Exited += (sender, args) => { taskCompletionSource.SetResult(true); }; process.Start(); From 9a99f197c45e9093fcff4d49ccadc52301a91ff1 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 4 May 2021 17:00:58 -0700 Subject: [PATCH 087/145] Add IQSharpSubmitter --- .../Microsoft.Quantum.Runtime.Core.csproj | 1 + .../Core/Submitters/IAzureSubmitter.cs | 2 +- .../Core/Submitters/IQSharpSubmitter.cs | 38 +++++++++++++++++++ .../Core/Submitters/IQirSubmitter.cs | 2 +- .../Core/Submitters/IQuantumMachine.cs | 5 ++- .../IQuantumMachineExecutionContext.cs | 3 ++ .../Core/Submitters/IQuantumMachineOutput.cs | 2 + .../IQuantumMachineSubmissionContext.cs | 3 ++ .../Core/Submitters/SubmissionOptions.cs | 2 +- 9 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 src/Simulation/Core/Submitters/IQSharpSubmitter.cs diff --git a/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj b/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj index 866adc91ba0..b3eb209e697 100644 --- a/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj +++ b/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj @@ -5,6 +5,7 @@ netstandard2.1 x64 + Microsoft.Quantum.Runtime diff --git a/src/Simulation/Core/Submitters/IAzureSubmitter.cs b/src/Simulation/Core/Submitters/IAzureSubmitter.cs index 0fc11515b3f..f70a8434147 100644 --- a/src/Simulation/Core/Submitters/IAzureSubmitter.cs +++ b/src/Simulation/Core/Submitters/IAzureSubmitter.cs @@ -3,7 +3,7 @@ #nullable enable -namespace Microsoft.Quantum.Runtime +namespace Microsoft.Quantum.Runtime.Submitters { /// /// An interface for submitting quantum programs to Azure. diff --git a/src/Simulation/Core/Submitters/IQSharpSubmitter.cs b/src/Simulation/Core/Submitters/IQSharpSubmitter.cs new file mode 100644 index 00000000000..f19928a83c3 --- /dev/null +++ b/src/Simulation/Core/Submitters/IQSharpSubmitter.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using Microsoft.Quantum.Simulation.Core; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Runtime.Submitters +{ + /// + /// An interface for submitting Q# programs to Azure. + /// + public interface IQSharpSubmitter : IAzureSubmitter + { + /// + /// Submits a job to execute a Q# program without waiting for execution to complete. + /// + /// The entry point argument type. + /// The entry point return type. + /// The entry point information for the submitted program. + /// The argument to the entry point. + /// Additional options for the submission. + /// The submitted job. + Task SubmitAsync( + EntryPointInfo entryPoint, TIn argument, SubmissionOptions options); + + /// + /// Validates a Q# program for execution on Azure Quantum. + /// + /// The entry point argument type. + /// The entry point return type. + /// The entry point information for the submitted program. + /// The argument to the entry point. + /// null if the program is valid, or an error message otherwise. + string? Validate(EntryPointInfo entryPoint, TIn argument); + } +} diff --git a/src/Simulation/Core/Submitters/IQirSubmitter.cs b/src/Simulation/Core/Submitters/IQirSubmitter.cs index d4f5591b662..99fa340cbf0 100644 --- a/src/Simulation/Core/Submitters/IQirSubmitter.cs +++ b/src/Simulation/Core/Submitters/IQirSubmitter.cs @@ -7,7 +7,7 @@ using System.IO; using System.Threading.Tasks; -namespace Microsoft.Quantum.Runtime +namespace Microsoft.Quantum.Runtime.Submitters { /// /// An interface for submitting QIR programs to Azure. diff --git a/src/Simulation/Core/Submitters/IQuantumMachine.cs b/src/Simulation/Core/Submitters/IQuantumMachine.cs index 361a6eea37a..2d16d03c9bb 100644 --- a/src/Simulation/Core/Submitters/IQuantumMachine.cs +++ b/src/Simulation/Core/Submitters/IQuantumMachine.cs @@ -1,14 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.Threading.Tasks; +using Microsoft.Quantum.Runtime.Submitters; using Microsoft.Quantum.Simulation.Core; +using System; +using System.Threading.Tasks; namespace Microsoft.Quantum.Runtime { /// /// An interface for submitting Q# programs to Azure. /// + [Obsolete("Replaced by IQSharpSubmitter.")] public interface IQuantumMachine : IAzureSubmitter { /// diff --git a/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs b/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs index c884e06e2d1..2b70bba8678 100644 --- a/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs +++ b/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs @@ -1,11 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; + namespace Microsoft.Quantum.Runtime { /// /// Interface to provide configuration details to manage execution. /// + [Obsolete("No longer used.")] public interface IQuantumMachineExecutionContext { /// diff --git a/src/Simulation/Core/Submitters/IQuantumMachineOutput.cs b/src/Simulation/Core/Submitters/IQuantumMachineOutput.cs index 204765d50f4..ec8e43db17d 100644 --- a/src/Simulation/Core/Submitters/IQuantumMachineOutput.cs +++ b/src/Simulation/Core/Submitters/IQuantumMachineOutput.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Collections.Generic; namespace Microsoft.Quantum.Runtime @@ -9,6 +10,7 @@ namespace Microsoft.Quantum.Runtime /// Interface to access the results of a program executed in a quantum machine. /// Type of output the quantum program returns. /// + [Obsolete("No longer used.")] public interface IQuantumMachineOutput { /// diff --git a/src/Simulation/Core/Submitters/IQuantumMachineSubmissionContext.cs b/src/Simulation/Core/Submitters/IQuantumMachineSubmissionContext.cs index aec8dc00bc7..e6bd71cf27b 100644 --- a/src/Simulation/Core/Submitters/IQuantumMachineSubmissionContext.cs +++ b/src/Simulation/Core/Submitters/IQuantumMachineSubmissionContext.cs @@ -1,11 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; + namespace Microsoft.Quantum.Runtime { /// /// Interface to provide configuration details to submit a job. /// + [Obsolete("Replaced by SubmissionOptions.")] public interface IQuantumMachineSubmissionContext { /// diff --git a/src/Simulation/Core/Submitters/SubmissionOptions.cs b/src/Simulation/Core/Submitters/SubmissionOptions.cs index 69f80301857..c06e676f599 100644 --- a/src/Simulation/Core/Submitters/SubmissionOptions.cs +++ b/src/Simulation/Core/Submitters/SubmissionOptions.cs @@ -3,7 +3,7 @@ #nullable enable -namespace Microsoft.Quantum.Runtime +namespace Microsoft.Quantum.Runtime.Submitters { /// /// Options for a job submitted to Azure Quantum. From c6498da42683fd21a91c1f4176c6bf9a9f48ce94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 5 May 2021 09:41:50 -0700 Subject: [PATCH 088/145] Microsoft.Quantum.Qir.Tools package (#670) * Pack tools project. * Add CLI11.hpp to the package. * Pack CLI11.hpp header. * Copy specific package content to output folder. * Add to manifest. --- build/manifest.ps1 | 2 + build/pack.ps1 | 1 + .../Execution/Tools/Externals/CLI11/CLI11.hpp | 8258 +++++++++++++++++ .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 8 + 4 files changed, 8269 insertions(+) create mode 100644 src/Qir/Execution/Tools/Externals/CLI11/CLI11.hpp diff --git a/build/manifest.ps1 b/build/manifest.ps1 index 4ce93ed25b1..7259062104d 100644 --- a/build/manifest.ps1 +++ b/build/manifest.ps1 @@ -27,6 +27,7 @@ $artifacts = @{ "Microsoft.Quantum.Type1.Core", "Microsoft.Quantum.Type2.Core", "Microsoft.Quantum.Type3.Core", + "Microsoft.Quantum.Qir.Tools", "Microsoft.Quantum.QSharp.Foundation" "Microsoft.Quantum.Runtime.Core", "Microsoft.Quantum.Simulators", @@ -35,6 +36,7 @@ $artifacts = @{ Assemblies = @( ".\src\Azure\Azure.Quantum.Client\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Azure.Quantum.Client.dll", + ".\src\Qir\Execution\Tools\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Qir.Tools.dll", ".\src\Simulation\CSharpGeneration\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.CSharpGeneration.dll", ".\src\Simulation\CSharpGeneration.App\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.CSharpGeneration.App.dll", ".\src\Simulation\RoslynWrapper\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.RoslynWrapper.dll", diff --git a/build/pack.ps1 b/build/pack.ps1 index 7f6dbe702a4..a3ff5e9c211 100644 --- a/build/pack.ps1 +++ b/build/pack.ps1 @@ -98,6 +98,7 @@ Pack-Dotnet '../src/Simulation/QSharpCore/Microsoft.Quantum.QSharp.Core.csproj' Pack-Dotnet '../src/Simulation/Type1Core/Microsoft.Quantum.Type1.Core.csproj' Pack-Dotnet '../src/Simulation/Type2Core/Microsoft.Quantum.Type2.Core.csproj' Pack-Dotnet '../src/Simulation/Type3Core/Microsoft.Quantum.Type3.Core.csproj' +Pack-Dotnet '../src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj' -ForcePrerelease Pack-One '../src/Simulation/Simulators/Microsoft.Quantum.Simulators.nuspec' Pack-One '../src/Quantum.Development.Kit/Microsoft.Quantum.Development.Kit.nuspec' Pack-One '../src/Xunit/Microsoft.Quantum.Xunit.csproj' diff --git a/src/Qir/Execution/Tools/Externals/CLI11/CLI11.hpp b/src/Qir/Execution/Tools/Externals/CLI11/CLI11.hpp new file mode 100644 index 00000000000..68244d3864d --- /dev/null +++ b/src/Qir/Execution/Tools/Externals/CLI11/CLI11.hpp @@ -0,0 +1,8258 @@ +#pragma once + +// CLI11: Version 1.9.1 +// Originally designed by Henry Schreiner +// https://github.com/CLIUtils/CLI11 +// +// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts +// from: v1.9.1 +// +// From LICENSE: +// +// CLI11 1.8 Copyright (c) 2017-2019 University of Cincinnati, developed by Henry +// Schreiner under NSF AWARD 1414736. All rights reserved. +// +// Redistribution and use in source and binary forms of CLI11, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Standard combined includes: + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// Verbatim copy from Version.hpp: + + +#define CLI11_VERSION_MAJOR 1 +#define CLI11_VERSION_MINOR 9 +#define CLI11_VERSION_PATCH 1 +#define CLI11_VERSION "1.9.1" + + + + +// Verbatim copy from Macros.hpp: + + +// The following version macro is very similar to the one in PyBind11 +#if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER) +#if __cplusplus >= 201402L +#define CLI11_CPP14 +#if __cplusplus >= 201703L +#define CLI11_CPP17 +#if __cplusplus > 201703L +#define CLI11_CPP20 +#endif +#endif +#endif +#elif defined(_MSC_VER) && __cplusplus == 199711L +// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented) +// Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer +#if _MSVC_LANG >= 201402L +#define CLI11_CPP14 +#if _MSVC_LANG > 201402L && _MSC_VER >= 1910 +#define CLI11_CPP17 +#if __MSVC_LANG > 201703L && _MSC_VER >= 1910 +#define CLI11_CPP20 +#endif +#endif +#endif +#endif + +#if defined(CLI11_CPP14) +#define CLI11_DEPRECATED(reason) [[deprecated(reason)]] +#elif defined(_MSC_VER) +#define CLI11_DEPRECATED(reason) __declspec(deprecated(reason)) +#else +#define CLI11_DEPRECATED(reason) __attribute__((deprecated(reason))) +#endif + + + + +// Verbatim copy from Validators.hpp: + + +// C standard library +// Only needed for existence checking +#if defined CLI11_CPP17 && defined __has_include && !defined CLI11_HAS_FILESYSTEM +#if __has_include() +// Filesystem cannot be used if targeting macOS < 10.15 +#if defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 +#define CLI11_HAS_FILESYSTEM 0 +#else +#include +#if defined __cpp_lib_filesystem && __cpp_lib_filesystem >= 201703 +#if defined _GLIBCXX_RELEASE && _GLIBCXX_RELEASE >= 9 +#define CLI11_HAS_FILESYSTEM 1 +#elif defined(__GLIBCXX__) +// if we are using gcc and Version <9 default to no filesystem +#define CLI11_HAS_FILESYSTEM 0 +#else +#define CLI11_HAS_FILESYSTEM 1 +#endif +#else +#define CLI11_HAS_FILESYSTEM 0 +#endif +#endif +#endif +#endif + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +#include // NOLINT(build/include) +#else +#include +#include +#endif + + + +// From Version.hpp: + + + +// From Macros.hpp: + + + +// From StringTools.hpp: + +namespace CLI { + +/// Include the items in this namespace to get free conversion of enums to/from streams. +/// (This is available inside CLI as well, so CLI11 will use this without a using statement). +namespace enums { + +/// output streaming for enumerations +template ::value>::type> +std::ostream &operator<<(std::ostream &in, const T &item) { + // make sure this is out of the detail namespace otherwise it won't be found when needed + return in << static_cast::type>(item); +} + +} // namespace enums + +/// Export to CLI namespace +using enums::operator<<; + +namespace detail { +/// a constant defining an expected max vector size defined to be a big number that could be multiplied by 4 and not +/// produce overflow for some expected uses +constexpr int expected_max_vector_size{1 << 29}; +// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c +/// Split a string by a delim +inline std::vector split(const std::string &s, char delim) { + std::vector elems; + // Check to see if empty string, give consistent result + if(s.empty()) { + elems.emplace_back(); + } else { + std::stringstream ss; + ss.str(s); + std::string item; + while(std::getline(ss, item, delim)) { + elems.push_back(item); + } + } + return elems; +} + +/// Simple function to join a string +template std::string join(const T &v, std::string delim = ",") { + std::ostringstream s; + auto beg = std::begin(v); + auto end = std::end(v); + if(beg != end) + s << *beg++; + while(beg != end) { + s << delim << *beg++; + } + return s.str(); +} + +/// Simple function to join a string from processed elements +template ::value>::type> +std::string join(const T &v, Callable func, std::string delim = ",") { + std::ostringstream s; + auto beg = std::begin(v); + auto end = std::end(v); + if(beg != end) + s << func(*beg++); + while(beg != end) { + s << delim << func(*beg++); + } + return s.str(); +} + +/// Join a string in reverse order +template std::string rjoin(const T &v, std::string delim = ",") { + std::ostringstream s; + for(std::size_t start = 0; start < v.size(); start++) { + if(start > 0) + s << delim; + s << v[v.size() - start - 1]; + } + return s.str(); +} + +// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string + +/// Trim whitespace from left of string +inline std::string <rim(std::string &str) { + auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace(ch, std::locale()); }); + str.erase(str.begin(), it); + return str; +} + +/// Trim anything from left of string +inline std::string <rim(std::string &str, const std::string &filter) { + auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); + str.erase(str.begin(), it); + return str; +} + +/// Trim whitespace from right of string +inline std::string &rtrim(std::string &str) { + auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace(ch, std::locale()); }); + str.erase(it.base(), str.end()); + return str; +} + +/// Trim anything from right of string +inline std::string &rtrim(std::string &str, const std::string &filter) { + auto it = + std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); + str.erase(it.base(), str.end()); + return str; +} + +/// Trim whitespace from string +inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); } + +/// Trim anything from string +inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); } + +/// Make a copy of the string and then trim it +inline std::string trim_copy(const std::string &str) { + std::string s = str; + return trim(s); +} + +/// remove quotes at the front and back of a string either '"' or '\'' +inline std::string &remove_quotes(std::string &str) { + if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) { + if(str.front() == str.back()) { + str.pop_back(); + str.erase(str.begin(), str.begin() + 1); + } + } + return str; +} + +/// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered) +inline std::string trim_copy(const std::string &str, const std::string &filter) { + std::string s = str; + return trim(s, filter); +} +/// Print a two part "help" string +inline std::ostream &format_help(std::ostream &out, std::string name, std::string description, std::size_t wid) { + name = " " + name; + out << std::setw(static_cast(wid)) << std::left << name; + if(!description.empty()) { + if(name.length() >= wid) + out << "\n" << std::setw(static_cast(wid)) << ""; + for(const char c : description) { + out.put(c); + if(c == '\n') { + out << std::setw(static_cast(wid)) << ""; + } + } + } + out << "\n"; + return out; +} + +/// Verify the first character of an option +template bool valid_first_char(T c) { + return std::isalnum(c, std::locale()) || c == '_' || c == '?' || c == '@'; +} + +/// Verify following characters of an option +template bool valid_later_char(T c) { return valid_first_char(c) || c == '.' || c == '-'; } + +/// Verify an option name +inline bool valid_name_string(const std::string &str) { + if(str.empty() || !valid_first_char(str[0])) + return false; + for(auto c : str.substr(1)) + if(!valid_later_char(c)) + return false; + return true; +} + +/// Verify that str consists of letters only +inline bool isalpha(const std::string &str) { + return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); }); +} + +/// Return a lower case version of a string +inline std::string to_lower(std::string str) { + std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) { + return std::tolower(x, std::locale()); + }); + return str; +} + +/// remove underscores from a string +inline std::string remove_underscore(std::string str) { + str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str)); + return str; +} + +/// Find and replace a substring with another substring +inline std::string find_and_replace(std::string str, std::string from, std::string to) { + + std::size_t start_pos = 0; + + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + + return str; +} + +/// check if the flag definitions has possible false flags +inline bool has_default_flag_values(const std::string &flags) { + return (flags.find_first_of("{!") != std::string::npos); +} + +inline void remove_default_flag_values(std::string &flags) { + auto loc = flags.find_first_of('{'); + while(loc != std::string::npos) { + auto finish = flags.find_first_of("},", loc + 1); + if((finish != std::string::npos) && (flags[finish] == '}')) { + flags.erase(flags.begin() + static_cast(loc), + flags.begin() + static_cast(finish) + 1); + } + loc = flags.find_first_of('{', loc + 1); + } + flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end()); +} + +/// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores +inline std::ptrdiff_t find_member(std::string name, + const std::vector names, + bool ignore_case = false, + bool ignore_underscore = false) { + auto it = std::end(names); + if(ignore_case) { + if(ignore_underscore) { + name = detail::to_lower(detail::remove_underscore(name)); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::to_lower(detail::remove_underscore(local_name)) == name; + }); + } else { + name = detail::to_lower(name); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::to_lower(local_name) == name; + }); + } + + } else if(ignore_underscore) { + name = detail::remove_underscore(name); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::remove_underscore(local_name) == name; + }); + } else { + it = std::find(std::begin(names), std::end(names), name); + } + + return (it != std::end(names)) ? (it - std::begin(names)) : (-1); +} + +/// Find a trigger string and call a modify callable function that takes the current string and starting position of the +/// trigger and returns the position in the string to search for the next trigger string +template inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) { + std::size_t start_pos = 0; + while((start_pos = str.find(trigger, start_pos)) != std::string::npos) { + start_pos = modify(str, start_pos); + } + return str; +} + +/// Split a string '"one two" "three"' into 'one two', 'three' +/// Quote characters can be ` ' or " +inline std::vector split_up(std::string str, char delimiter = '\0') { + + const std::string delims("\'\"`"); + auto find_ws = [delimiter](char ch) { + return (delimiter == '\0') ? (std::isspace(ch, std::locale()) != 0) : (ch == delimiter); + }; + trim(str); + + std::vector output; + bool embeddedQuote = false; + char keyChar = ' '; + while(!str.empty()) { + if(delims.find_first_of(str[0]) != std::string::npos) { + keyChar = str[0]; + auto end = str.find_first_of(keyChar, 1); + while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes + end = str.find_first_of(keyChar, end + 1); + embeddedQuote = true; + } + if(end != std::string::npos) { + output.push_back(str.substr(1, end - 1)); + str = str.substr(end + 1); + } else { + output.push_back(str.substr(1)); + str = ""; + } + } else { + auto it = std::find_if(std::begin(str), std::end(str), find_ws); + if(it != std::end(str)) { + std::string value = std::string(str.begin(), it); + output.push_back(value); + str = std::string(it + 1, str.end()); + } else { + output.push_back(str); + str = ""; + } + } + // transform any embedded quotes into the regular character + if(embeddedQuote) { + output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar)); + embeddedQuote = false; + } + trim(str); + } + return output; +} + +/// Add a leader to the beginning of all new lines (nothing is added +/// at the start of the first line). `"; "` would be for ini files +/// +/// Can't use Regex, or this would be a subs. +inline std::string fix_newlines(const std::string &leader, std::string input) { + std::string::size_type n = 0; + while(n != std::string::npos && n < input.size()) { + n = input.find('\n', n); + if(n != std::string::npos) { + input = input.substr(0, n + 1) + leader + input.substr(n + 1); + n += leader.size(); + } + } + return input; +} + +/// This function detects an equal or colon followed by an escaped quote after an argument +/// then modifies the string to replace the equality with a space. This is needed +/// to allow the split up function to work properly and is intended to be used with the find_and_modify function +/// the return value is the offset+1 which is required by the find_and_modify function. +inline std::size_t escape_detect(std::string &str, std::size_t offset) { + auto next = str[offset + 1]; + if((next == '\"') || (next == '\'') || (next == '`')) { + auto astart = str.find_last_of("-/ \"\'`", offset - 1); + if(astart != std::string::npos) { + if(str[astart] == ((str[offset] == '=') ? '-' : '/')) + str[offset] = ' '; // interpret this as a space so the split_up works properly + } + } + return offset + 1; +} + +/// Add quotes if the string contains spaces +inline std::string &add_quotes_if_needed(std::string &str) { + if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) { + char quote = str.find('"') < str.find('\'') ? '\'' : '"'; + if(str.find(' ') != std::string::npos) { + str.insert(0, 1, quote); + str.append(1, quote); + } + } + return str; +} + +} // namespace detail + +} // namespace CLI + +// From Error.hpp: + +namespace CLI { + +// Use one of these on all error classes. +// These are temporary and are undef'd at the end of this file. +#define CLI11_ERROR_DEF(parent, name) \ + protected: \ + name(std::string ename, std::string msg, int exit_code) : parent(std::move(ename), std::move(msg), exit_code) {} \ + name(std::string ename, std::string msg, ExitCodes exit_code) \ + : parent(std::move(ename), std::move(msg), exit_code) {} \ + \ + public: \ + name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \ + name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {} + +// This is added after the one above if a class is used directly and builds its own message +#define CLI11_ERROR_SIMPLE(name) \ + explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {} + +/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut, +/// int values from e.get_error_code(). +enum class ExitCodes { + Success = 0, + IncorrectConstruction = 100, + BadNameString, + OptionAlreadyAdded, + FileError, + ConversionError, + ValidationError, + RequiredError, + RequiresError, + ExcludesError, + ExtrasError, + ConfigError, + InvalidError, + HorribleError, + OptionNotFound, + ArgumentMismatch, + BaseClass = 127 +}; + +// Error definitions + +/// @defgroup error_group Errors +/// @brief Errors thrown by CLI11 +/// +/// These are the errors that can be thrown. Some of them, like CLI::Success, are not really errors. +/// @{ + +/// All errors derive from this one +class Error : public std::runtime_error { + int actual_exit_code; + std::string error_name{"Error"}; + + public: + int get_exit_code() const { return actual_exit_code; } + + std::string get_name() const { return error_name; } + + Error(std::string name, std::string msg, int exit_code = static_cast(ExitCodes::BaseClass)) + : runtime_error(msg), actual_exit_code(exit_code), error_name(std::move(name)) {} + + Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast(exit_code)) {} +}; + +// Note: Using Error::Error constructors does not work on GCC 4.7 + +/// Construction errors (not in parsing) +class ConstructionError : public Error { + CLI11_ERROR_DEF(Error, ConstructionError) +}; + +/// Thrown when an option is set to conflicting values (non-vector and multi args, for example) +class IncorrectConstruction : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction) + CLI11_ERROR_SIMPLE(IncorrectConstruction) + static IncorrectConstruction PositionalFlag(std::string name) { + return IncorrectConstruction(name + ": Flags cannot be positional"); + } + static IncorrectConstruction Set0Opt(std::string name) { + return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead"); + } + static IncorrectConstruction SetFlag(std::string name) { + return IncorrectConstruction(name + ": Cannot set an expected number for flags"); + } + static IncorrectConstruction ChangeNotVector(std::string name) { + return IncorrectConstruction(name + ": You can only change the expected arguments for vectors"); + } + static IncorrectConstruction AfterMultiOpt(std::string name) { + return IncorrectConstruction( + name + ": You can't change expected arguments after you've changed the multi option policy!"); + } + static IncorrectConstruction MissingOption(std::string name) { + return IncorrectConstruction("Option " + name + " is not defined"); + } + static IncorrectConstruction MultiOptionPolicy(std::string name) { + return IncorrectConstruction(name + ": multi_option_policy only works for flags and exact value options"); + } +}; + +/// Thrown on construction of a bad name +class BadNameString : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, BadNameString) + CLI11_ERROR_SIMPLE(BadNameString) + static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); } + static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); } + static BadNameString DashesOnly(std::string name) { + return BadNameString("Must have a name, not just dashes: " + name); + } + static BadNameString MultiPositionalNames(std::string name) { + return BadNameString("Only one positional name allowed, remove: " + name); + } +}; + +/// Thrown when an option already exists +class OptionAlreadyAdded : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded) + explicit OptionAlreadyAdded(std::string name) + : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {} + static OptionAlreadyAdded Requires(std::string name, std::string other) { + return OptionAlreadyAdded(name + " requires " + other, ExitCodes::OptionAlreadyAdded); + } + static OptionAlreadyAdded Excludes(std::string name, std::string other) { + return OptionAlreadyAdded(name + " excludes " + other, ExitCodes::OptionAlreadyAdded); + } +}; + +// Parsing errors + +/// Anything that can error in Parse +class ParseError : public Error { + CLI11_ERROR_DEF(Error, ParseError) +}; + +// Not really "errors" + +/// This is a successful completion on parsing, supposed to exit +class Success : public ParseError { + CLI11_ERROR_DEF(ParseError, Success) + Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {} +}; + +/// -h or --help on command line +class CallForHelp : public ParseError { + CLI11_ERROR_DEF(ParseError, CallForHelp) + CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// Usually something like --help-all on command line +class CallForAllHelp : public ParseError { + CLI11_ERROR_DEF(ParseError, CallForAllHelp) + CallForAllHelp() + : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code. +class RuntimeError : public ParseError { + CLI11_ERROR_DEF(ParseError, RuntimeError) + explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {} +}; + +/// Thrown when parsing an INI file and it is missing +class FileError : public ParseError { + CLI11_ERROR_DEF(ParseError, FileError) + CLI11_ERROR_SIMPLE(FileError) + static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); } +}; + +/// Thrown when conversion call back fails, such as when an int fails to coerce to a string +class ConversionError : public ParseError { + CLI11_ERROR_DEF(ParseError, ConversionError) + CLI11_ERROR_SIMPLE(ConversionError) + ConversionError(std::string member, std::string name) + : ConversionError("The value " + member + " is not an allowed value for " + name) {} + ConversionError(std::string name, std::vector results) + : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {} + static ConversionError TooManyInputsFlag(std::string name) { + return ConversionError(name + ": too many inputs for a flag"); + } + static ConversionError TrueFalse(std::string name) { + return ConversionError(name + ": Should be true/false or a number"); + } +}; + +/// Thrown when validation of results fails +class ValidationError : public ParseError { + CLI11_ERROR_DEF(ParseError, ValidationError) + CLI11_ERROR_SIMPLE(ValidationError) + explicit ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {} +}; + +/// Thrown when a required option is missing +class RequiredError : public ParseError { + CLI11_ERROR_DEF(ParseError, RequiredError) + explicit RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {} + static RequiredError Subcommand(std::size_t min_subcom) { + if(min_subcom == 1) { + return RequiredError("A subcommand"); + } + return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands", + ExitCodes::RequiredError); + } + static RequiredError + Option(std::size_t min_option, std::size_t max_option, std::size_t used, const std::string &option_list) { + if((min_option == 1) && (max_option == 1) && (used == 0)) + return RequiredError("Exactly 1 option from [" + option_list + "]"); + if((min_option == 1) && (max_option == 1) && (used > 1)) { + return RequiredError("Exactly 1 option from [" + option_list + "] is required and " + std::to_string(used) + + " were given", + ExitCodes::RequiredError); + } + if((min_option == 1) && (used == 0)) + return RequiredError("At least 1 option from [" + option_list + "]"); + if(used < min_option) { + return RequiredError("Requires at least " + std::to_string(min_option) + " options used and only " + + std::to_string(used) + "were given from [" + option_list + "]", + ExitCodes::RequiredError); + } + if(max_option == 1) + return RequiredError("Requires at most 1 options be given from [" + option_list + "]", + ExitCodes::RequiredError); + + return RequiredError("Requires at most " + std::to_string(max_option) + " options be used and " + + std::to_string(used) + "were given from [" + option_list + "]", + ExitCodes::RequiredError); + } +}; + +/// Thrown when the wrong number of arguments has been received +class ArgumentMismatch : public ParseError { + CLI11_ERROR_DEF(ParseError, ArgumentMismatch) + CLI11_ERROR_SIMPLE(ArgumentMismatch) + ArgumentMismatch(std::string name, int expected, std::size_t received) + : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name + + ", got " + std::to_string(received)) + : ("Expected at least " + std::to_string(-expected) + " arguments to " + name + + ", got " + std::to_string(received)), + ExitCodes::ArgumentMismatch) {} + + static ArgumentMismatch AtLeast(std::string name, int num, std::size_t received) { + return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required but received " + + std::to_string(received)); + } + static ArgumentMismatch AtMost(std::string name, int num, std::size_t received) { + return ArgumentMismatch(name + ": At Most " + std::to_string(num) + " required but received " + + std::to_string(received)); + } + static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) { + return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing"); + } + static ArgumentMismatch FlagOverride(std::string name) { + return ArgumentMismatch(name + " was given a disallowed flag override"); + } +}; + +/// Thrown when a requires option is missing +class RequiresError : public ParseError { + CLI11_ERROR_DEF(ParseError, RequiresError) + RequiresError(std::string curname, std::string subname) + : RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {} +}; + +/// Thrown when an excludes option is present +class ExcludesError : public ParseError { + CLI11_ERROR_DEF(ParseError, ExcludesError) + ExcludesError(std::string curname, std::string subname) + : ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {} +}; + +/// Thrown when too many positionals or options are found +class ExtrasError : public ParseError { + CLI11_ERROR_DEF(ParseError, ExtrasError) + explicit ExtrasError(std::vector args) + : ExtrasError((args.size() > 1 ? "The following arguments were not expected: " + : "The following argument was not expected: ") + + detail::rjoin(args, " "), + ExitCodes::ExtrasError) {} + ExtrasError(const std::string &name, std::vector args) + : ExtrasError(name, + (args.size() > 1 ? "The following arguments were not expected: " + : "The following argument was not expected: ") + + detail::rjoin(args, " "), + ExitCodes::ExtrasError) {} +}; + +/// Thrown when extra values are found in an INI file +class ConfigError : public ParseError { + CLI11_ERROR_DEF(ParseError, ConfigError) + CLI11_ERROR_SIMPLE(ConfigError) + static ConfigError Extras(std::string item) { return ConfigError("INI was not able to parse " + item); } + static ConfigError NotConfigurable(std::string item) { + return ConfigError(item + ": This option is not allowed in a configuration file"); + } +}; + +/// Thrown when validation fails before parsing +class InvalidError : public ParseError { + CLI11_ERROR_DEF(ParseError, InvalidError) + explicit InvalidError(std::string name) + : InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) { + } +}; + +/// This is just a safety check to verify selection and parsing match - you should not ever see it +/// Strings are directly added to this error, but again, it should never be seen. +class HorribleError : public ParseError { + CLI11_ERROR_DEF(ParseError, HorribleError) + CLI11_ERROR_SIMPLE(HorribleError) +}; + +// After parsing + +/// Thrown when counting a non-existent option +class OptionNotFound : public Error { + CLI11_ERROR_DEF(Error, OptionNotFound) + explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {} +}; + +#undef CLI11_ERROR_DEF +#undef CLI11_ERROR_SIMPLE + +/// @} + +} // namespace CLI + +// From TypeTools.hpp: + +namespace CLI { + +// Type tools + +// Utilities for type enabling +namespace detail { +// Based generally on https://rmf.io/cxx11/almost-static-if +/// Simple empty scoped class +enum class enabler {}; + +/// An instance to use in EnableIf +constexpr enabler dummy = {}; +} // namespace detail + +/// A copy of enable_if_t from C++14, compatible with C++11. +/// +/// We could check to see if C++14 is being used, but it does not hurt to redefine this +/// (even Google does this: https://github.com/google/skia/blob/master/include/private/SkTLogic.h) +/// It is not in the std namespace anyway, so no harm done. +template using enable_if_t = typename std::enable_if::type; + +/// A copy of std::void_t from C++17 (helper for C++11 and C++14) +template struct make_void { using type = void; }; + +/// A copy of std::void_t from C++17 - same reasoning as enable_if_t, it does not hurt to redefine +template using void_t = typename make_void::type; + +/// A copy of std::conditional_t from C++14 - same reasoning as enable_if_t, it does not hurt to redefine +template using conditional_t = typename std::conditional::type; + +/// Check to see if something is a vector (fail check by default) +template struct is_vector : std::false_type {}; + +/// Check to see if something is a vector (true if actually a vector) +template struct is_vector> : std::true_type {}; + +/// Check to see if something is a vector (true if actually a const vector) +template struct is_vector> : std::true_type {}; + +/// Check to see if something is bool (fail check by default) +template struct is_bool : std::false_type {}; + +/// Check to see if something is bool (true if actually a bool) +template <> struct is_bool : std::true_type {}; + +/// Check to see if something is a shared pointer +template struct is_shared_ptr : std::false_type {}; + +/// Check to see if something is a shared pointer (True if really a shared pointer) +template struct is_shared_ptr> : std::true_type {}; + +/// Check to see if something is a shared pointer (True if really a shared pointer) +template struct is_shared_ptr> : std::true_type {}; + +/// Check to see if something is copyable pointer +template struct is_copyable_ptr { + static bool const value = is_shared_ptr::value || std::is_pointer::value; +}; + +/// This can be specialized to override the type deduction for IsMember. +template struct IsMemberType { using type = T; }; + +/// The main custom type needed here is const char * should be a string. +template <> struct IsMemberType { using type = std::string; }; + +namespace detail { + +// These are utilities for IsMember and other transforming objects + +/// Handy helper to access the element_type generically. This is not part of is_copyable_ptr because it requires that +/// pointer_traits be valid. + +/// not a pointer +template struct element_type { using type = T; }; + +template struct element_type::value>::type> { + using type = typename std::pointer_traits::element_type; +}; + +/// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of +/// the container +template struct element_value_type { using type = typename element_type::type::value_type; }; + +/// Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost nothing. +template struct pair_adaptor : std::false_type { + using value_type = typename T::value_type; + using first_type = typename std::remove_const::type; + using second_type = typename std::remove_const::type; + + /// Get the first value (really just the underlying value) + template static auto first(Q &&pair_value) -> decltype(std::forward(pair_value)) { + return std::forward(pair_value); + } + /// Get the second value (really just the underlying value) + template static auto second(Q &&pair_value) -> decltype(std::forward(pair_value)) { + return std::forward(pair_value); + } +}; + +/// Adaptor for map-like structure (true version, must have key_type and mapped_type). +/// This wraps a mapped container in a few utilities access it in a general way. +template +struct pair_adaptor< + T, + conditional_t, void>> + : std::true_type { + using value_type = typename T::value_type; + using first_type = typename std::remove_const::type; + using second_type = typename std::remove_const::type; + + /// Get the first value (really just the underlying value) + template static auto first(Q &&pair_value) -> decltype(std::get<0>(std::forward(pair_value))) { + return std::get<0>(std::forward(pair_value)); + } + /// Get the second value (really just the underlying value) + template static auto second(Q &&pair_value) -> decltype(std::get<1>(std::forward(pair_value))) { + return std::get<1>(std::forward(pair_value)); + } +}; + +// Warning is suppressed due to "bug" in gcc<5.0 and gcc 7.0 with c++17 enabled that generates a Wnarrowing warning +// in the unevaluated context even if the function that was using this wasn't used. The standard says narrowing in +// brace initialization shouldn't be allowed but for backwards compatibility gcc allows it in some contexts. It is a +// little fuzzy what happens in template constructs and I think that was something GCC took a little while to work out. +// But regardless some versions of gcc generate a warning when they shouldn't from the following code so that should be +// suppressed +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnarrowing" +#endif +// check for constructibility from a specific type and copy assignable used in the parse detection +template class is_direct_constructible { + template + static auto test(int, std::true_type) -> decltype( +// NVCC warns about narrowing conversions here +#ifdef __CUDACC__ +#pragma diag_suppress 2361 +#endif + TT { std::declval() } +#ifdef __CUDACC__ +#pragma diag_default 2361 +#endif + , + std::is_move_assignable()); + + template static auto test(int, std::false_type) -> std::false_type; + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0, typename std::is_constructible::type()))::value; +}; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +// Check for output streamability +// Based on https://stackoverflow.com/questions/22758291/how-can-i-detect-if-a-type-can-be-streamed-to-an-stdostream + +template class is_ostreamable { + template + static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Check for input streamability +template class is_istreamable { + template + static auto test(int) -> decltype(std::declval() >> std::declval(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Templated operation to get a value from a stream +template ::value, detail::enabler> = detail::dummy> +bool from_stream(const std::string &istring, T &obj) { + std::istringstream is; + is.str(istring); + is >> obj; + return !is.fail() && !is.rdbuf()->in_avail(); +} + +template ::value, detail::enabler> = detail::dummy> +bool from_stream(const std::string & /*istring*/, T & /*obj*/) { + return false; +} + +// Check for tuple like types, as in classes with a tuple_size type trait +template class is_tuple_like { + template + // static auto test(int) + // -> decltype(std::conditional<(std::tuple_size::value > 0), std::true_type, std::false_type>::type()); + static auto test(int) -> decltype(std::tuple_size::value, std::true_type{}); + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Convert an object to a string (directly forward if this can become a string) +template ::value, detail::enabler> = detail::dummy> +auto to_string(T &&value) -> decltype(std::forward(value)) { + return std::forward(value); +} + +/// Construct a string from the object +template ::value && !std::is_convertible::value, + detail::enabler> = detail::dummy> +std::string to_string(const T &value) { + return std::string(value); +} + +/// Convert an object to a string (streaming must be supported for that type) +template ::value && !std::is_constructible::value && + is_ostreamable::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&value) { + std::stringstream stream; + stream << value; + return stream.str(); +} + +/// If conversion is not supported, return an empty string (streaming is not supported for that type) +template ::value && !is_ostreamable::value && + !is_vector::type>::type>::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&) { + return std::string{}; +} + +/// convert a vector to a string +template ::value && !is_ostreamable::value && + is_vector::type>::type>::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&variable) { + std::vector defaults; + defaults.reserve(variable.size()); + auto cval = variable.begin(); + auto end = variable.end(); + while(cval != end) { + defaults.emplace_back(CLI::detail::to_string(*cval)); + ++cval; + } + return std::string("[" + detail::join(defaults) + "]"); +} + +/// special template overload +template ::value, detail::enabler> = detail::dummy> +auto checked_to_string(T &&value) -> decltype(to_string(std::forward(value))) { + return to_string(std::forward(value)); +} + +/// special template overload +template ::value, detail::enabler> = detail::dummy> +std::string checked_to_string(T &&) { + return std::string{}; +} +/// get a string as a convertible value for arithmetic types +template ::value, detail::enabler> = detail::dummy> +std::string value_string(const T &value) { + return std::to_string(value); +} +/// get a string as a convertible value for enumerations +template ::value, detail::enabler> = detail::dummy> +std::string value_string(const T &value) { + return std::to_string(static_cast::type>(value)); +} +/// for other types just use the regular to_string function +template ::value && !std::is_arithmetic::value, detail::enabler> = detail::dummy> +auto value_string(const T &value) -> decltype(to_string(value)) { + return to_string(value); +} + +/// This will only trigger for actual void type +template struct type_count { static const int value{0}; }; + +/// Set of overloads to get the type size of an object +template struct type_count::value>::type> { + static constexpr int value{std::tuple_size::value}; +}; +/// Type size for regular object types that do not look like a tuple +template +struct type_count< + T, + typename std::enable_if::value && !is_tuple_like::value && !std::is_void::value>::type> { + static constexpr int value{1}; +}; + +/// Type size of types that look like a vector +template struct type_count::value>::type> { + static constexpr int value{is_vector::value ? expected_max_vector_size + : type_count::value}; +}; + +/// This will only trigger for actual void type +template struct expected_count { static const int value{0}; }; + +/// For most types the number of expected items is 1 +template +struct expected_count::value && !std::is_void::value>::type> { + static constexpr int value{1}; +}; +/// number of expected items in a vector +template struct expected_count::value>::type> { + static constexpr int value{expected_max_vector_size}; +}; + +// Enumeration of the different supported categorizations of objects +enum class object_category : int { + integral_value = 2, + unsigned_integral = 4, + enumeration = 6, + boolean_value = 8, + floating_point = 10, + number_constructible = 12, + double_constructible = 14, + integer_constructible = 16, + vector_value = 30, + tuple_value = 35, + // string assignable or greater used in a condition so anything string like must come last + string_assignable = 50, + string_constructible = 60, + other = 200, + +}; + +/// some type that is not otherwise recognized +template struct classify_object { + static constexpr object_category value{object_category::other}; +}; + +/// Set of overloads to classify an object according to type +template +struct classify_object::value && std::is_signed::value && + !is_bool::value && !std::is_enum::value>::type> { + static constexpr object_category value{object_category::integral_value}; +}; + +/// Unsigned integers +template +struct classify_object< + T, + typename std::enable_if::value && std::is_unsigned::value && !is_bool::value>::type> { + static constexpr object_category value{object_category::unsigned_integral}; +}; + +/// Boolean values +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::boolean_value}; +}; + +/// Floats +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::floating_point}; +}; + +/// String and similar direct assignment +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && + std::is_assignable::value && !is_vector::value>::type> { + static constexpr object_category value{object_category::string_assignable}; +}; + +/// String and similar constructible and copy assignment +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && + !std::is_assignable::value && + std::is_constructible::value && !is_vector::value>::type> { + static constexpr object_category value{object_category::string_constructible}; +}; + +/// Enumerations +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::enumeration}; +}; + +/// Handy helper to contain a bunch of checks that rule out many common types (integers, string like, floating point, +/// vectors, and enumerations +template struct uncommon_type { + using type = typename std::conditional::value && !std::is_integral::value && + !std::is_assignable::value && + !std::is_constructible::value && !is_vector::value && + !std::is_enum::value, + std::true_type, + std::false_type>::type; + static constexpr bool value = type::value; +}; + +/// Assignable from double or int +template +struct classify_object::value && type_count::value == 1 && + is_direct_constructible::value && + is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::number_constructible}; +}; + +/// Assignable from int +template +struct classify_object::value && type_count::value == 1 && + !is_direct_constructible::value && + is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::integer_constructible}; +}; + +/// Assignable from double +template +struct classify_object::value && type_count::value == 1 && + is_direct_constructible::value && + !is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::double_constructible}; +}; + +/// Tuple type +template +struct classify_object::value >= 2 && !is_vector::value) || + (is_tuple_like::value && uncommon_type::value && + !is_direct_constructible::value && + !is_direct_constructible::value)>::type> { + static constexpr object_category value{object_category::tuple_value}; +}; + +/// Vector type +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::vector_value}; +}; + +// Type name print + +/// Was going to be based on +/// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template +/// But this is cleaner and works better in this case + +template ::value == object_category::integral_value || + classify_object::value == object_category::integer_constructible, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "INT"; +} + +template ::value == object_category::unsigned_integral, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "UINT"; +} + +template ::value == object_category::floating_point || + classify_object::value == object_category::number_constructible || + classify_object::value == object_category::double_constructible, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "FLOAT"; +} + +/// Print name for enumeration types +template ::value == object_category::enumeration, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "ENUM"; +} + +/// Print name for enumeration types +template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "BOOLEAN"; +} + +/// Print for all other types +template ::value >= object_category::string_assignable, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "TEXT"; +} + +/// Print name for single element tuple types +template ::value == object_category::tuple_value && type_count::value == 1, + detail::enabler> = detail::dummy> +inline std::string type_name() { + return type_name::type>(); +} + +/// Empty string if the index > tuple size +template +inline typename std::enable_if::value, std::string>::type tuple_name() { + return std::string{}; +} + +/// Recursively generate the tuple type name +template + inline typename std::enable_if < I::value, std::string>::type tuple_name() { + std::string str = std::string(type_name::type>()) + ',' + tuple_name(); + if(str.back() == ',') + str.pop_back(); + return str; +} + +/// Print type name for tuples with 2 or more elements +template ::value == object_category::tuple_value && type_count::value >= 2, + detail::enabler> = detail::dummy> +std::string type_name() { + auto tname = std::string(1, '[') + tuple_name(); + tname.push_back(']'); + return tname; +} + +/// This one should not be used normally, since vector types print the internal type +template ::value == object_category::vector_value, detail::enabler> = detail::dummy> +inline std::string type_name() { + return type_name(); +} + +// Lexical cast + +/// Convert a flag into an integer value typically binary flags +inline std::int64_t to_flag_value(std::string val) { + static const std::string trueString("true"); + static const std::string falseString("false"); + if(val == trueString) { + return 1; + } + if(val == falseString) { + return -1; + } + val = detail::to_lower(val); + std::int64_t ret; + if(val.size() == 1) { + if(val[0] >= '1' && val[0] <= '9') { + return (static_cast(val[0]) - '0'); + } + switch(val[0]) { + case '0': + case 'f': + case 'n': + case '-': + ret = -1; + break; + case 't': + case 'y': + case '+': + ret = 1; + break; + default: + throw std::invalid_argument("unrecognized character"); + } + return ret; + } + if(val == trueString || val == "on" || val == "yes" || val == "enable") { + ret = 1; + } else if(val == falseString || val == "off" || val == "no" || val == "disable") { + ret = -1; + } else { + ret = std::stoll(val); + } + return ret; +} + +/// Signed integers +template ::value == object_category::integral_value, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + try { + std::size_t n = 0; + std::int64_t output_ll = std::stoll(input, &n, 0); + output = static_cast(output_ll); + return n == input.size() && static_cast(output) == output_ll; + } catch(const std::invalid_argument &) { + return false; + } catch(const std::out_of_range &) { + return false; + } +} + +/// Unsigned integers +template ::value == object_category::unsigned_integral, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + if(!input.empty() && input.front() == '-') + return false; // std::stoull happily converts negative values to junk without any errors. + + try { + std::size_t n = 0; + std::uint64_t output_ll = std::stoull(input, &n, 0); + output = static_cast(output_ll); + return n == input.size() && static_cast(output) == output_ll; + } catch(const std::invalid_argument &) { + return false; + } catch(const std::out_of_range &) { + return false; + } +} + +/// Boolean values +template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + try { + auto out = to_flag_value(input); + output = (out > 0); + return true; + } catch(const std::invalid_argument &) { + return false; + } catch(const std::out_of_range &) { + // if the number is out of the range of a 64 bit value then it is still a number and for this purpose is still + // valid all we care about the sign + output = (input[0] != '-'); + return true; + } +} + +/// Floats +template ::value == object_category::floating_point, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + try { + std::size_t n = 0; + output = static_cast(std::stold(input, &n)); + return n == input.size(); + } catch(const std::invalid_argument &) { + return false; + } catch(const std::out_of_range &) { + return false; + } +} + +/// String and similar direct assignment +template ::value == object_category::string_assignable, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = input; + return true; +} + +/// String and similar constructible and copy assignment +template < + typename T, + enable_if_t::value == object_category::string_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = T(input); + return true; +} + +/// Enumerations +template ::value == object_category::enumeration, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename std::underlying_type::type val; + bool retval = detail::lexical_cast(input, val); + if(!retval) { + return false; + } + output = static_cast(val); + return true; +} + +/// Assignable from double or int +template < + typename T, + enable_if_t::value == object_category::number_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val; + if(lexical_cast(input, val)) { + output = T(val); + return true; + } else { + double dval; + if(lexical_cast(input, dval)) { + output = T{dval}; + return true; + } + } + return from_stream(input, output); +} + +/// Assignable from int +template < + typename T, + enable_if_t::value == object_category::integer_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val; + if(lexical_cast(input, val)) { + output = T(val); + return true; + } + return from_stream(input, output); +} + +/// Assignable from double +template < + typename T, + enable_if_t::value == object_category::double_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + double val; + if(lexical_cast(input, val)) { + output = T{val}; + return true; + } + return from_stream(input, output); +} + +/// Non-string parsable by a stream +template ::value == object_category::other, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + static_assert(is_istreamable::value, + "option object type must have a lexical cast overload or streaming input operator(>>) defined, if it " + "is convertible from another type use the add_option(...) with XC being the known type"); + return from_stream(input, output); +} + +/// Assign a value through lexical cast operations +template < + typename T, + typename XC, + enable_if_t::value && (classify_object::value == object_category::string_assignable || + classify_object::value == object_category::string_constructible), + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, T &output) { + return lexical_cast(input, output); +} + +/// Assign a value through lexical cast operations +template ::value && classify_object::value != object_category::string_assignable && + classify_object::value != object_category::string_constructible, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, T &output) { + if(input.empty()) { + output = T{}; + return true; + } + return lexical_cast(input, output); +} + +/// Assign a value converted from a string in lexical cast to the output value directly +template < + typename T, + typename XC, + enable_if_t::value && std::is_assignable::value, detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, T &output) { + XC val{}; + bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; + if(parse_result) { + output = val; + } + return parse_result; +} + +/// Assign a value from a lexical cast through constructing a value and move assigning it +template ::value && !std::is_assignable::value && + std::is_move_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, T &output) { + XC val{}; + bool parse_result = input.empty() ? true : lexical_cast(input, val); + if(parse_result) { + output = T(val); // use () form of constructor to allow some implicit conversions + } + return parse_result; +} +/// Lexical conversion if there is only one element +template < + typename T, + typename XC, + enable_if_t::value && !is_tuple_like::value && !is_vector::value && !is_vector::value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + return lexical_assign(strings[0], output); +} + +/// Lexical conversion if there is only one element but the conversion type is for two call a two element constructor +template ::value == 1 && type_count::value == 2, detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + typename std::tuple_element<0, XC>::type v1; + typename std::tuple_element<1, XC>::type v2; + bool retval = lexical_assign(strings[0], v1); + if(strings.size() > 1) { + retval = retval && lexical_assign(strings[1], v2); + } + if(retval) { + output = T{v1, v2}; + } + return retval; +} + +/// Lexical conversion of a vector types +template ::value == expected_max_vector_size && + expected_count::value == expected_max_vector_size && type_count::value == 1, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + output.clear(); + output.reserve(strings.size()); + for(const auto &elem : strings) { + + output.emplace_back(); + bool retval = lexical_assign(elem, output.back()); + if(!retval) { + return false; + } + } + return (!output.empty()); +} + +/// Lexical conversion of a vector types with type size of two +template ::value == expected_max_vector_size && + expected_count::value == expected_max_vector_size && type_count::value == 2, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + output.clear(); + for(std::size_t ii = 0; ii < strings.size(); ii += 2) { + + typename std::tuple_element<0, typename XC::value_type>::type v1; + typename std::tuple_element<1, typename XC::value_type>::type v2; + bool retval = lexical_assign(strings[ii], v1); + if(strings.size() > ii + 1) { + retval = retval && lexical_assign(strings[ii + 1], v2); + } + if(retval) { + output.emplace_back(v1, v2); + } else { + return false; + } + } + return (!output.empty()); +} + +/// Conversion to a vector type using a particular single type as the conversion type +template ::value == expected_max_vector_size) && (expected_count::value == 1) && + (type_count::value == 1), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + bool retval = true; + output.clear(); + output.reserve(strings.size()); + for(const auto &elem : strings) { + + output.emplace_back(); + retval = retval && lexical_assign(elem, output.back()); + } + return (!output.empty()) && retval; +} +// This one is last since it can call other lexical_conversion functions +/// Lexical conversion if there is only one element but the conversion type is a vector +template ::value && !is_vector::value && is_vector::value, detail::enabler> = + detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + + if(strings.size() > 1 || (!strings.empty() && !(strings.front().empty()))) { + XC val; + auto retval = lexical_conversion(strings, val); + output = T{val}; + return retval; + } + output = T{}; + return true; +} + +/// function template for converting tuples if the static Index is greater than the tuple size +template +inline typename std::enable_if= type_count::value, bool>::type tuple_conversion(const std::vector &, + T &) { + return true; +} +/// Tuple conversion operation +template + inline typename std::enable_if < + I::value, bool>::type tuple_conversion(const std::vector &strings, T &output) { + bool retval = true; + if(strings.size() > I) { + retval = retval && lexical_assign::type, + typename std::conditional::value, + typename std::tuple_element::type, + XC>::type>(strings[I], std::get(output)); + } + retval = retval && tuple_conversion(strings, output); + return retval; +} + +/// Conversion for tuples +template ::value, detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + static_assert( + !is_tuple_like::value || type_count::value == type_count::value, + "if the conversion type is defined as a tuple it must be the same size as the type you are converting to"); + return tuple_conversion(strings, output); +} + +/// Lexical conversion of a vector types with type_size >2 +template ::value == expected_max_vector_size && + expected_count::value == expected_max_vector_size && (type_count::value > 2), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, T &output) { + bool retval = true; + output.clear(); + std::vector temp; + std::size_t ii = 0; + std::size_t icount = 0; + std::size_t xcm = type_count::value; + while(ii < strings.size()) { + temp.push_back(strings[ii]); + ++ii; + ++icount; + if(icount == xcm || temp.back().empty()) { + if(static_cast(xcm) == expected_max_vector_size) { + temp.pop_back(); + } + output.emplace_back(); + retval = retval && lexical_conversion(temp, output.back()); + temp.clear(); + if(!retval) { + return false; + } + icount = 0; + } + } + return retval; +} +/// Sum a vector of flag representations +/// The flag vector produces a series of strings in a vector, simple true is represented by a "1", simple false is +/// by +/// "-1" an if numbers are passed by some fashion they are captured as well so the function just checks for the most +/// common true and false strings then uses stoll to convert the rest for summing +template ::value && std::is_unsigned::value, detail::enabler> = detail::dummy> +void sum_flag_vector(const std::vector &flags, T &output) { + std::int64_t count{0}; + for(auto &flag : flags) { + count += detail::to_flag_value(flag); + } + output = (count > 0) ? static_cast(count) : T{0}; +} + +/// Sum a vector of flag representations +/// The flag vector produces a series of strings in a vector, simple true is represented by a "1", simple false is +/// by +/// "-1" an if numbers are passed by some fashion they are captured as well so the function just checks for the most +/// common true and false strings then uses stoll to convert the rest for summing +template ::value && std::is_signed::value, detail::enabler> = detail::dummy> +void sum_flag_vector(const std::vector &flags, T &output) { + std::int64_t count{0}; + for(auto &flag : flags) { + count += detail::to_flag_value(flag); + } + output = static_cast(count); +} + +} // namespace detail +} // namespace CLI + +// From Split.hpp: + +namespace CLI { +namespace detail { + +// Returns false if not a short option. Otherwise, sets opt name and rest and returns true +inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) { + if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) { + name = current.substr(1, 1); + rest = current.substr(2); + return true; + } + return false; +} + +// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true +inline bool split_long(const std::string ¤t, std::string &name, std::string &value) { + if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) { + auto loc = current.find_first_of('='); + if(loc != std::string::npos) { + name = current.substr(2, loc - 2); + value = current.substr(loc + 1); + } else { + name = current.substr(2); + value = ""; + } + return true; + } + return false; +} + +// Returns false if not a windows style option. Otherwise, sets opt name and value and returns true +inline bool split_windows_style(const std::string ¤t, std::string &name, std::string &value) { + if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) { + auto loc = current.find_first_of(':'); + if(loc != std::string::npos) { + name = current.substr(1, loc - 1); + value = current.substr(loc + 1); + } else { + name = current.substr(1); + value = ""; + } + return true; + } + return false; +} + +// Splits a string into multiple long and short names +inline std::vector split_names(std::string current) { + std::vector output; + std::size_t val; + while((val = current.find(",")) != std::string::npos) { + output.push_back(trim_copy(current.substr(0, val))); + current = current.substr(val + 1); + } + output.push_back(trim_copy(current)); + return output; +} + +/// extract default flag values either {def} or starting with a ! +inline std::vector> get_default_flag_values(const std::string &str) { + std::vector flags = split_names(str); + flags.erase(std::remove_if(flags.begin(), + flags.end(), + [](const std::string &name) { + return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) && + (name.back() == '}')) || + (name[0] == '!')))); + }), + flags.end()); + std::vector> output; + output.reserve(flags.size()); + for(auto &flag : flags) { + auto def_start = flag.find_first_of('{'); + std::string defval = "false"; + if((def_start != std::string::npos) && (flag.back() == '}')) { + defval = flag.substr(def_start + 1); + defval.pop_back(); + flag.erase(def_start, std::string::npos); + } + flag.erase(0, flag.find_first_not_of("-!")); + output.emplace_back(flag, defval); + } + return output; +} + +/// Get a vector of short names, one of long names, and a single name +inline std::tuple, std::vector, std::string> +get_names(const std::vector &input) { + + std::vector short_names; + std::vector long_names; + std::string pos_name; + + for(std::string name : input) { + if(name.length() == 0) { + continue; + } + if(name.length() > 1 && name[0] == '-' && name[1] != '-') { + if(name.length() == 2 && valid_first_char(name[1])) + short_names.emplace_back(1, name[1]); + else + throw BadNameString::OneCharName(name); + } else if(name.length() > 2 && name.substr(0, 2) == "--") { + name = name.substr(2); + if(valid_name_string(name)) + long_names.push_back(name); + else + throw BadNameString::BadLongName(name); + } else if(name == "-" || name == "--") { + throw BadNameString::DashesOnly(name); + } else { + if(pos_name.length() > 0) + throw BadNameString::MultiPositionalNames(name); + pos_name = name; + } + } + + return std::tuple, std::vector, std::string>( + short_names, long_names, pos_name); +} + +} // namespace detail +} // namespace CLI + +// From ConfigFwd.hpp: + +namespace CLI { + +class App; + +/// Holds values to load into Options +struct ConfigItem { + /// This is the list of parents + std::vector parents{}; + + /// This is the name + std::string name{}; + + /// Listing of inputs + std::vector inputs{}; + + /// The list of parents and name joined by "." + std::string fullname() const { + std::vector tmp = parents; + tmp.emplace_back(name); + return detail::join(tmp, "."); + } +}; + +/// This class provides a converter for configuration files. +class Config { + protected: + std::vector items{}; + + public: + /// Convert an app into a configuration + virtual std::string to_config(const App *, bool, bool, std::string) const = 0; + + /// Convert a configuration into an app + virtual std::vector from_config(std::istream &) const = 0; + + /// Get a flag value + virtual std::string to_flag(const ConfigItem &item) const { + if(item.inputs.size() == 1) { + return item.inputs.at(0); + } + throw ConversionError::TooManyInputsFlag(item.fullname()); + } + + /// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure + std::vector from_file(const std::string &name) { + std::ifstream input{name}; + if(!input.good()) + throw FileError::Missing(name); + + return from_config(input); + } + + /// Virtual destructor + virtual ~Config() = default; +}; + +/// This converter works with INI/TOML files; to write proper TOML files use ConfigTOML +class ConfigBase : public Config { + protected: + /// the character used for comments + char commentChar = ';'; + /// the character used to start an array '\0' is a default to not use + char arrayStart = '\0'; + /// the character used to end an array '\0' is a default to not use + char arrayEnd = '\0'; + /// the character used to separate elements in an array + char arraySeparator = ' '; + /// the character used separate the name from the value + char valueDelimiter = '='; + + public: + std::string + to_config(const App * /*app*/, bool default_also, bool write_description, std::string prefix) const override; + + std::vector from_config(std::istream &input) const override; + /// Specify the configuration for comment characters + ConfigBase *comment(char cchar) { + commentChar = cchar; + return this; + } + /// Specify the start and end characters for an array + ConfigBase *arrayBounds(char aStart, char aEnd) { + arrayStart = aStart; + arrayEnd = aEnd; + return this; + } + /// Specify the delimiter character for an array + ConfigBase *arrayDelimiter(char aSep) { + arraySeparator = aSep; + return this; + } + /// Specify the delimiter between a name and value + ConfigBase *valueSeparator(char vSep) { + valueDelimiter = vSep; + return this; + } +}; + +/// the default Config is the INI file format +using ConfigINI = ConfigBase; + +/// ConfigTOML generates a TOML compliant output +class ConfigTOML : public ConfigINI { + + public: + ConfigTOML() { + commentChar = '#'; + arrayStart = '['; + arrayEnd = ']'; + arraySeparator = ','; + valueDelimiter = '='; + } +}; +} // namespace CLI + +// From Validators.hpp: + +namespace CLI { + +class Option; + +/// @defgroup validator_group Validators + +/// @brief Some validators that are provided +/// +/// These are simple `std::string(const std::string&)` validators that are useful. They return +/// a string if the validation fails. A custom struct is provided, as well, with the same user +/// semantics, but with the ability to provide a new type name. +/// @{ + +/// +class Validator { + protected: + /// This is the description function, if empty the description_ will be used + std::function desc_function_{[]() { return std::string{}; }}; + + /// This is the base function that is to be called. + /// Returns a string error message if validation fails. + std::function func_{[](std::string &) { return std::string{}; }}; + /// The name for search purposes of the Validator + std::string name_{}; + /// A Validator will only apply to an indexed value (-1 is all elements) + int application_index_ = -1; + /// Enable for Validator to allow it to be disabled if need be + bool active_{true}; + /// specify that a validator should not modify the input + bool non_modifying_{false}; + + public: + Validator() = default; + /// Construct a Validator with just the description string + explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {} + /// Construct Validator from basic information + Validator(std::function op, std::string validator_desc, std::string validator_name = "") + : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)), + name_(std::move(validator_name)) {} + /// Set the Validator operation function + Validator &operation(std::function op) { + func_ = std::move(op); + return *this; + } + /// This is the required operator for a Validator - provided to help + /// users (CLI11 uses the member `func` directly) + std::string operator()(std::string &str) const { + std::string retstring; + if(active_) { + if(non_modifying_) { + std::string value = str; + retstring = func_(value); + } else { + retstring = func_(str); + } + } + return retstring; + } + + /// This is the required operator for a Validator - provided to help + /// users (CLI11 uses the member `func` directly) + std::string operator()(const std::string &str) const { + std::string value = str; + return (active_) ? func_(value) : std::string{}; + } + + /// Specify the type string + Validator &description(std::string validator_desc) { + desc_function_ = [validator_desc]() { return validator_desc; }; + return *this; + } + /// Specify the type string + Validator description(std::string validator_desc) const { + Validator newval(*this); + newval.desc_function_ = [validator_desc]() { return validator_desc; }; + return newval; + } + /// Generate type description information for the Validator + std::string get_description() const { + if(active_) { + return desc_function_(); + } + return std::string{}; + } + /// Specify the type string + Validator &name(std::string validator_name) { + name_ = std::move(validator_name); + return *this; + } + /// Specify the type string + Validator name(std::string validator_name) const { + Validator newval(*this); + newval.name_ = std::move(validator_name); + return newval; + } + /// Get the name of the Validator + const std::string &get_name() const { return name_; } + /// Specify whether the Validator is active or not + Validator &active(bool active_val = true) { + active_ = active_val; + return *this; + } + /// Specify whether the Validator is active or not + Validator active(bool active_val = true) const { + Validator newval(*this); + newval.active_ = active_val; + return newval; + } + + /// Specify whether the Validator can be modifying or not + Validator &non_modifying(bool no_modify = true) { + non_modifying_ = no_modify; + return *this; + } + /// Specify the application index of a validator + Validator &application_index(int app_index) { + application_index_ = app_index; + return *this; + } + /// Specify the application index of a validator + Validator application_index(int app_index) const { + Validator newval(*this); + newval.application_index_ = app_index; + return newval; + } + /// Get the current value of the application index + int get_application_index() const { return application_index_; } + /// Get a boolean if the validator is active + bool get_active() const { return active_; } + + /// Get a boolean if the validator is allowed to modify the input returns true if it can modify the input + bool get_modifying() const { return !non_modifying_; } + + /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the + /// same. + Validator operator&(const Validator &other) const { + Validator newval; + + newval._merge_description(*this, other, " AND "); + + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + const std::function &f2 = other.func_; + + newval.func_ = [f1, f2](std::string &input) { + std::string s1 = f1(input); + std::string s2 = f2(input); + if(!s1.empty() && !s2.empty()) + return std::string("(") + s1 + ") AND (" + s2 + ")"; + else + return s1 + s2; + }; + + newval.active_ = (active_ & other.active_); + newval.application_index_ = application_index_; + return newval; + } + + /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the + /// same. + Validator operator|(const Validator &other) const { + Validator newval; + + newval._merge_description(*this, other, " OR "); + + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + const std::function &f2 = other.func_; + + newval.func_ = [f1, f2](std::string &input) { + std::string s1 = f1(input); + std::string s2 = f2(input); + if(s1.empty() || s2.empty()) + return std::string(); + + return std::string("(") + s1 + ") OR (" + s2 + ")"; + }; + newval.active_ = (active_ & other.active_); + newval.application_index_ = application_index_; + return newval; + } + + /// Create a validator that fails when a given validator succeeds + Validator operator!() const { + Validator newval; + const std::function &dfunc1 = desc_function_; + newval.desc_function_ = [dfunc1]() { + auto str = dfunc1(); + return (!str.empty()) ? std::string("NOT ") + str : std::string{}; + }; + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + + newval.func_ = [f1, dfunc1](std::string &test) -> std::string { + std::string s1 = f1(test); + if(s1.empty()) { + return std::string("check ") + dfunc1() + " succeeded improperly"; + } + return std::string{}; + }; + newval.active_ = active_; + newval.application_index_ = application_index_; + return newval; + } + + private: + void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger) { + + const std::function &dfunc1 = val1.desc_function_; + const std::function &dfunc2 = val2.desc_function_; + + desc_function_ = [=]() { + std::string f1 = dfunc1(); + std::string f2 = dfunc2(); + if((f1.empty()) || (f2.empty())) { + return f1 + f2; + } + return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')'; + }; + } +}; // namespace CLI + +/// Class wrapping some of the accessors of Validator +class CustomValidator : public Validator { + public: +}; +// The implementation of the built in validators is using the Validator class; +// the user is only expected to use the const (static) versions (since there's no setup). +// Therefore, this is in detail. +namespace detail { + +/// CLI enumeration of different file types +enum class path_type { nonexistent, file, directory }; + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +/// get the type of the path from a file name +inline path_type check_path(const char *file) noexcept { + std::error_code ec; + auto stat = std::filesystem::status(file, ec); + if(ec) { + return path_type::nonexistent; + } + switch(stat.type()) { + case std::filesystem::file_type::none: + case std::filesystem::file_type::not_found: + return path_type::nonexistent; + case std::filesystem::file_type::directory: + return path_type::directory; + case std::filesystem::file_type::symlink: + case std::filesystem::file_type::block: + case std::filesystem::file_type::character: + case std::filesystem::file_type::fifo: + case std::filesystem::file_type::socket: + case std::filesystem::file_type::regular: + case std::filesystem::file_type::unknown: + default: + return path_type::file; + } +} +#else +/// get the type of the path from a file name +inline path_type check_path(const char *file) noexcept { +#if defined(_MSC_VER) + struct __stat64 buffer; + if(_stat64(file, &buffer) == 0) { + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; + } +#else + struct stat buffer; + if(stat(file, &buffer) == 0) { + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; + } +#endif + return path_type::nonexistent; +} +#endif +/// Check for an existing file (returns error message if check fails) +class ExistingFileValidator : public Validator { + public: + ExistingFileValidator() : Validator("FILE") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "File does not exist: " + filename; + } + if(path_result == path_type::directory) { + return "File is actually a directory: " + filename; + } + return std::string(); + }; + } +}; + +/// Check for an existing directory (returns error message if check fails) +class ExistingDirectoryValidator : public Validator { + public: + ExistingDirectoryValidator() : Validator("DIR") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "Directory does not exist: " + filename; + } + if(path_result == path_type::file) { + return "Directory is actually a file: " + filename; + } + return std::string(); + }; + } +}; + +/// Check for an existing path +class ExistingPathValidator : public Validator { + public: + ExistingPathValidator() : Validator("PATH(existing)") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "Path does not exist: " + filename; + } + return std::string(); + }; + } +}; + +/// Check for an non-existing path +class NonexistentPathValidator : public Validator { + public: + NonexistentPathValidator() : Validator("PATH(non-existing)") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result != path_type::nonexistent) { + return "Path already exists: " + filename; + } + return std::string(); + }; + } +}; + +/// Validate the given string is a legal ipv4 address +class IPV4Validator : public Validator { + public: + IPV4Validator() : Validator("IPV4") { + func_ = [](std::string &ip_addr) { + auto result = CLI::detail::split(ip_addr, '.'); + if(result.size() != 4) { + return std::string("Invalid IPV4 address must have four parts (") + ip_addr + ')'; + } + int num; + for(const auto &var : result) { + bool retval = detail::lexical_cast(var, num); + if(!retval) { + return std::string("Failed parsing number (") + var + ')'; + } + if(num < 0 || num > 255) { + return std::string("Each IP number must be between 0 and 255 ") + var; + } + } + return std::string(); + }; + } +}; + +/// Validate the argument is a number and greater than 0 +class PositiveNumber : public Validator { + public: + PositiveNumber() : Validator("POSITIVE") { + func_ = [](std::string &number_str) { + double number; + if(!detail::lexical_cast(number_str, number)) { + return std::string("Failed parsing number: (") + number_str + ')'; + } + if(number <= 0) { + return std::string("Number less or equal to 0: (") + number_str + ')'; + } + return std::string(); + }; + } +}; +/// Validate the argument is a number and greater than or equal to 0 +class NonNegativeNumber : public Validator { + public: + NonNegativeNumber() : Validator("NONNEGATIVE") { + func_ = [](std::string &number_str) { + double number; + if(!detail::lexical_cast(number_str, number)) { + return std::string("Failed parsing number: (") + number_str + ')'; + } + if(number < 0) { + return std::string("Number less than 0: (") + number_str + ')'; + } + return std::string(); + }; + } +}; + +/// Validate the argument is a number +class Number : public Validator { + public: + Number() : Validator("NUMBER") { + func_ = [](std::string &number_str) { + double number; + if(!detail::lexical_cast(number_str, number)) { + return std::string("Failed parsing as a number (") + number_str + ')'; + } + return std::string(); + }; + } +}; + +} // namespace detail + +// Static is not needed here, because global const implies static. + +/// Check for existing file (returns error message if check fails) +const detail::ExistingFileValidator ExistingFile; + +/// Check for an existing directory (returns error message if check fails) +const detail::ExistingDirectoryValidator ExistingDirectory; + +/// Check for an existing path +const detail::ExistingPathValidator ExistingPath; + +/// Check for an non-existing path +const detail::NonexistentPathValidator NonexistentPath; + +/// Check for an IP4 address +const detail::IPV4Validator ValidIPV4; + +/// Check for a positive number +const detail::PositiveNumber PositiveNumber; + +/// Check for a non-negative number +const detail::NonNegativeNumber NonNegativeNumber; + +/// Check for a number +const detail::Number Number; + +/// Produce a range (factory). Min and max are inclusive. +class Range : public Validator { + public: + /// This produces a range with min and max inclusive. + /// + /// Note that the constructor is templated, but the struct is not, so C++17 is not + /// needed to provide nice syntax for Range(a,b). + template Range(T min, T max) { + std::stringstream out; + out << detail::type_name() << " in [" << min << " - " << max << "]"; + description(out.str()); + + func_ = [min, max](std::string &input) { + T val; + bool converted = detail::lexical_cast(input, val); + if((!converted) || (val < min || val > max)) + return std::string("Value ") + input + " not in range " + std::to_string(min) + " to " + + std::to_string(max); + + return std::string(); + }; + } + + /// Range of one value is 0 to value + template explicit Range(T max) : Range(static_cast(0), max) {} +}; + +/// Produce a bounded range (factory). Min and max are inclusive. +class Bound : public Validator { + public: + /// This bounds a value with min and max inclusive. + /// + /// Note that the constructor is templated, but the struct is not, so C++17 is not + /// needed to provide nice syntax for Range(a,b). + template Bound(T min, T max) { + std::stringstream out; + out << detail::type_name() << " bounded to [" << min << " - " << max << "]"; + description(out.str()); + + func_ = [min, max](std::string &input) { + T val; + bool converted = detail::lexical_cast(input, val); + if(!converted) { + return std::string("Value ") + input + " could not be converted"; + } + if(val < min) + input = detail::to_string(min); + else if(val > max) + input = detail::to_string(max); + + return std::string{}; + }; + } + + /// Range of one value is 0 to value + template explicit Bound(T max) : Bound(static_cast(0), max) {} +}; + +namespace detail { +template ::type>::value, detail::enabler> = detail::dummy> +auto smart_deref(T value) -> decltype(*value) { + return *value; +} + +template < + typename T, + enable_if_t::type>::value, detail::enabler> = detail::dummy> +typename std::remove_reference::type &smart_deref(T &value) { + return value; +} +/// Generate a string representation of a set +template std::string generate_set(const T &set) { + using element_t = typename detail::element_type::type; + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + std::string out(1, '{'); + out.append(detail::join( + detail::smart_deref(set), + [](const iteration_type_t &v) { return detail::pair_adaptor::first(v); }, + ",")); + out.push_back('}'); + return out; +} + +/// Generate a string representation of a map +template std::string generate_map(const T &map, bool key_only = false) { + using element_t = typename detail::element_type::type; + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + std::string out(1, '{'); + out.append(detail::join( + detail::smart_deref(map), + [key_only](const iteration_type_t &v) { + std::string res{detail::to_string(detail::pair_adaptor::first(v))}; + + if(!key_only) { + res.append("->"); + res += detail::to_string(detail::pair_adaptor::second(v)); + } + return res; + }, + ",")); + out.push_back('}'); + return out; +} + +template struct has_find { + template + static auto test(int) -> decltype(std::declval().find(std::declval()), std::true_type()); + template static auto test(...) -> decltype(std::false_type()); + + static const auto value = decltype(test(0))::value; + using type = std::integral_constant; +}; + +/// A search function +template ::value, detail::enabler> = detail::dummy> +auto search(const T &set, const V &val) -> std::pair { + using element_t = typename detail::element_type::type; + auto &setref = detail::smart_deref(set); + auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) { + return (detail::pair_adaptor::first(v) == val); + }); + return {(it != std::end(setref)), it}; +} + +/// A search function that uses the built in find function +template ::value, detail::enabler> = detail::dummy> +auto search(const T &set, const V &val) -> std::pair { + auto &setref = detail::smart_deref(set); + auto it = setref.find(val); + return {(it != std::end(setref)), it}; +} + +/// A search function with a filter function +template +auto search(const T &set, const V &val, const std::function &filter_function) + -> std::pair { + using element_t = typename detail::element_type::type; + // do the potentially faster first search + auto res = search(set, val); + if((res.first) || (!(filter_function))) { + return res; + } + // if we haven't found it do the longer linear search with all the element translations + auto &setref = detail::smart_deref(set); + auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) { + V a{detail::pair_adaptor::first(v)}; + a = filter_function(a); + return (a == val); + }); + return {(it != std::end(setref)), it}; +} + +// the following suggestion was made by Nikita Ofitserov(@himikof) +// done in templates to prevent compiler warnings on negation of unsigned numbers + +/// Do a check for overflow on signed numbers +template +inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { + if((a > 0) == (b > 0)) { + return ((std::numeric_limits::max)() / (std::abs)(a) < (std::abs)(b)); + } else { + return ((std::numeric_limits::min)() / (std::abs)(a) > -(std::abs)(b)); + } +} +/// Do a check for overflow on unsigned numbers +template +inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { + return ((std::numeric_limits::max)() / a < b); +} + +/// Performs a *= b; if it doesn't cause integer overflow. Returns false otherwise. +template typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { + if(a == 0 || b == 0 || a == 1 || b == 1) { + a *= b; + return true; + } + if(a == (std::numeric_limits::min)() || b == (std::numeric_limits::min)()) { + return false; + } + if(overflowCheck(a, b)) { + return false; + } + a *= b; + return true; +} + +/// Performs a *= b; if it doesn't equal infinity. Returns false otherwise. +template +typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { + T c = a * b; + if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) { + return false; + } + a = c; + return true; +} + +} // namespace detail +/// Verify items are in a set +class IsMember : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction using an initializer list + template + IsMember(std::initializer_list values, Args &&... args) + : IsMember(std::vector(values), std::forward(args)...) {} + + /// This checks to see if an item is in a set (empty function) + template explicit IsMember(T &&set) : IsMember(std::forward(set), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit IsMember(T set, F filter_function) { + + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + + using local_item_t = typename IsMemberType::type; // This will convert bad types to good ones + // (const char * to std::string) + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + // This is the type name for help, it will take the current version of the set contents + desc_function_ = [set]() { return detail::generate_set(detail::smart_deref(set)); }; + + // This is the function that validates + // It stores a copy of the set pointer-like, so shared_ptr will stay alive + func_ = [set, filter_fn](std::string &input) { + local_item_t b; + if(!detail::lexical_cast(input, b)) { + throw ValidationError(input); // name is added later + } + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(set, b, filter_fn); + if(res.first) { + // Make sure the version in the input string is identical to the one in the set + if(filter_fn) { + input = detail::value_string(detail::pair_adaptor::first(*(res.second))); + } + + // Return empty error string (success) + return std::string{}; + } + + // If you reach this point, the result was not found + std::string out(" not in "); + out += detail::generate_set(detail::smart_deref(set)); + return out; + }; + } + + /// You can pass in as many filter functions as you like, they nest (string only currently) + template + IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&... other) + : IsMember( + std::forward(set), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// definition of the default transformation object +template using TransformPairs = std::vector>; + +/// Translate named items to other or a value set +class Transformer : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction + template + Transformer(std::initializer_list> values, Args &&... args) + : Transformer(TransformPairs(values), std::forward(args)...) {} + + /// direct map of std::string to std::string + template explicit Transformer(T &&mapping) : Transformer(std::forward(mapping), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit Transformer(T mapping, F filter_function) { + + static_assert(detail::pair_adaptor::type>::value, + "mapping must produce value pairs"); + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones + // (const char * to std::string) + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + // This is the type name for help, it will take the current version of the set contents + desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); }; + + func_ = [mapping, filter_fn](std::string &input) { + local_item_t b; + if(!detail::lexical_cast(input, b)) { + return std::string(); + // there is no possible way we can match anything in the mapping if we can't convert so just return + } + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(mapping, b, filter_fn); + if(res.first) { + input = detail::value_string(detail::pair_adaptor::second(*res.second)); + } + return std::string{}; + }; + } + + /// You can pass in as many filter functions as you like, they nest + template + Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&... other) + : Transformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// translate named items to other or a value set +class CheckedTransformer : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction + template + CheckedTransformer(std::initializer_list> values, Args &&... args) + : CheckedTransformer(TransformPairs(values), std::forward(args)...) {} + + /// direct map of std::string to std::string + template explicit CheckedTransformer(T mapping) : CheckedTransformer(std::move(mapping), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit CheckedTransformer(T mapping, F filter_function) { + + static_assert(detail::pair_adaptor::type>::value, + "mapping must produce value pairs"); + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones + // (const char * to std::string) + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + auto tfunc = [mapping]() { + std::string out("value in "); + out += detail::generate_map(detail::smart_deref(mapping)) + " OR {"; + out += detail::join( + detail::smart_deref(mapping), + [](const iteration_type_t &v) { return detail::to_string(detail::pair_adaptor::second(v)); }, + ","); + out.push_back('}'); + return out; + }; + + desc_function_ = tfunc; + + func_ = [mapping, tfunc, filter_fn](std::string &input) { + local_item_t b; + bool converted = detail::lexical_cast(input, b); + if(converted) { + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(mapping, b, filter_fn); + if(res.first) { + input = detail::value_string(detail::pair_adaptor::second(*res.second)); + return std::string{}; + } + } + for(const auto &v : detail::smart_deref(mapping)) { + auto output_string = detail::value_string(detail::pair_adaptor::second(v)); + if(output_string == input) { + return std::string(); + } + } + + return "Check " + input + " " + tfunc() + " FAILED"; + }; + } + + /// You can pass in as many filter functions as you like, they nest + template + CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&... other) + : CheckedTransformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// Helper function to allow ignore_case to be passed to IsMember or Transform +inline std::string ignore_case(std::string item) { return detail::to_lower(item); } + +/// Helper function to allow ignore_underscore to be passed to IsMember or Transform +inline std::string ignore_underscore(std::string item) { return detail::remove_underscore(item); } + +/// Helper function to allow checks to ignore spaces to be passed to IsMember or Transform +inline std::string ignore_space(std::string item) { + item.erase(std::remove(std::begin(item), std::end(item), ' '), std::end(item)); + item.erase(std::remove(std::begin(item), std::end(item), '\t'), std::end(item)); + return item; +} + +/// Multiply a number by a factor using given mapping. +/// Can be used to write transforms for SIZE or DURATION inputs. +/// +/// Example: +/// With mapping = `{"b"->1, "kb"->1024, "mb"->1024*1024}` +/// one can recognize inputs like "100", "12kb", "100 MB", +/// that will be automatically transformed to 100, 14448, 104857600. +/// +/// Output number type matches the type in the provided mapping. +/// Therefore, if it is required to interpret real inputs like "0.42 s", +/// the mapping should be of a type or . +class AsNumberWithUnit : public Validator { + public: + /// Adjust AsNumberWithUnit behavior. + /// CASE_SENSITIVE/CASE_INSENSITIVE controls how units are matched. + /// UNIT_OPTIONAL/UNIT_REQUIRED throws ValidationError + /// if UNIT_REQUIRED is set and unit literal is not found. + enum Options { + CASE_SENSITIVE = 0, + CASE_INSENSITIVE = 1, + UNIT_OPTIONAL = 0, + UNIT_REQUIRED = 2, + DEFAULT = CASE_INSENSITIVE | UNIT_OPTIONAL + }; + + template + explicit AsNumberWithUnit(std::map mapping, + Options opts = DEFAULT, + const std::string &unit_name = "UNIT") { + description(generate_description(unit_name, opts)); + validate_mapping(mapping, opts); + + // transform function + func_ = [mapping, opts](std::string &input) -> std::string { + Number num; + + detail::rtrim(input); + if(input.empty()) { + throw ValidationError("Input is empty"); + } + + // Find split position between number and prefix + auto unit_begin = input.end(); + while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) { + --unit_begin; + } + + std::string unit{unit_begin, input.end()}; + input.resize(static_cast(std::distance(input.begin(), unit_begin))); + detail::trim(input); + + if(opts & UNIT_REQUIRED && unit.empty()) { + throw ValidationError("Missing mandatory unit"); + } + if(opts & CASE_INSENSITIVE) { + unit = detail::to_lower(unit); + } + + bool converted = detail::lexical_cast(input, num); + if(!converted) { + throw ValidationError(std::string("Value ") + input + " could not be converted to " + + detail::type_name()); + } + + if(unit.empty()) { + // No need to modify input if no unit passed + return {}; + } + + // find corresponding factor + auto it = mapping.find(unit); + if(it == mapping.end()) { + throw ValidationError(unit + + " unit not recognized. " + "Allowed values: " + + detail::generate_map(mapping, true)); + } + + // perform safe multiplication + bool ok = detail::checked_multiply(num, it->second); + if(!ok) { + throw ValidationError(detail::to_string(num) + " multiplied by " + unit + + " factor would cause number overflow. Use smaller value."); + } + input = detail::to_string(num); + + return {}; + }; + } + + private: + /// Check that mapping contains valid units. + /// Update mapping for CASE_INSENSITIVE mode. + template static void validate_mapping(std::map &mapping, Options opts) { + for(auto &kv : mapping) { + if(kv.first.empty()) { + throw ValidationError("Unit must not be empty."); + } + if(!detail::isalpha(kv.first)) { + throw ValidationError("Unit must contain only letters."); + } + } + + // make all units lowercase if CASE_INSENSITIVE + if(opts & CASE_INSENSITIVE) { + std::map lower_mapping; + for(auto &kv : mapping) { + auto s = detail::to_lower(kv.first); + if(lower_mapping.count(s)) { + throw ValidationError(std::string("Several matching lowercase unit representations are found: ") + + s); + } + lower_mapping[detail::to_lower(kv.first)] = kv.second; + } + mapping = std::move(lower_mapping); + } + } + + /// Generate description like this: NUMBER [UNIT] + template static std::string generate_description(const std::string &name, Options opts) { + std::stringstream out; + out << detail::type_name() << ' '; + if(opts & UNIT_REQUIRED) { + out << name; + } else { + out << '[' << name << ']'; + } + return out.str(); + } +}; + +/// Converts a human-readable size string (with unit literal) to uin64_t size. +/// Example: +/// "100" => 100 +/// "1 b" => 100 +/// "10Kb" => 10240 // you can configure this to be interpreted as kilobyte (*1000) or kibibyte (*1024) +/// "10 KB" => 10240 +/// "10 kb" => 10240 +/// "10 kib" => 10240 // *i, *ib are always interpreted as *bibyte (*1024) +/// "10kb" => 10240 +/// "2 MB" => 2097152 +/// "2 EiB" => 2^61 // Units up to exibyte are supported +class AsSizeValue : public AsNumberWithUnit { + public: + using result_t = std::uint64_t; + + /// If kb_is_1000 is true, + /// interpret 'kb', 'k' as 1000 and 'kib', 'ki' as 1024 + /// (same applies to higher order units as well). + /// Otherwise, interpret all literals as factors of 1024. + /// The first option is formally correct, but + /// the second interpretation is more wide-spread + /// (see https://en.wikipedia.org/wiki/Binary_prefix). + explicit AsSizeValue(bool kb_is_1000) : AsNumberWithUnit(get_mapping(kb_is_1000)) { + if(kb_is_1000) { + description("SIZE [b, kb(=1000b), kib(=1024b), ...]"); + } else { + description("SIZE [b, kb(=1024b), ...]"); + } + } + + private: + /// Get mapping + static std::map init_mapping(bool kb_is_1000) { + std::map m; + result_t k_factor = kb_is_1000 ? 1000 : 1024; + result_t ki_factor = 1024; + result_t k = 1; + result_t ki = 1; + m["b"] = 1; + for(std::string p : {"k", "m", "g", "t", "p", "e"}) { + k *= k_factor; + ki *= ki_factor; + m[p] = k; + m[p + "b"] = k; + m[p + "i"] = ki; + m[p + "ib"] = ki; + } + return m; + } + + /// Cache calculated mapping + static std::map get_mapping(bool kb_is_1000) { + if(kb_is_1000) { + static auto m = init_mapping(true); + return m; + } else { + static auto m = init_mapping(false); + return m; + } + } +}; + +namespace detail { +/// Split a string into a program name and command line arguments +/// the string is assumed to contain a file name followed by other arguments +/// the return value contains is a pair with the first argument containing the program name and the second +/// everything else. +inline std::pair split_program_name(std::string commandline) { + // try to determine the programName + std::pair vals; + trim(commandline); + auto esp = commandline.find_first_of(' ', 1); + while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) { + esp = commandline.find_first_of(' ', esp + 1); + if(esp == std::string::npos) { + // if we have reached the end and haven't found a valid file just assume the first argument is the + // program name + esp = commandline.find_first_of(' ', 1); + break; + } + } + vals.first = commandline.substr(0, esp); + rtrim(vals.first); + // strip the program name + vals.second = (esp != std::string::npos) ? commandline.substr(esp + 1) : std::string{}; + ltrim(vals.second); + return vals; +} + +} // namespace detail +/// @} + +} // namespace CLI + +// From FormatterFwd.hpp: + +namespace CLI { + +class Option; +class App; + +/// This enum signifies the type of help requested +/// +/// This is passed in by App; all user classes must accept this as +/// the second argument. + +enum class AppFormatMode { + Normal, ///< The normal, detailed help + All, ///< A fully expanded help + Sub, ///< Used when printed as part of expanded subcommand +}; + +/// This is the minimum requirements to run a formatter. +/// +/// A user can subclass this is if they do not care at all +/// about the structure in CLI::Formatter. +class FormatterBase { + protected: + /// @name Options + ///@{ + + /// The width of the first column + std::size_t column_width_{30}; + + /// @brief The required help printout labels (user changeable) + /// Values are Needs, Excludes, etc. + std::map labels_{}; + + ///@} + /// @name Basic + ///@{ + + public: + FormatterBase() = default; + FormatterBase(const FormatterBase &) = default; + FormatterBase(FormatterBase &&) = default; + + /// Adding a destructor in this form to work around bug in GCC 4.7 + virtual ~FormatterBase() noexcept {} // NOLINT(modernize-use-equals-default) + + /// This is the key method that puts together help + virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0; + + ///@} + /// @name Setters + ///@{ + + /// Set the "REQUIRED" label + void label(std::string key, std::string val) { labels_[key] = val; } + + /// Set the column width + void column_width(std::size_t val) { column_width_ = val; } + + ///@} + /// @name Getters + ///@{ + + /// Get the current value of a name (REQUIRED, etc.) + std::string get_label(std::string key) const { + if(labels_.find(key) == labels_.end()) + return key; + else + return labels_.at(key); + } + + /// Get the current column width + std::size_t get_column_width() const { return column_width_; } + + ///@} +}; + +/// This is a specialty override for lambda functions +class FormatterLambda final : public FormatterBase { + using funct_t = std::function; + + /// The lambda to hold and run + funct_t lambda_; + + public: + /// Create a FormatterLambda with a lambda function + explicit FormatterLambda(funct_t funct) : lambda_(std::move(funct)) {} + + /// Adding a destructor (mostly to make GCC 4.7 happy) + ~FormatterLambda() noexcept override {} // NOLINT(modernize-use-equals-default) + + /// This will simply call the lambda function + std::string make_help(const App *app, std::string name, AppFormatMode mode) const override { + return lambda_(app, name, mode); + } +}; + +/// This is the default Formatter for CLI11. It pretty prints help output, and is broken into quite a few +/// overridable methods, to be highly customizable with minimal effort. +class Formatter : public FormatterBase { + public: + Formatter() = default; + Formatter(const Formatter &) = default; + Formatter(Formatter &&) = default; + + /// @name Overridables + ///@{ + + /// This prints out a group of options with title + /// + virtual std::string make_group(std::string group, bool is_positional, std::vector opts) const; + + /// This prints out just the positionals "group" + virtual std::string make_positionals(const App *app) const; + + /// This prints out all the groups of options + std::string make_groups(const App *app, AppFormatMode mode) const; + + /// This prints out all the subcommands + virtual std::string make_subcommands(const App *app, AppFormatMode mode) const; + + /// This prints out a subcommand + virtual std::string make_subcommand(const App *sub) const; + + /// This prints out a subcommand in help-all + virtual std::string make_expanded(const App *sub) const; + + /// This prints out all the groups of options + virtual std::string make_footer(const App *app) const; + + /// This displays the description line + virtual std::string make_description(const App *app) const; + + /// This displays the usage line + virtual std::string make_usage(const App *app, std::string name) const; + + /// This puts everything together + std::string make_help(const App * /*app*/, std::string, AppFormatMode) const override; + + ///@} + /// @name Options + ///@{ + + /// This prints out an option help line, either positional or optional form + virtual std::string make_option(const Option *opt, bool is_positional) const { + std::stringstream out; + detail::format_help( + out, make_option_name(opt, is_positional) + make_option_opts(opt), make_option_desc(opt), column_width_); + return out.str(); + } + + /// @brief This is the name part of an option, Default: left column + virtual std::string make_option_name(const Option *, bool) const; + + /// @brief This is the options part of the name, Default: combined into left column + virtual std::string make_option_opts(const Option *) const; + + /// @brief This is the description. Default: Right column, on new line if left column too large + virtual std::string make_option_desc(const Option *) const; + + /// @brief This is used to print the name on the USAGE line + virtual std::string make_option_usage(const Option *opt) const; + + ///@} +}; + +} // namespace CLI + +// From Option.hpp: + +namespace CLI { + +using results_t = std::vector; +/// callback function definition +using callback_t = std::function; + +class Option; +class App; + +using Option_p = std::unique_ptr public static SubmissionOptions Default { get; } = new SubmissionOptions("", 500); - private SubmissionOptions(string friendlyName, int shots) => + private SubmissionOptions(string friendlyName, int shots) => (this.FriendlyName, this.Shots) = (friendlyName, shots); /// From 8e3f8cb9a6ed8e488ed9a3ef9ee2551e21d54415 Mon Sep 17 00:00:00 2001 From: Scott Carda <55811729+ScottCarda-MS@users.noreply.github.com> Date: Fri, 7 May 2021 11:50:19 -0700 Subject: [PATCH 092/145] QIR Build From Q# DLL (#658) Fills out the BuildFromQSharpDll function. --- src/Qir/Controller/Controller.cs | 2 +- .../QirDriverGeneratorTests.cs | 2 +- .../QirExecutableTests.cs | 2 +- .../Tests.Microsoft.Quantum.Qir.Tools/Util.cs | 2 -- .../Tools/Driver/IQirDriverGenerator.cs | 2 +- .../Execution/Tools/Driver/QirCppDriver.cs | 2 +- .../Execution/Tools/Driver/QirCppDriverEx.cs | 2 +- .../Tools/Driver/QirCppDriverGenerator.cs | 2 +- .../Execution/Tools/Driver/QirCppInterop.cs | 2 +- .../Driver/QirFullStateDriverGenerator.cs | 3 +- .../Tools/Executable/IQirExecutable.cs | 2 +- .../Tools/Executable/QirExecutable.cs | 2 +- .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 2 +- src/Qir/Execution/Tools/QirTools.cs | 34 +++++++++++++++++-- 14 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 2e6593dde35..1ae7e6a747c 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -7,9 +7,9 @@ using System.Text.Json; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Model; +using Microsoft.Quantum.Qir.Serialization; using Microsoft.Quantum.Qir.Tools.Executable; using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir { diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs index 92d8daaa744..03a0859093e 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -8,7 +8,7 @@ using Xunit; using Microsoft.Quantum.Qir.Tools.Driver; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; +using Microsoft.Quantum.Qir.Serialization; namespace Tests.Microsoft.Quantum.Qir.Tools { diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs index a47b4023b68..8c3b469c2a5 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Serialization; using Microsoft.Quantum.Qir.Tools.Driver; using Microsoft.Quantum.Qir.Tools.Executable; using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; using Moq; using Xunit; diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs index ab6aee7d8eb..e027bbe5403 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System.IO; -using System.Reflection; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Tests.Microsoft.Quantum.Qir.Tools { diff --git a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs index 28c3ef5fc90..8f29518aca3 100644 --- a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs @@ -3,7 +3,7 @@ using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; +using Microsoft.Quantum.Qir.Serialization; namespace Microsoft.Quantum.Qir.Tools.Driver { diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index 807f959095b..c1eb3cec1d3 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -10,7 +10,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { using System.IO; - using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; + using Microsoft.Quantum.Qir.Serialization; using System; /// diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs index 7c05fba2b3e..b66eca09a57 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; +using Microsoft.Quantum.Qir.Serialization; namespace Microsoft.Quantum.Qir.Tools.Driver { diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index a9a8233464b..26db40b0c90 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; +using Microsoft.Quantum.Qir.Serialization; namespace Microsoft.Quantum.Qir.Tools.Driver { diff --git a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs index b4da38b9676..dfac2fac833 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; +using Microsoft.Quantum.Qir.Serialization; #nullable enable diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs index 8f98b4a80f9..381a06b532f 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs @@ -3,8 +3,7 @@ using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; +using Microsoft.Quantum.Qir.Serialization; namespace Microsoft.Quantum.Qir.Tools.Driver { diff --git a/src/Qir/Execution/Tools/Executable/IQirExecutable.cs b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs index 765207e3c99..477dd2cfe2a 100644 --- a/src/Qir/Execution/Tools/Executable/IQirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs @@ -3,7 +3,7 @@ using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; +using Microsoft.Quantum.Qir.Serialization; namespace Microsoft.Quantum.Qir.Tools.Executable { diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs index a1613c41773..4c6f73c7d2d 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -4,9 +4,9 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Serialization; using Microsoft.Quantum.Qir.Tools.Driver; using Microsoft.Quantum.Qir.Utility; -using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir.Tools.Executable { diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index 77ceccafb92..8917f61f09e 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Qir/Execution/Tools/QirTools.cs b/src/Qir/Execution/Tools/QirTools.cs index 08531a54057..e430ce5501b 100644 --- a/src/Qir/Execution/Tools/QirTools.cs +++ b/src/Qir/Execution/Tools/QirTools.cs @@ -1,8 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using Microsoft.Quantum.Qir.Tools.Executable; +using Microsoft.Quantum.QsCompiler; +using Microsoft.Quantum.QsCompiler.QIR; using System; using System.IO; +using System.Linq; using System.Threading.Tasks; namespace Microsoft.Quantum.Qir.Tools @@ -12,16 +16,40 @@ namespace Microsoft.Quantum.Qir.Tools /// public static class QirTools { - /// /// Creates a QIR-based executable from a .NET DLL generated by the Q# compiler. /// /// .NET DLL generated by the Q# compiler. /// Directory where the libraries to link to are located. /// Directory where the headers needed for compilation are located. - public static Task BuildFromQSharpDll(FileInfo qsharpDll, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) + /// Directory where the created executables are placed. + public static async Task BuildFromQSharpDll( + FileInfo qsharpDll, + DirectoryInfo libraryDirectory, + DirectoryInfo includeDirectory, + DirectoryInfo executablesDirectory) { - throw new NotImplementedException(); + using var qirContentStream = new MemoryStream(); + if (!AssemblyLoader.LoadQirByteCode(qsharpDll, qirContentStream)) + { + throw new ArgumentException("The given DLL does not contain QIR byte code."); + } + + if (!executablesDirectory.Exists) + { + executablesDirectory.Create(); + } + + var tasks = EntryPointOperationLoader.LoadEntryPointOperations(qsharpDll).Select(entryPointOp => + { + var exeFileInfo = new FileInfo(Path.Combine(executablesDirectory.FullName, entryPointOp.Name)); + var exe = new QirFullStateExecutable(exeFileInfo, qirContentStream.ToArray()); + return exe.BuildAsync(entryPointOp, libraryDirectory, includeDirectory); + }); + + await Task.WhenAll(tasks); + + // ToDo: Return list of created file names } } } From d22a7da0facf4c2aaf6566a04da5e9d903b4d34e Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 10:02:39 -0700 Subject: [PATCH 093/145] Fix build errors --- src/Simulation/EntryPointDriver/Azure/Azure.cs | 11 ++++++++--- .../EntryPointDriver/Azure/AzureSettings.cs | 2 +- src/Simulation/EntryPointDriver/Driver.cs | 4 ++-- .../EntryPointDriver/Mock/NoOpQirSubmitter.cs | 4 +++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index e90be11339f..9bf17cecd30 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -6,6 +6,7 @@ using static Microsoft.Quantum.EntryPointDriver.Driver; using Microsoft.Quantum.EntryPointDriver.Mock; using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; using Microsoft.Quantum.Simulation.Common.Exceptions; using System; using System.Threading.Tasks; @@ -95,9 +96,13 @@ private static async Task SubmitQir( return 1; } - return await DisplayJobOrError( - settings, - submitter.SubmitAsync(submission.QirStream, submission.EntryPointName, submission.Arguments)); + var job = submitter.SubmitAsync( + submission.QirStream, + submission.EntryPointName, + submission.Arguments, + SubmissionOptions.Default.With(settings.JobName, settings.Shots)); + + return await DisplayJobOrError(settings, job); } /// diff --git a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs index d6693b10047..1ec30ff5fd6 100644 --- a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs +++ b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs @@ -59,7 +59,7 @@ public sealed class AzureSettings /// /// The name of the submitted job. /// - public string? JobName { get; set; } + public string JobName { get; set; } = ""; /// /// The number of times the program is executed on the target machine. diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 66b957ab41a..ffa96a01ed5 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -84,8 +84,8 @@ public sealed class Driver /// /// The job name option. /// - private static readonly OptionInfo JobNameOption = new OptionInfo( - ImmutableList.Create("--job-name"), default, "The name of the submitted job."); + private static readonly OptionInfo JobNameOption = new OptionInfo( + ImmutableList.Create("--job-name"), "", "The name of the submitted job."); /// /// The shots option. diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs index 2d486e9ed13..0b356817a10 100644 --- a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs @@ -5,6 +5,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; namespace Microsoft.Quantum.EntryPointDriver.Mock { @@ -22,7 +23,8 @@ internal class NoOpQirSubmitter : IQirSubmitter public string Target => TargetId; - public Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments) => + public Task SubmitAsync( + Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) => Task.FromResult(new ExampleJob()); } } From 845b678d0e1b7618c80009ab200dea5cff36956a Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 10:49:59 -0700 Subject: [PATCH 094/145] Use IQSharpSubmitter from driver --- .../EntryPointDriver/Azure/Azure.cs | 91 +++++++++++++++---- 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 9bf17cecd30..027905f8756 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -34,14 +34,19 @@ public static class Azure public static Task Submit( AzureSettings settings, QSharpSubmission qsSubmission, QirSubmission? qirSubmission) { - if (!(qirSubmission is null) && QirSubmitter(settings) is { } submitter) + if (!(qirSubmission is null) && QirSubmitter(settings) is { } qirSubmitter) { - return SubmitQir(settings, submitter, qirSubmission); + return SubmitQir(settings, qirSubmitter, qirSubmission); + } + + if (QSharpSubmitter(settings) is { } qsSubmitter) + { + return SubmitQSharp(settings, qsSubmitter, qsSubmission); } if (QSharpMachine(settings) is { } machine) { - return SubmitQSharp(settings, machine, qsSubmission); + return SubmitQSharpMachine(settings, machine, qsSubmission); } DisplayWithColor(ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); @@ -49,7 +54,7 @@ public static Task Submit( } /// - /// Submits a Q# entry point to Azure Quantum. + /// Submits a Q# entry point to Azure Quantum using a quantum machine. /// /// The entry point's argument type. /// The entry point's return type. @@ -57,21 +62,58 @@ public static Task Submit( /// The quantum machine used for submission. /// The Q# entry point submission. /// The exit code. - private static async Task SubmitQSharp( + private static async Task SubmitQSharpMachine( AzureSettings settings, IQuantumMachine machine, QSharpSubmission submission) { - Task SubmitJob() => machine.SubmitAsync( + if (settings.Verbose) + { + Console.WriteLine("Submitting Q# entry point using a quantum machine." + Environment.NewLine); + Console.WriteLine(settings + Environment.NewLine); + } + + if (settings.DryRun) + { + var (valid, message) = machine.Validate(submission.EntryPointInfo, submission.Argument); + return DisplayValidation(valid ? null : message); + } + + var job = machine.SubmitAsync( submission.EntryPointInfo, submission.Argument, new SubmissionContext { FriendlyName = settings.JobName, Shots = settings.Shots }); + return await DisplayJobOrError(settings, job); + } + + /// + /// Submits a Q# entry point to Azure Quantum. + /// + /// The entry point's argument type. + /// The entry point's return type. + /// The Azure submission settings. + /// The Q# submitter. + /// The Q# entry point submission. + /// The exit code. + private static async Task SubmitQSharp( + AzureSettings settings, IQSharpSubmitter submitter, QSharpSubmission submission) + { if (settings.Verbose) { Console.WriteLine("Submitting Q# entry point." + Environment.NewLine); Console.WriteLine(settings + Environment.NewLine); } - return settings.DryRun ? Validate(machine, submission) : await DisplayJobOrError(settings, SubmitJob()); + if (settings.DryRun) + { + return DisplayValidation(submitter.Validate(submission.EntryPointInfo, submission.Argument)); + } + + var job = submitter.SubmitAsync( + submission.EntryPointInfo, + submission.Argument, + SubmissionOptions.Default.With(settings.JobName, settings.Shots)); + + return await DisplayJobOrError(settings, job); } /// @@ -135,22 +177,21 @@ private static async Task DisplayJobOrError(AzureSettings settings, Task - /// Validates the program for the quantum machine target. + /// Displays a validation message for a program. /// - /// The input type. - /// The output type. - /// The quantum machine target. - /// The entry point submission. + /// The validation error message, or null if the program is valid. /// The exit code. - private static int Validate(IQuantumMachine machine, QSharpSubmission submission) + private static int DisplayValidation(string? message) { - var (isValid, message) = machine.Validate(submission.EntryPointInfo, submission.Argument); - Console.WriteLine(isValid ? "✔️ The program is valid!" : "❌ The program is invalid."); - if (!string.IsNullOrWhiteSpace(message)) + if (message is null) { - Console.WriteLine(Environment.NewLine + message); + Console.WriteLine("✔️ The program is valid!"); + return 0; } - return isValid ? 0 : 1; + + Console.WriteLine("❌ The program is invalid." + Environment.NewLine); + Console.WriteLine(message); + return 1; } /// @@ -216,6 +257,18 @@ private static void DisplayError(string summary, string? message) _ => QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage) }; + /// + /// Returns a Q# submitter. + /// + /// The Azure Quantum submission settings. + /// A Q# submitter. + /// .Target is null. + private static IQSharpSubmitter? QSharpSubmitter(AzureSettings settings) => settings.Target switch + { + null => throw new ArgumentNullException(nameof(settings), "Target is null."), + _ => null // TODO: Factory. + }; + /// /// Returns a QIR submitter. /// @@ -226,7 +279,7 @@ private static void DisplayError(string summary, string? message) { null => throw new ArgumentNullException(nameof(settings), "Target is null"), NoOpQirSubmitter.TargetId => new NoOpQirSubmitter(), - _ => null // TODO + _ => null // TODO: Factory. }; /// From 6c5fd613ef84343ee15293c9705f88f893397e40 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 11:01:18 -0700 Subject: [PATCH 095/145] Add AzureSettings.SubmissionOptions --- src/Simulation/EntryPointDriver/Azure/Azure.cs | 11 ++--------- .../EntryPointDriver/Azure/AzureSettings.cs | 11 +++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 027905f8756..49b86e4824b 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -109,10 +109,7 @@ private static async Task SubmitQSharp( } var job = submitter.SubmitAsync( - submission.EntryPointInfo, - submission.Argument, - SubmissionOptions.Default.With(settings.JobName, settings.Shots)); - + submission.EntryPointInfo, submission.Argument, settings.SubmissionOptions); return await DisplayJobOrError(settings, job); } @@ -139,11 +136,7 @@ private static async Task SubmitQir( } var job = submitter.SubmitAsync( - submission.QirStream, - submission.EntryPointName, - submission.Arguments, - SubmissionOptions.Default.With(settings.JobName, settings.Shots)); - + submission.QirStream, submission.EntryPointName, submission.Arguments, settings.SubmissionOptions); return await DisplayJobOrError(settings, job); } diff --git a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs index 1ec30ff5fd6..02d6538871b 100644 --- a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs +++ b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Microsoft.Azure.Quantum; +using Microsoft.Quantum.Runtime.Submitters; using System; using System.Linq; @@ -81,6 +82,11 @@ public sealed class AzureSettings /// public bool Verbose { get; set; } + /// + /// The submission options corresponding to these settings. + /// + internal SubmissionOptions SubmissionOptions => SubmissionOptions.Default.With(JobName, Shots); + /// /// Creates a based on the settings. /// @@ -122,6 +128,11 @@ public override string ToString() => string.Join( $"Dry Run: {DryRun}", $"Verbose: {Verbose}"); + /// + /// Normalizes an Azure location string. + /// + /// The location string. + /// The normalized location string. internal static string NormalizeLocation(string location) => string.Concat(location.Where(c => !char.IsWhiteSpace(c))).ToLower(); } From f806a827b5430cc57f1791faaf6dfd8664ad35c2 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 11:17:36 -0700 Subject: [PATCH 096/145] Add Log function --- .../EntryPointDriver/Azure/Azure.cs | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 49b86e4824b..b5aee4456b8 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -34,6 +34,8 @@ public static class Azure public static Task Submit( AzureSettings settings, QSharpSubmission qsSubmission, QirSubmission? qirSubmission) { + Log(settings, settings.ToString()); + if (!(qirSubmission is null) && QirSubmitter(settings) is { } qirSubmitter) { return SubmitQir(settings, qirSubmitter, qirSubmission); @@ -65,11 +67,7 @@ public static Task Submit( private static async Task SubmitQSharpMachine( AzureSettings settings, IQuantumMachine machine, QSharpSubmission submission) { - if (settings.Verbose) - { - Console.WriteLine("Submitting Q# entry point using a quantum machine." + Environment.NewLine); - Console.WriteLine(settings + Environment.NewLine); - } + Log(settings, "Submitting Q# entry point using a quantum machine."); if (settings.DryRun) { @@ -97,11 +95,7 @@ private static async Task SubmitQSharpMachine( private static async Task SubmitQSharp( AzureSettings settings, IQSharpSubmitter submitter, QSharpSubmission submission) { - if (settings.Verbose) - { - Console.WriteLine("Submitting Q# entry point." + Environment.NewLine); - Console.WriteLine(settings + Environment.NewLine); - } + Log(settings, "Submitting Q# entry point."); if (settings.DryRun) { @@ -123,11 +117,7 @@ private static async Task SubmitQSharp( private static async Task SubmitQir( AzureSettings settings, IQirSubmitter submitter, QirSubmission submission) { - if (settings.Verbose) - { - Console.WriteLine("Submitting QIR entry point." + Environment.NewLine); - Console.WriteLine(settings + Environment.NewLine); - } + Log(settings, "Submitting QIR entry point."); if (settings.DryRun) { @@ -236,6 +226,20 @@ private static void DisplayError(string summary, string? message) } } + /// + /// Logs a message if the verbose setting is enabled. + /// + /// The Azure Quantum submission settings. + /// The message. + private static void Log(AzureSettings settings, string message) + { + if (settings.Verbose) + { + Console.WriteLine(message); + Console.WriteLine(); + } + } + /// /// Returns a Q# machine. /// From 5f64884192ca8bd2bf1fa185da5da4a2c68ebdad Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 11:24:07 -0700 Subject: [PATCH 097/145] Update TODO comments --- src/Simulation/EntryPointDriver/Azure/Azure.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index b5aee4456b8..f0549d16322 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -263,7 +263,7 @@ private static void Log(AzureSettings settings, string message) private static IQSharpSubmitter? QSharpSubmitter(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null."), - _ => null // TODO: Factory. + _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. }; /// @@ -276,7 +276,7 @@ private static void Log(AzureSettings settings, string message) { null => throw new ArgumentNullException(nameof(settings), "Target is null"), NoOpQirSubmitter.TargetId => new NoOpQirSubmitter(), - _ => null // TODO: Factory. + _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. }; /// From 5cce84ca3ee8bdb44a20a376de90b0be61a80a07 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 11:30:28 -0700 Subject: [PATCH 098/145] Update tests --- .../EntryPointDriver.Tests/Tests.fs | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index 303e28ce90a..a5a84e80e31 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -557,9 +557,7 @@ let ``Submit can show only the ID`` () = let ``Submit uses default values`` () = let given = test "Returns Unit" given (submitWithNoOpTarget @ ["--verbose"]) - |> yields "Submitting Q# entry point. - - Subscription: mySubscription + |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -573,15 +571,15 @@ let ``Submit uses default values`` () = Dry Run: False Verbose: True + Submitting Q# entry point using a quantum machine. + https://www.example.com/00000000-0000-0000-0000-0000000000000" [] let ``Submit uses default values with default target`` () = let given = testWithTarget "test.noop" "Returns Unit" given (submitWithoutTarget @ ["--verbose"]) - |> yields "Submitting Q# entry point. - - Subscription: mySubscription + |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -595,6 +593,8 @@ let ``Submit uses default values with default target`` () = Dry Run: False Verbose: True + Submitting Q# entry point using a quantum machine. + https://www.example.com/00000000-0000-0000-0000-0000000000000" [] @@ -613,9 +613,7 @@ let ``Submit allows overriding default values`` () = "--shots" "750" ]) - |> yields "Submitting Q# entry point. - - Subscription: mySubscription + |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -629,6 +627,8 @@ let ``Submit allows overriding default values`` () = Dry Run: False Verbose: True + Submitting Q# entry point using a quantum machine. + https://www.example.com/00000000-0000-0000-0000-0000000000000" [] @@ -647,9 +647,7 @@ let ``Submit allows overriding default values with default target`` () = "--shots" "750" ]) - |> yields "Submitting Q# entry point. - - Subscription: mySubscription + |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -663,6 +661,8 @@ let ``Submit allows overriding default values with default target`` () = Dry Run: False Verbose: True + Submitting Q# entry point using a quantum machine. + https://www.example.com/00000000-0000-0000-0000-0000000000000" [] @@ -684,9 +684,7 @@ let ``Submit allows to include --base-uri option when --location is not present` "--base-uri" "myBaseUri" ]) - |> yields "Submitting Q# entry point. - - Subscription: mySubscription + |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -700,6 +698,8 @@ let ``Submit allows to include --base-uri option when --location is not present` Dry Run: False Verbose: True + Submitting Q# entry point using a quantum machine. + https://www.example.com/00000000-0000-0000-0000-0000000000000" [] @@ -710,9 +710,7 @@ let ``Submit allows to include --location option when --base-uri is not present` "--location" "myLocation" ]) - |> yields "Submitting Q# entry point. - - Subscription: mySubscription + |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -726,6 +724,8 @@ let ``Submit allows to include --location option when --base-uri is not present` Dry Run: False Verbose: True + Submitting Q# entry point using a quantum machine. + https://www.example.com/00000000-0000-0000-0000-0000000000000" [] @@ -736,9 +736,7 @@ let ``Submit allows spaces for the --location option`` () = "--location" "My Location" ]) - |> yields "Submitting Q# entry point. - - Subscription: mySubscription + |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace Target: test.noop @@ -752,6 +750,8 @@ let ``Submit allows spaces for the --location option`` () = Dry Run: False Verbose: True + Submitting Q# entry point using a quantum machine. + https://www.example.com/00000000-0000-0000-0000-0000000000000" [] From e28a94e7fd96eb19400985853eee3b6bb643ab13 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 11:57:45 -0700 Subject: [PATCH 099/145] Update CoreTests.SubmitsQir --- src/Simulation/Simulators.Tests/CoreTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 376f0039ee7..5670734848a 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -94,8 +94,6 @@ public void SubmitsQir() Assert.Equal( string.Join( Environment.NewLine, - "Submitting QIR entry point.", - "", "Subscription: foo", "Resource Group: bar", "Workspace: baz", @@ -110,6 +108,8 @@ public void SubmitsQir() "Dry Run: False", "Verbose: True", "", + "Submitting QIR entry point.", + "", "https://www.example.com/00000000-0000-0000-0000-0000000000000", ""), output.ToString()); From 7cff67b6bbcc6ebc1509b634b1dbceb21a62c6db Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Mon, 10 May 2021 14:09:57 -0700 Subject: [PATCH 100/145] Replace map+concat with collect --- src/Simulation/CSharpGeneration/EntryPoint.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 107a5ef6271..3f0bf21e982 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -35,7 +35,7 @@ let rec private parameters context doc = function CSharpTypeName = SimulationCode.roslynTypeName context variable.Type Description = ParameterDescription doc name } | InvalidName -> Seq.empty - | QsTuple items -> items |> Seq.map (parameters context doc) |> Seq.concat + | QsTuple items -> items |> Seq.collect (parameters context doc) /// An expression representing the name of an entry point option given its parameter name. let private optionName (paramName : string) = From fa0f26363f3ce2a2af4774e5f22948cec8633aaa Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 11 May 2021 13:51:19 -0700 Subject: [PATCH 101/145] Use AssemblyConstants.QirOutputPath --- src/Simulation/CSharpGeneration/EntryPoint.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 3f0bf21e982..9d989833f68 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -165,6 +165,7 @@ let private submitMethod context entryPoint parameters = let callableName, argTypeName, returnTypeName = callableTypeNames context entryPoint let parseResultParamName = "parseResult" let settingsParamName = "settings" + let hasQir = context.assemblyConstants.ContainsKey AssemblyConstants.QirOutputPath let qsSubmission = ``new`` (generic (driverNamespace + ".Azure.QSharpSubmission") ``<<`` [argTypeName; returnTypeName] ``>>``) @@ -196,7 +197,7 @@ let private submitMethod context entryPoint parameters = [ ident settingsParamName :> ExpressionSyntax qsSubmission - if context.assemblyConstants.ContainsKey "QirOutputPath" then qirSubmission.Value else ``null`` + if hasQir then qirSubmission.Value else ``null`` ] arrow_method "System.Threading.Tasks.Task" "Submit" ``<<`` [] ``>>`` From 147dc638a4e6baf6d0fbc4cd3897ae20719e6c97 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 12 May 2021 10:55:03 -0700 Subject: [PATCH 102/145] Check if QIR stream resource is null at runtime --- src/Simulation/CSharpGeneration/EntryPoint.fs | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 9d989833f68..0ef7203c2b1 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -158,14 +158,36 @@ let private qirArguments parameters parseResult = ``new`` (ident "global::Microsoft.Quantum.Runtime.Argument") ``(`` [literal param.Name; value] ``)`` - ident "global::System.Collections.Immutable.ImmutableList" <.> (ident "Create", parameters |> Seq.map argument) + ident "global::System.Collections.Immutable.ImmutableList" + <.> (ident "Create", parameters |> Seq.map argument) + +/// The QIR submission for the given entry point, parameters, and parsed arguments. Returns null if the QIR stream +/// resource does not exist. +let private qirSubmission (entryPoint: QsCallable) parameters parseResult = + let stream = + ident "global::System.Reflection.Assembly" + <.> (ident "GetExecutingAssembly", []) + <.> (ident "GetManifestResourceStream", [literal DotnetCoreDll.QirResourceName]) + + let streamVar = ident "qirStream" + + let submission = + ``new`` (driverNamespace + ".Azure.QirSubmission" |> ``type``) + ``(`` + [ + streamVar :> ExpressionSyntax + string entryPoint.FullName |> literal + qirArguments parameters parseResult + ] + ``)`` + + ``?`` (stream |> ``is assign`` "{ }" streamVar) (submission, ``null``) /// Generates the Submit method for an entry point class. let private submitMethod context entryPoint parameters = let callableName, argTypeName, returnTypeName = callableTypeNames context entryPoint let parseResultParamName = "parseResult" let settingsParamName = "settings" - let hasQir = context.assemblyConstants.ContainsKey AssemblyConstants.QirOutputPath let qsSubmission = ``new`` (generic (driverNamespace + ".Azure.QSharpSubmission") ``<<`` [argTypeName; returnTypeName] ``>>``) @@ -176,28 +198,11 @@ let private submitMethod context entryPoint parameters = ] ``)`` - let qirStream = - lazy - ident "global::System.Reflection.Assembly" - <.> (ident "GetExecutingAssembly", []) - <.> (ident "GetManifestResourceStream", [literal DotnetCoreDll.QirResourceName]) - - let qirSubmission = - lazy - ``new`` (driverNamespace + ".Azure.QirSubmission" |> ``type``) - ``(`` - [ - qirStream.Value - string entryPoint.FullName |> literal - ident parseResultParamName |> qirArguments parameters - ] - ``)`` - let args = [ ident settingsParamName :> ExpressionSyntax qsSubmission - if hasQir then qirSubmission.Value else ``null`` + ident parseResultParamName |> qirSubmission entryPoint parameters ] arrow_method "System.Threading.Tasks.Task" "Submit" ``<<`` [] ``>>`` From 6fb63c84ef7f72ff54a6d9b0525c53f399bad764 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 12 May 2021 11:04:52 -0700 Subject: [PATCH 103/145] Use Target instead of TargetId --- src/Simulation/EntryPointDriver/Azure/Azure.cs | 7 ++++--- .../EntryPointDriver/Mock/ErrorQuantumMachine.cs | 7 ++++--- src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs | 6 +++--- src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs | 7 ++++--- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index f0549d16322..e9827d4be03 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -203,6 +203,7 @@ private static void DisplayJob(IQuantumMachineJob job, OutputFormat format) Console.WriteLine(job.Id); } + break; case OutputFormat.Id: Console.WriteLine(job.Id); @@ -249,8 +250,8 @@ private static void Log(AzureSettings settings, string message) private static IQuantumMachine? QSharpMachine(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null."), - NoOpQuantumMachine.TargetId => new NoOpQuantumMachine(), - ErrorQuantumMachine.TargetId => new ErrorQuantumMachine(), + NoOpQuantumMachine.Target => new NoOpQuantumMachine(), + ErrorQuantumMachine.Target => new ErrorQuantumMachine(), _ => QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage) }; @@ -275,7 +276,7 @@ private static void Log(AzureSettings settings, string message) private static IQirSubmitter? QirSubmitter(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null"), - NoOpQirSubmitter.TargetId => new NoOpQirSubmitter(), + NoOpQirSubmitter.Target => new NoOpQirSubmitter(), _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. }; diff --git a/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs index 8be69b89968..6cea567a218 100644 --- a/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs +++ b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs @@ -3,6 +3,7 @@ using Microsoft.Azure.Quantum.Exceptions; using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; using Microsoft.Quantum.Simulation.Core; using System; using System.Threading.Tasks; @@ -15,13 +16,13 @@ namespace Microsoft.Quantum.EntryPointDriver.Mock internal class ErrorQuantumMachine : IQuantumMachine { /// - /// The target ID for the error quantum machine. + /// The target for the error quantum machine. /// - internal const string TargetId = "test.error"; + internal const string Target = "test.error"; public string ProviderId => nameof(ErrorQuantumMachine); - public string Target => TargetId; + string IAzureSubmitter.Target => Target; public Task> ExecuteAsync( EntryPointInfo info, TInput input) => diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs index 0b356817a10..eb46e28039e 100644 --- a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs @@ -15,13 +15,13 @@ namespace Microsoft.Quantum.EntryPointDriver.Mock internal class NoOpQirSubmitter : IQirSubmitter { /// - /// The target ID for the no-op QIR submitter. + /// The target for the no-op QIR submitter. /// - internal const string TargetId = "test.noop"; + internal const string Target = "test.noop"; public string ProviderId => nameof(NoOpQirSubmitter); - public string Target => TargetId; + string IAzureSubmitter.Target => Target; public Task SubmitAsync( Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) => diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs index db860ba46f3..92291bc13c2 100644 --- a/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; using Microsoft.Quantum.Simulation.Core; using System; using System.Threading.Tasks; @@ -14,13 +15,13 @@ namespace Microsoft.Quantum.EntryPointDriver.Mock internal class NoOpQuantumMachine : IQuantumMachine { /// - /// The target ID for the no-op quantum machine. + /// The target for the no-op quantum machine. /// - internal const string TargetId = "test.noop"; + internal const string Target = "test.noop"; public string ProviderId => nameof(NoOpQuantumMachine); - public string Target => TargetId; + string IAzureSubmitter.Target => Target; public Task> ExecuteAsync( EntryPointInfo info, TInput input) => From c5b67be9cd0a58887b40a07d5924d817305b91c5 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 12 May 2021 11:31:26 -0700 Subject: [PATCH 104/145] Add NoOpSubmitter --- .../EntryPointDriver.Tests/Tests.fs | 28 +++++++++---------- .../EntryPointDriver/Azure/Azure.cs | 3 +- .../Mock/ErrorQuantumMachine.cs | 2 +- .../Mock/NoOpQuantumMachine.cs | 2 +- .../{NoOpQirSubmitter.cs => NoOpSubmitter.cs} | 21 +++++++++----- src/Simulation/Simulators.Tests/CoreTests.cs | 4 +-- 6 files changed, 34 insertions(+), 26 deletions(-) rename src/Simulation/EntryPointDriver/Mock/{NoOpQirSubmitter.cs => NoOpSubmitter.cs} (50%) diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index a5a84e80e31..a5cc9818964 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -201,11 +201,11 @@ let private submitWithoutTarget = "--workspace" "myWorkspace" ] -/// Standard command-line arguments for the "submit" command using the "test.noop" target. -let private submitWithNoOpTarget = submitWithoutTarget @ ["--target"; "test.noop"] +/// Standard command-line arguments for the "submit" command using the "test.machine.noop" target. +let private submitWithNoOpTarget = submitWithoutTarget @ ["--target"; "test.machine.noop"] -/// Standard command-line arguments for the "submit" command using the "test.error" target. -let private submitWithErrorTarget = submitWithoutTarget @ ["--target"; "test.error"] +/// Standard command-line arguments for the "submit" command using the "test.machine.error" target. +let private submitWithErrorTarget = submitWithoutTarget @ ["--target"; "test.machine.error"] // No Option @@ -560,7 +560,7 @@ let ``Submit uses default values`` () = |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.noop + Target: test.machine.noop Storage: AAD Token: Base URI: @@ -577,12 +577,12 @@ let ``Submit uses default values`` () = [] let ``Submit uses default values with default target`` () = - let given = testWithTarget "test.noop" "Returns Unit" + let given = testWithTarget "test.machine.noop" "Returns Unit" given (submitWithoutTarget @ ["--verbose"]) |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.noop + Target: test.machine.noop Storage: AAD Token: Base URI: @@ -616,7 +616,7 @@ let ``Submit allows overriding default values`` () = |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.noop + Target: test.machine.noop Storage: myStorage AAD Token: myToken Base URI: myBaseUri @@ -650,7 +650,7 @@ let ``Submit allows overriding default values with default target`` () = |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.noop + Target: test.machine.noop Storage: myStorage AAD Token: myToken Base URI: myBaseUri @@ -687,7 +687,7 @@ let ``Submit allows to include --base-uri option when --location is not present` |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.noop + Target: test.machine.noop Storage: AAD Token: Base URI: myBaseUri @@ -713,7 +713,7 @@ let ``Submit allows to include --location option when --base-uri is not present` |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.noop + Target: test.machine.noop Storage: AAD Token: Base URI: @@ -739,7 +739,7 @@ let ``Submit allows spaces for the --location option`` () = |> yields "Subscription: mySubscription Resource Group: myResourceGroup Workspace: myWorkspace - Target: test.noop + Target: test.machine.noop Storage: AAD Token: Base URI: @@ -945,7 +945,7 @@ let ``Supports submitting multiple entry points`` () = "--workspace" "myWorkspace" "--target" - "test.noop" + "test.machine.noop" ] let given = test "Multiple entry points" let succeeds = yields "https://www.example.com/00000000-0000-0000-0000-0000000000000" @@ -966,7 +966,7 @@ let ``Supports submitting multiple entry points with different parameters`` () = "--workspace" "myWorkspace" "--target" - "test.noop" + "test.machine.noop" ] let entryPoint1Args = ["-n"; "42.5"] let entryPoint2Args = ["-s"; "Hello, World!"] diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index e9827d4be03..20e9cb43990 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -264,6 +264,7 @@ private static void Log(AzureSettings settings, string message) private static IQSharpSubmitter? QSharpSubmitter(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null."), + NoOpSubmitter.Target => new NoOpSubmitter(), _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. }; @@ -276,7 +277,7 @@ private static void Log(AzureSettings settings, string message) private static IQirSubmitter? QirSubmitter(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null"), - NoOpQirSubmitter.Target => new NoOpQirSubmitter(), + NoOpSubmitter.Target => new NoOpSubmitter(), _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. }; diff --git a/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs index 6cea567a218..6842d5a5b87 100644 --- a/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs +++ b/src/Simulation/EntryPointDriver/Mock/ErrorQuantumMachine.cs @@ -18,7 +18,7 @@ internal class ErrorQuantumMachine : IQuantumMachine /// /// The target for the error quantum machine. /// - internal const string Target = "test.error"; + internal const string Target = "test.machine.error"; public string ProviderId => nameof(ErrorQuantumMachine); diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs index 92291bc13c2..255f9e061b0 100644 --- a/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQuantumMachine.cs @@ -17,7 +17,7 @@ internal class NoOpQuantumMachine : IQuantumMachine /// /// The target for the no-op quantum machine. /// - internal const string Target = "test.noop"; + internal const string Target = "test.machine.noop"; public string ProviderId => nameof(NoOpQuantumMachine); diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mock/NoOpSubmitter.cs similarity index 50% rename from src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs rename to src/Simulation/EntryPointDriver/Mock/NoOpSubmitter.cs index eb46e28039e..b6721578565 100644 --- a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpSubmitter.cs @@ -1,30 +1,37 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; +using Microsoft.Quantum.Simulation.Core; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.Runtime; -using Microsoft.Quantum.Runtime.Submitters; namespace Microsoft.Quantum.EntryPointDriver.Mock { /// - /// A QIR submitter that does nothing. + /// A submitter that does nothing. /// - internal class NoOpQirSubmitter : IQirSubmitter + internal class NoOpSubmitter : IQirSubmitter, IQSharpSubmitter { /// - /// The target for the no-op QIR submitter. + /// The target for the no-op submitter. /// - internal const string Target = "test.noop"; + internal const string Target = "test.submitter.noop"; - public string ProviderId => nameof(NoOpQirSubmitter); + public string ProviderId => nameof(NoOpSubmitter); string IAzureSubmitter.Target => Target; public Task SubmitAsync( Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) => Task.FromResult(new ExampleJob()); + + public Task SubmitAsync( + EntryPointInfo entryPoint, TIn argument, SubmissionOptions options) => + Task.FromResult(new ExampleJob()); + + public string? Validate(EntryPointInfo entryPoint, TIn argument) => null; } } diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 5670734848a..2a5d39ef416 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -83,7 +83,7 @@ public void SubmitsQir() "--workspace", "baz", "--target", - "test.noop", + "test.submitter.noop", "--verbose"); ProcessRunner.Run("dotnet", args, out var output, out var error, out var status, out var ex); @@ -97,7 +97,7 @@ public void SubmitsQir() "Subscription: foo", "Resource Group: bar", "Workspace: baz", - "Target: test.noop", + "Target: test.submitter.noop", "Storage: ", "AAD Token: ", "Base URI: ", From ed4ef09f6bfb3c4ef5cc917c2f3f6bc92bdab1fd Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 12 May 2021 13:01:52 -0700 Subject: [PATCH 105/145] Don't fail if parameter types are not supported for QIR --- src/Simulation/CSharpGeneration/EntryPoint.fs | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Simulation/CSharpGeneration/EntryPoint.fs b/src/Simulation/CSharpGeneration/EntryPoint.fs index 0ef7203c2b1..ad96568c91d 100644 --- a/src/Simulation/CSharpGeneration/EntryPoint.fs +++ b/src/Simulation/CSharpGeneration/EntryPoint.fs @@ -148,21 +148,25 @@ let rec private qirArgumentValue (type_ : ResolvedType) (value : ExpressionSynta Option.map2 arrayValue (ident "item" |> qirArgumentValue itemType) (qirArgumentType itemType) | _ -> None -/// The list of QIR arguments for the entry point parameters and the result of parsing the command-line arguments. +/// The list of QIR arguments for the entry point parameters and the result of parsing the command-line arguments, or +/// None if not all parameters are supported in a QIR entry point. let private qirArguments parameters parseResult = - let argument param = - let value = - parseResult <.> (sprintf "ValueForOption<%s>" param.CSharpTypeName |> ident, [optionName param.Name]) - |> qirArgumentValue param.QSharpType - |> Option.defaultWith (fun () -> failwith "Unsupported parameter type.") + let argumentType = "global::Microsoft.Quantum.Runtime.Argument" + let listType = "global::System.Collections.Immutable.ImmutableList" - ``new`` (ident "global::Microsoft.Quantum.Runtime.Argument") ``(`` [literal param.Name; value] ``)`` + let argument param = + parseResult <.> (sprintf "ValueForOption<%s>" param.CSharpTypeName |> ident, [optionName param.Name]) + |> qirArgumentValue param.QSharpType + |> Option.map (fun value -> ``new`` (ident argumentType) ``(`` [literal param.Name; value] ``)``) - ident "global::System.Collections.Immutable.ImmutableList" - <.> (ident "Create", parameters |> Seq.map argument) + parameters + |> Seq.fold + (fun state param -> Option.map2 (fun xs x -> x :: xs) state (argument param)) + (Some []) + |> Option.map (fun args -> ident listType <.> (sprintf "Create<%s>" argumentType |> ident, args)) /// The QIR submission for the given entry point, parameters, and parsed arguments. Returns null if the QIR stream -/// resource does not exist. +/// resource does not exist, or the entry point contains unsupported parameter types. let private qirSubmission (entryPoint: QsCallable) parameters parseResult = let stream = ident "global::System.Reflection.Assembly" @@ -171,17 +175,15 @@ let private qirSubmission (entryPoint: QsCallable) parameters parseResult = let streamVar = ident "qirStream" - let submission = + let submission args = ``new`` (driverNamespace + ".Azure.QirSubmission" |> ``type``) ``(`` - [ - streamVar :> ExpressionSyntax - string entryPoint.FullName |> literal - qirArguments parameters parseResult - ] + [streamVar :> ExpressionSyntax; string entryPoint.FullName |> literal; args] ``)`` - ``?`` (stream |> ``is assign`` "{ }" streamVar) (submission, ``null``) + match qirArguments parameters parseResult with + | Some args -> ``?`` (stream |> ``is assign`` "{ }" streamVar) (submission args, ``null``) + | None -> upcast ``null`` /// Generates the Submit method for an entry point class. let private submitMethod context entryPoint parameters = From 82534b0b47ee88a271eefebd2c7b920c82b00e9e Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 12 May 2021 13:34:10 -0700 Subject: [PATCH 106/145] More helpful error message when missing QIR --- .../EntryPointDriver.Tests/Tests.fs | 11 ++++++- .../EntryPointDriver/Azure/Azure.cs | 26 +++++++++++----- .../EntryPointDriver/Mock/NoOpQirSubmitter.cs | 30 +++++++++++++++++++ 3 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index a5cc9818964..c38f72e109d 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -774,7 +774,7 @@ let ``Submit requires a positive number of shots`` () = [] let ``Submit fails with unknown target`` () = let given = test "Returns Unit" - given (submitWithoutTarget @ ["--target"; "foo"]) |> failsWith "The target 'foo' is not recognized." + given (submitWithoutTarget @ ["--target"; "foo"]) |> failsWith "No submitters were found for the target foo." [] let ``Submit supports dry run option`` () = @@ -813,6 +813,15 @@ let ``Submit catches exceptions`` () = This machine always has an error." +[] +let ``Submit shows specific error message when QIR stream is unavailable`` () = + let given = testWithTarget "test.submitter.qir.noop" "Returns Unit" + + given submitWithoutTarget + |> failsWith + ("The target test.submitter.qir.noop requires QIR submission, but the project was built without QIR. " + + "Please enable QIR generation in the project settings.") + // Help [] diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 20e9cb43990..800ce4c0e91 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -51,7 +51,18 @@ public static Task Submit( return SubmitQSharpMachine(settings, machine, qsSubmission); } - DisplayWithColor(ConsoleColor.Red, Console.Error, $"The target '{settings.Target}' is not recognized."); + if (qirSubmission is null && !(QirSubmitter(settings) is null)) + { + DisplayError( + $"The target {settings.Target} requires QIR submission, but the project was built without QIR. " + + "Please enable QIR generation in the project settings.", + null); + } + else + { + DisplayError($"No submitters were found for the target {settings.Target}.", null); + } + return Task.FromResult(1); } @@ -242,9 +253,9 @@ private static void Log(AzureSettings settings, string message) } /// - /// Returns a Q# machine. + /// Returns a Q# machine for the target in the given Azure settings. /// - /// The Azure Quantum submission settings. + /// The Azure settings. /// A quantum machine. /// .Target is null. private static IQuantumMachine? QSharpMachine(AzureSettings settings) => settings.Target switch @@ -256,9 +267,9 @@ private static void Log(AzureSettings settings, string message) }; /// - /// Returns a Q# submitter. + /// Returns a Q# submitter for the target in the given Azure settings. /// - /// The Azure Quantum submission settings. + /// The Azure settings. /// A Q# submitter. /// .Target is null. private static IQSharpSubmitter? QSharpSubmitter(AzureSettings settings) => settings.Target switch @@ -269,14 +280,15 @@ private static void Log(AzureSettings settings, string message) }; /// - /// Returns a QIR submitter. + /// Returns a QIR submitter for the target in the given Azure settings. /// - /// The Azure Quantum submission settings. + /// The Azure settings. /// A QIR submitter. /// .Target is null. private static IQirSubmitter? QirSubmitter(AzureSettings settings) => settings.Target switch { null => throw new ArgumentNullException(nameof(settings), "Target is null"), + NoOpQirSubmitter.Target => new NoOpQirSubmitter(), NoOpSubmitter.Target => new NoOpSubmitter(), _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. }; diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs new file mode 100644 index 00000000000..185df32c64d --- /dev/null +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.EntryPointDriver.Mock +{ + /// + /// A QIR submitter that does nothing. + /// + public class NoOpQirSubmitter : IQirSubmitter + { + /// + /// The target for the no-op QIR submitter. + /// + internal const string Target = "test.submitter.qir.noop"; + + public string ProviderId => nameof(NoOpQirSubmitter); + + string IAzureSubmitter.Target => Target; + + public Task SubmitAsync( + Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) => + Task.FromResult(new ExampleJob()); + } +} From 51a7c15100b5ba1a4e3c1b439b9adb2168da0196 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 12 May 2021 13:50:34 -0700 Subject: [PATCH 107/145] Add test for test.submitter.noop with Q# --- .../EntryPointDriver.Tests/Tests.fs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index c38f72e109d..a2c62190066 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -822,6 +822,30 @@ let ``Submit shows specific error message when QIR stream is unavailable`` () = ("The target test.submitter.qir.noop requires QIR submission, but the project was built without QIR. " + "Please enable QIR generation in the project settings.") +[] +let ``Submit supports Q# submitters`` () = + let given = testWithTarget "test.submitter.noop" "Returns Unit" + + given (submitWithoutTarget @ ["--verbose"]) + |> yields + "Subscription: mySubscription + Resource Group: myResourceGroup + Workspace: myWorkspace + Target: test.submitter.noop + Storage: + AAD Token: + Base URI: + Location: + Job Name: + Shots: 500 + Output: FriendlyUri + Dry Run: False + Verbose: True + + Submitting Q# entry point. + + https://www.example.com/00000000-0000-0000-0000-0000000000000" + // Help [] From 62493f7a10641cc2a14631a5af7377bfa55f7ae2 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 12 May 2021 17:18:04 -0700 Subject: [PATCH 108/145] Add submitter factory --- .../Microsoft.Azure.Quantum.Client.csproj | 1 + .../Azure.Quantum.Client/SubmitterFactory.cs | 126 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 src/Azure/Azure.Quantum.Client/SubmitterFactory.cs diff --git a/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj index 5cbb18eb53b..d3e44f8fb59 100644 --- a/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj +++ b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj @@ -6,6 +6,7 @@ netstandard2.1 x64 Client library for Azure Quantum. + Microsoft.Azure.Quantum diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs new file mode 100644 index 00000000000..27e9f921e9a --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +namespace Microsoft.Azure.Quantum +{ + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.IO; + using System.Linq; + using System.Reflection; + using Microsoft.Quantum.Runtime.Submitters; + + /// + /// Creates Azure Quantum submitters for specific targets. + /// + public static class SubmitterFactory + { + /// + /// Information about each supported QIR submitter. + /// + private static readonly ImmutableList QirSubmitters = ImmutableList.Empty; + + /// + /// Information about each supported Q# submitter. + /// + private static readonly ImmutableList QSharpSubmitters = ImmutableList.Empty; + + /// + /// Returns a QIR submitter. + /// + /// The ID of the execution target provider. + /// The name of the execution target. + /// The workspace used to manage jobs. + /// The connection string for the storage account. + /// A QIR submitter. + public static IQirSubmitter? QirSubmitter( + string providerId, string target, IWorkspace workspace, string? storageConnectionString) => + Submitter(QirSubmitters, providerId, target, workspace, storageConnectionString); + + /// + /// Returns a Q# submitter. + /// + /// The ID of the execution target provider. + /// The name of the execution target. + /// The workspace used to manage jobs. + /// The connection string for the storage account. + /// A Q# submitter. + public static IQSharpSubmitter? QSharpSubmitter( + string providerId, string target, IWorkspace workspace, string? storageConnectionString) => + Submitter(QSharpSubmitters, providerId, target, workspace, storageConnectionString); + + /// + /// Returns an instance of a submitter from the given list that matches the target. + /// + /// Information about each submitter. + /// The ID of the execution target provider. + /// The name of the execution target. + /// The workspace used to manage jobs. + /// The connection string for the storage account. + /// The type of the submitter interface. + /// The submitter instance. + private static T? Submitter( + IEnumerable submitters, + string providerId, + string target, + IWorkspace workspace, + string? storageConnectionString) + where T : class + { + var submitter = submitters.FirstOrDefault(s => target.StartsWith(s.TargetPrefix + ".")); + if (submitter is null) + { + return null; + } + + var type = QdkType(submitter.TypeName); + return (T)Activator.CreateInstance(type, providerId, target, workspace, storageConnectionString); + } + + /// + /// Returns a type from a QDK assembly given its type name. + /// + /// The fully-qualified or assembly-qualified type name. + /// The type. + private static Type QdkType(string name) + { + try + { + var version = Assembly.GetExecutingAssembly().GetName().Version; + var signedName = $"{name}, Version={version}, Culture=neutral, PublicKeyToken=40866b40fd95c7f5"; + return Type.GetType(signedName, true); + } + catch (FileLoadException) + { + return Type.GetType(name, true); + } + } + + /// + /// Information about a submitter. + /// + private class SubmitterInfo + { + /// + /// Initializes a new instance of the class. + /// + /// The prefix for targets supported by the submitter. + /// The fully-qualified or assembly-qualified name of the submitter type. + public SubmitterInfo(string targetPrefix, string typeName) => + (TargetPrefix, TypeName) = (targetPrefix, typeName); + + /// + /// The prefix for targets supported by the submitter. + /// + public string TargetPrefix { get; } + + /// + /// The fully-qualified or assembly-qualified name of the submitter type. + /// + public string TypeName { get; } + } + } +} From 158bbeec33edb0e9e0b078da595b64f0350617e9 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 13 May 2021 12:31:06 -0700 Subject: [PATCH 109/145] Mark CreateMachine obsolete --- src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs index cd61dd5ce49..98dfab392f9 100644 --- a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs +++ b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs @@ -17,6 +17,7 @@ public static class QuantumMachineFactory /// The execution target for job submission. /// The connection string for the Azure storage account. /// A quantum machine for job submission targeting targetName. + [Obsolete("Use SubmitterFactory.QSharpSubmitter.")] public static IQuantumMachine? CreateMachine( IWorkspace workspace, string targetName, string? storageConnectionString = null) { From bd11891d3eeef3afca7486a9ca58d6de92e6f77f Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 13 May 2021 12:38:37 -0700 Subject: [PATCH 110/145] Use SubmitterFactory in driver --- src/Simulation/EntryPointDriver/Azure/Azure.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 800ce4c0e91..7d3e9cada2a 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -257,10 +257,9 @@ private static void Log(AzureSettings settings, string message) /// /// The Azure settings. /// A quantum machine. - /// .Target is null. private static IQuantumMachine? QSharpMachine(AzureSettings settings) => settings.Target switch { - null => throw new ArgumentNullException(nameof(settings), "Target is null."), + null => null, NoOpQuantumMachine.Target => new NoOpQuantumMachine(), ErrorQuantumMachine.Target => new ErrorQuantumMachine(), _ => QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage) @@ -271,12 +270,11 @@ private static void Log(AzureSettings settings, string message) /// /// The Azure settings. /// A Q# submitter. - /// .Target is null. private static IQSharpSubmitter? QSharpSubmitter(AzureSettings settings) => settings.Target switch { - null => throw new ArgumentNullException(nameof(settings), "Target is null."), + null => null, NoOpSubmitter.Target => new NoOpSubmitter(), - _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. + _ => SubmitterFactory.QSharpSubmitter("TODO", settings.Target, settings.CreateWorkspace(), settings.Storage) }; /// @@ -284,13 +282,12 @@ private static void Log(AzureSettings settings, string message) /// /// The Azure settings. /// A QIR submitter. - /// .Target is null. private static IQirSubmitter? QirSubmitter(AzureSettings settings) => settings.Target switch { - null => throw new ArgumentNullException(nameof(settings), "Target is null"), + null => null, NoOpQirSubmitter.Target => new NoOpQirSubmitter(), NoOpSubmitter.Target => new NoOpSubmitter(), - _ => null // TODO: Add a factory to Microsoft.Azure.Quantum.Client. + _ => SubmitterFactory.QirSubmitter("TODO", settings.Target, settings.CreateWorkspace(), settings.Storage) }; /// From 181b7ac32c45d1968acd4ac838bf1ef55f812e0c Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 13 May 2021 13:42:47 -0700 Subject: [PATCH 111/145] Remove providerId parameter --- .../Azure.Quantum.Client/SubmitterFactory.cs | 26 +++++++------------ .../EntryPointDriver/Azure/Azure.cs | 4 +-- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs index 27e9f921e9a..3c1cfc64a4a 100644 --- a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs +++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs @@ -31,43 +31,35 @@ public static class SubmitterFactory /// /// Returns a QIR submitter. /// - /// The ID of the execution target provider. /// The name of the execution target. /// The workspace used to manage jobs. - /// The connection string for the storage account. + /// The connection string for the storage account. /// A QIR submitter. - public static IQirSubmitter? QirSubmitter( - string providerId, string target, IWorkspace workspace, string? storageConnectionString) => - Submitter(QirSubmitters, providerId, target, workspace, storageConnectionString); + public static IQirSubmitter? QirSubmitter(string target, IWorkspace workspace, string? storageConnection) => + Submitter(QirSubmitters, target, workspace, storageConnection); /// /// Returns a Q# submitter. /// - /// The ID of the execution target provider. /// The name of the execution target. /// The workspace used to manage jobs. - /// The connection string for the storage account. + /// The connection string for the storage account. /// A Q# submitter. public static IQSharpSubmitter? QSharpSubmitter( - string providerId, string target, IWorkspace workspace, string? storageConnectionString) => - Submitter(QSharpSubmitters, providerId, target, workspace, storageConnectionString); + string target, IWorkspace workspace, string? storageConnection) => + Submitter(QSharpSubmitters, target, workspace, storageConnection); /// /// Returns an instance of a submitter from the given list that matches the target. /// /// Information about each submitter. - /// The ID of the execution target provider. /// The name of the execution target. /// The workspace used to manage jobs. - /// The connection string for the storage account. + /// The connection string for the storage account. /// The type of the submitter interface. /// The submitter instance. private static T? Submitter( - IEnumerable submitters, - string providerId, - string target, - IWorkspace workspace, - string? storageConnectionString) + IEnumerable submitters, string target, IWorkspace workspace, string? storageConnection) where T : class { var submitter = submitters.FirstOrDefault(s => target.StartsWith(s.TargetPrefix + ".")); @@ -77,7 +69,7 @@ public static class SubmitterFactory } var type = QdkType(submitter.TypeName); - return (T)Activator.CreateInstance(type, providerId, target, workspace, storageConnectionString); + return (T)Activator.CreateInstance(type, target, workspace, storageConnection); } /// diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 7d3e9cada2a..a4b51985161 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -274,7 +274,7 @@ private static void Log(AzureSettings settings, string message) { null => null, NoOpSubmitter.Target => new NoOpSubmitter(), - _ => SubmitterFactory.QSharpSubmitter("TODO", settings.Target, settings.CreateWorkspace(), settings.Storage) + _ => SubmitterFactory.QSharpSubmitter(settings.Target, settings.CreateWorkspace(), settings.Storage) }; /// @@ -287,7 +287,7 @@ private static void Log(AzureSettings settings, string message) null => null, NoOpQirSubmitter.Target => new NoOpQirSubmitter(), NoOpSubmitter.Target => new NoOpSubmitter(), - _ => SubmitterFactory.QirSubmitter("TODO", settings.Target, settings.CreateWorkspace(), settings.Storage) + _ => SubmitterFactory.QirSubmitter(settings.Target, settings.CreateWorkspace(), settings.Storage) }; /// From 774c592fa0eae17688ffc9447153036386f0f6ff Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 18 May 2021 12:55:30 -0700 Subject: [PATCH 112/145] Add MicrosoftSimulatorSubmitter --- .../Azure.Quantum.Client/SubmitterFactory.cs | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs index 3c1cfc64a4a..6cb3e07b730 100644 --- a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs +++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs @@ -8,7 +8,6 @@ namespace Microsoft.Azure.Quantum using System; using System.Collections.Generic; using System.Collections.Immutable; - using System.IO; using System.Linq; using System.Reflection; using Microsoft.Quantum.Runtime.Submitters; @@ -21,7 +20,11 @@ public static class SubmitterFactory /// /// Information about each supported QIR submitter. /// - private static readonly ImmutableList QirSubmitters = ImmutableList.Empty; + private static readonly ImmutableList QirSubmitters = ImmutableList.Create( + new SubmitterInfo( + "microsoft", + "Microsoft.Quantum.Providers.Targets.MicrosoftSimulatorSubmitter, Microsoft.Quantum.Providers.Core", + "Create")); /// /// Information about each supported Q# submitter. @@ -69,7 +72,9 @@ public static class SubmitterFactory } var type = QdkType(submitter.TypeName); - return (T)Activator.CreateInstance(type, target, workspace, storageConnection); + var args = new object?[] { target, workspace, storageConnection }; + return (T)type.InvokeMember( + submitter.MethodName, BindingFlags.InvokeMethod, Type.DefaultBinder, null, args); } /// @@ -79,16 +84,9 @@ public static class SubmitterFactory /// The type. private static Type QdkType(string name) { - try - { - var version = Assembly.GetExecutingAssembly().GetName().Version; - var signedName = $"{name}, Version={version}, Culture=neutral, PublicKeyToken=40866b40fd95c7f5"; - return Type.GetType(signedName, true); - } - catch (FileLoadException) - { - return Type.GetType(name, true); - } + var version = Assembly.GetExecutingAssembly().GetName().Version; + var strongName = $"{name}, Version={version}, Culture=neutral, PublicKeyToken=40866b40fd95c7f5"; + return Type.GetType(strongName, true); } /// @@ -101,8 +99,9 @@ private class SubmitterInfo /// /// The prefix for targets supported by the submitter. /// The fully-qualified or assembly-qualified name of the submitter type. - public SubmitterInfo(string targetPrefix, string typeName) => - (TargetPrefix, TypeName) = (targetPrefix, typeName); + /// The name of the static factory method. + public SubmitterInfo(string targetPrefix, string typeName, string methodName) => + (TargetPrefix, TypeName, MethodName) = (targetPrefix, typeName, methodName); /// /// The prefix for targets supported by the submitter. @@ -113,6 +112,11 @@ public SubmitterInfo(string targetPrefix, string typeName) => /// The fully-qualified or assembly-qualified name of the submitter type. /// public string TypeName { get; } + + /// + /// The name of the static factory method. + /// + public string MethodName { get; } } } } From 8964fcbd1da02e37601d6f6ae56017bddee77758 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 18 May 2021 13:01:12 -0700 Subject: [PATCH 113/145] Update method name --- src/Azure/Azure.Quantum.Client/SubmitterFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs index 6cb3e07b730..e38e01bf3bf 100644 --- a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs +++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs @@ -24,7 +24,7 @@ public static class SubmitterFactory new SubmitterInfo( "microsoft", "Microsoft.Quantum.Providers.Targets.MicrosoftSimulatorSubmitter, Microsoft.Quantum.Providers.Core", - "Create")); + "QirSubmitter")); /// /// Information about each supported Q# submitter. From fcc72786edb58e650604a0838a5066959497f3e1 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 18 May 2021 13:58:09 -0700 Subject: [PATCH 114/145] Use regex for target matching --- .../Azure.Quantum.Client/SubmitterFactory.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs index e38e01bf3bf..4a46234c034 100644 --- a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs +++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs @@ -10,6 +10,7 @@ namespace Microsoft.Azure.Quantum using System.Collections.Immutable; using System.Linq; using System.Reflection; + using System.Text.RegularExpressions; using Microsoft.Quantum.Runtime.Submitters; /// @@ -22,7 +23,7 @@ public static class SubmitterFactory /// private static readonly ImmutableList QirSubmitters = ImmutableList.Create( new SubmitterInfo( - "microsoft", + new Regex(@"^microsoft\.simulator$"), "Microsoft.Quantum.Providers.Targets.MicrosoftSimulatorSubmitter, Microsoft.Quantum.Providers.Core", "QirSubmitter")); @@ -65,7 +66,7 @@ public static class SubmitterFactory IEnumerable submitters, string target, IWorkspace workspace, string? storageConnection) where T : class { - var submitter = submitters.FirstOrDefault(s => target.StartsWith(s.TargetPrefix + ".")); + var submitter = submitters.FirstOrDefault(s => s.TargetPattern.IsMatch(target)); if (submitter is null) { return null; @@ -97,16 +98,16 @@ private class SubmitterInfo /// /// Initializes a new instance of the class. /// - /// The prefix for targets supported by the submitter. + /// The pattern for targets supported by the submitter. /// The fully-qualified or assembly-qualified name of the submitter type. /// The name of the static factory method. - public SubmitterInfo(string targetPrefix, string typeName, string methodName) => - (TargetPrefix, TypeName, MethodName) = (targetPrefix, typeName, methodName); + public SubmitterInfo(Regex targetPattern, string typeName, string methodName) => + (TargetPattern, TypeName, MethodName) = (targetPattern, typeName, methodName); /// - /// The prefix for targets supported by the submitter. + /// The pattern for targets supported by the submitter. /// - public string TargetPrefix { get; } + public Regex TargetPattern { get; } /// /// The fully-qualified or assembly-qualified name of the submitter type. From 6255a152b94d8de1e2a744637e6e07c7a1f25f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 19 May 2021 15:38:00 -0700 Subject: [PATCH 115/145] Fix remaining merge conflicts. --- Simulation.sln | 3 --- 1 file changed, 3 deletions(-) diff --git a/Simulation.sln b/Simulation.sln index c5633252d78..419bd8075cf 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -878,15 +878,12 @@ Global {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {A7DB7367-9FD6-4164-8263-A05077BE54AB} = {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} {D7D34736-A719-4B45-A33F-2723F59EC29D} = {A7DB7367-9FD6-4164-8263-A05077BE54AB} -<<<<<<< HEAD {4E07F247-ED93-4497-8B58-022314308E67} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {A77E6661-D143-4E3E-BCD1-8E321A966829} = {4E07F247-ED93-4497-8B58-022314308E67} {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {C60226E3-98DE-4E92-AED4-B4A93D4CA063} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} {4794FC80-4594-403F-AFEC-4889EFE87EA0} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} -======= {A0B98D0E-FC28-4FD8-8806-4825B9F5489D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} ->>>>>>> feature/azure-quantum-simulator-client EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} From 1b514cc7e180ffb46b4c6505a90083b86f3db9b4 Mon Sep 17 00:00:00 2001 From: Scott Carda <55811729+ScottCarda-MS@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:00:19 -0700 Subject: [PATCH 116/145] Command-Line Compiler (#681) Added command line project --- Simulation.sln | 21 ++- src/Qir/Controller/Controller.cs | 2 +- .../Execution/QirCommandLineTool/Program.cs | 152 ++++++++++++++++++ .../QirCommandLineTool.csproj | 15 ++ .../QirExecutableGeneratorTests.cs | 6 +- .../QirExecutableTests.cs | 4 +- .../Execution/Tools/Executable/ClangClient.cs | 28 +++- .../Tools/Executable/IClangClient.cs | 2 +- .../Tools/Executable/IQirExecutable.cs | 7 +- .../Executable/IQirExecutableGenerator.cs | 6 +- .../Tools/Executable/QirExecutable.cs | 4 +- .../Executable/QirExecutableGenerator.cs | 25 ++- src/Qir/Execution/Tools/QirTools.cs | 25 +-- 13 files changed, 255 insertions(+), 42 deletions(-) create mode 100644 src/Qir/Execution/QirCommandLineTool/Program.cs create mode 100644 src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj diff --git a/Simulation.sln b/Simulation.sln index 419bd8075cf..f636b1c1a9a 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -121,7 +121,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Execution", "Execution", "{ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools\Microsoft.Quantum.Qir.Tools.csproj", "{C60226E3-98DE-4E92-AED4-B4A93D4CA063}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tests.Microsoft.Quantum.Qir.Tools\Tests.Microsoft.Quantum.Qir.Tools.csproj", "{4794FC80-4594-403F-AFEC-4889EFE87EA0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tests.Microsoft.Quantum.Qir.Tools\Tests.Microsoft.Quantum.Qir.Tools.csproj", "{4794FC80-4594-403F-AFEC-4889EFE87EA0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirCommandLineTool", "src\Qir\Execution\QirCommandLineTool\QirCommandLineTool.csproj", "{039D2649-20F6-46C7-8599-C44F3AA2CD4C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QirExe", "src\Simulation\Simulators.Tests\TestProjects\QirExe\QirExe.csproj", "{A0B98D0E-FC28-4FD8-8806-4825B9F5489D}" EndProject @@ -809,6 +811,22 @@ Global {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|x64.ActiveCfg = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|x64.Build.0 = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|Any CPU.Build.0 = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|x64.ActiveCfg = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|x64.Build.0 = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -883,6 +901,7 @@ Global {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {C60226E3-98DE-4E92-AED4-B4A93D4CA063} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} {4794FC80-4594-403F-AFEC-4889EFE87EA0} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} + {039D2649-20F6-46C7-8599-C44F3AA2CD4C} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} {A0B98D0E-FC28-4FD8-8806-4825B9F5489D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index 1ae7e6a747c..93b8b38a8bd 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -41,7 +41,7 @@ public static async Task ExecuteAsync( var bytecodeArray = input.QirBytecode.Array.Skip(input.QirBytecode.Offset).Take(input.QirBytecode.Count).ToList().ToArray(); var executableFile = new FileInfo(Path.Combine(BinaryDirectoryPath, ExecutableName)); var executable = new QirFullStateExecutable(executableFile, bytecodeArray, logger); - await executable.BuildAsync(executionInfo.EntryPoint, libraryDirectory, includeDirectory); + await executable.BuildAsync(executionInfo.EntryPoint, new[] { libraryDirectory }, new[] { includeDirectory }); // Step 3: Run executable. if (outputFile.Exists) diff --git a/src/Qir/Execution/QirCommandLineTool/Program.cs b/src/Qir/Execution/QirCommandLineTool/Program.cs new file mode 100644 index 00000000000..760788508e7 --- /dev/null +++ b/src/Qir/Execution/QirCommandLineTool/Program.cs @@ -0,0 +1,152 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Help; +using System.CommandLine.Invocation; +using System.CommandLine.Parsing; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Tools; + +namespace Microsoft.Quantum.CommandLineCompiler +{ + class Program + { + private static async Task Main(string[] args) + { + var buildCommand = CreateBuildCommand(); + + var root = new RootCommand() { buildCommand }; + SetSubCommandAsDefault(root, buildCommand); + root.Description = "Command-line tool for processing QIR DLL files."; + root.TreatUnmatchedTokensAsErrors = true; + + Console.OutputEncoding = Encoding.UTF8; + return await new CommandLineBuilder(root) + .UseDefaults() + .UseHelpBuilder(context => new QsHelpBuilder(context.Console)) + .Build() + .InvokeAsync(args); + } + + /// + /// Creates the Build command for the command line compiler, which is used to + /// compile the executables from a given QIR DLL. + /// + /// The Build command. + private static Command CreateBuildCommand() + { + var buildCommand = new Command("build", "(default) Build the executables from a QIR DLL.") + { + Handler = CommandHandler.Create((BuildOptions settings) => + { + return QirTools.BuildFromQSharpDll(settings.QSharpDll, settings.LibraryDirectories, settings.IncludeDirectories, settings.ExecutablesDirectory); + }) + }; + buildCommand.TreatUnmatchedTokensAsErrors = true; + + buildCommand.AddOption(new Option( + aliases: new string[] { "--qsharp-dll", "--dll" }, + description: "The path to the .NET DLL file generated by the Q# compiler.") + { + Required = true + }); + + buildCommand.AddOption(new Option( + aliases: new string[] { "--library-directories", "--lib" }, + description: "One or more paths to the directories containing the libraries to be linked.") + { + Required = false, + Argument = new Argument(() => new DirectoryInfo[] { }) + { + Arity = ArgumentArity.OneOrMore + } + }); + + buildCommand.AddOption(new Option( + aliases: new string[] { "--include-directories", "--include" }, + description: "One or more paths to the directories containing the headers required for compilation.") + { + Required = false, + Argument = new Argument(() => new DirectoryInfo[] { }) + { + Arity = ArgumentArity.OneOrMore + } + }); + + buildCommand.AddOption(new Option( + aliases: new string[] { "--executables-directory", "--exe" }, + description: "The path to the output directory where the created executables will be placed.") + { + Required = true + }); + + return buildCommand; + } + + /// + /// Copies the handle and options from the given sub command to the given command. + /// + /// The command whose handle and options will be set. + /// The sub command that will be copied from. + private static void SetSubCommandAsDefault(Command root, Command subCommand) + { + root.Handler = subCommand.Handler; + foreach (var option in subCommand.Options) + { + root.AddOption(option); + } + } + + /// + /// A modification of the command-line class. + /// + private sealed class QsHelpBuilder : HelpBuilder + { + /// + /// Creates a new help builder using the given console. + /// + /// The console to use. + internal QsHelpBuilder(IConsole console) : base(console) + { + } + + protected override string ArgumentDescriptor(IArgument argument) + { + // Hide long argument descriptors. + var descriptor = base.ArgumentDescriptor(argument); + return descriptor.Length > 30 ? argument.Name : descriptor; + } + } + + /// + /// A class for encapsulating the different options for the build command. + /// + public sealed class BuildOptions + { + /// + /// The path to the .NET DLL file generated by the Q# compiler. + /// + public FileInfo QSharpDll { get; set; } + + /// + /// One or more paths to the directories containing the libraries to be linked. + /// + public DirectoryInfo[] LibraryDirectories { get; set; } + + /// + /// One or more paths to the directories containing the headers required for compilation. + /// + public DirectoryInfo[] IncludeDirectories { get; set; } + + /// + /// The path to the output directory where the created executables will be placed. + /// + public DirectoryInfo ExecutablesDirectory { get; set; } + } + } +} diff --git a/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj b/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj new file mode 100644 index 00000000000..868df199d12 --- /dev/null +++ b/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj @@ -0,0 +1,15 @@ + + + + Exe + netcoreapp3.1 + true + + + + + + + + + diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs index b110c59df65..fd88b7550f6 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs @@ -65,14 +65,14 @@ public void Dispose() public async Task TestGenerateExecutable() { var executableFile = new FileInfo(Path.Combine(binDirectory.FullName, "executableFile")); - await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, libraryDirectory, includeDirectory, linkLibraries); + await executableGenerator.GenerateExecutableAsync(executableFile, sourceDirectory, new[] { libraryDirectory }, new[] { includeDirectory }, linkLibraries); // Verify invocation of clang. clangClientMock.Verify(obj => obj.CreateExecutableAsync( It.Is(s => s.OrderBy(val => val).SequenceEqual(sourceFiles.OrderBy(val => val.FullName).Select(fileInfo => fileInfo.FullName))), It.Is(s => s.OrderBy(val => val).SequenceEqual(linkLibraries.OrderBy(val => val))), - libraryDirectory.FullName, - includeDirectory.FullName, + new[] { libraryDirectory.FullName }, + new[] { includeDirectory.FullName }, executableFile.FullName)); // Verify files were copied. diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs index 8c3b469c2a5..61750a83d5c 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -72,7 +72,7 @@ public async Task TestBuild() }); // Build the executable. - await qirExecutable.Object.BuildAsync(entryPoint, libraryDirectory, includeDirectory); + await qirExecutable.Object.BuildAsync(entryPoint, new[] { libraryDirectory }, new[] { includeDirectory }); // Verify that the "bytecode" file was created correctly. var bytecodeFilePath = new FileInfo(Path.Combine(sourceDirectory.FullName, "qir.bc")); @@ -90,7 +90,7 @@ public async Task TestBuild() Assert.Equal(driverFileContents, actualDriverContents); // Verify that the executable was generated. - executableGeneratorMock.Verify(obj => obj.GenerateExecutableAsync(executableFile, It.Is(arg => arg.FullName == sourceDirectory.FullName), libraryDirectory, includeDirectory, linkLibraries)); + executableGeneratorMock.Verify(obj => obj.GenerateExecutableAsync(executableFile, It.Is(arg => arg.FullName == sourceDirectory.FullName), new[] { libraryDirectory }, new[] { includeDirectory }, linkLibraries)); } [Fact] diff --git a/src/Qir/Execution/Tools/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs index 0279e8cdf53..a8e74f2a404 100644 --- a/src/Qir/Execution/Tools/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Utility; @@ -11,6 +12,8 @@ namespace Microsoft.Quantum.Qir.Tools.Executable internal class ClangClient : IClangClient { private const string LinkFlag = " -l "; + private const string LibraryPathFlag = " -L "; + private const string IncludePathFlag = " -I "; private readonly ILogger logger; public ClangClient(ILogger logger) @@ -18,18 +21,20 @@ public ClangClient(ILogger logger) this.logger = logger; } - public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string includePath, string outputPath) + public async Task CreateExecutableAsync(string[] inputFiles, string[] linkedLibraries, string[] libraryPaths, string[] includePaths, string outputPath) { var inputsArg = string.Join(' ', inputFiles); // string.Join does not automatically prepend the delimiter, so it is included again in the string here. - var librariesArg = $"{LinkFlag} {string.Join(LinkFlag, libraries)}"; - var arguments = $"{inputsArg} -I {includePath} -L {libraryPath} {librariesArg} -o {outputPath} -std=c++17 -v"; - logger.LogInfo($"Invoking clang with the following arguments: {arguments}"); + var linkedLibrariesArg = $"{LinkFlag} {string.Join(LinkFlag, linkedLibraries)}"; + var libraryPathsArg = $"{LibraryPathFlag} {string.Join(LibraryPathFlag, libraryPaths)}"; + var includePathsArg = $"{IncludePathFlag} {string.Join(IncludePathFlag, includePaths)}"; + var arguments = $"{inputsArg} {includePathsArg} {libraryPathsArg} {linkedLibrariesArg} -o {outputPath} -std=c++17 -v"; + logger?.LogInfo($"Invoking clang with the following arguments: {arguments}"); var taskCompletionSource = new TaskCompletionSource(); using var process = new Process(); - Environment.SetEnvironmentVariable("DYLD_LIBRARY_PATH", libraryPath); - Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", libraryPath); + AddPathsToEnvironmentVariable("DYLD_LIBRARY_PATH", libraryPaths); + AddPathsToEnvironmentVariable("LD_LIBRARY_PATH", libraryPaths); process.StartInfo = new ProcessStartInfo { FileName = "clang++", @@ -40,5 +45,16 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] libraries, process.Start(); await taskCompletionSource.Task; } + + private static void AddPathsToEnvironmentVariable(string variable, string[] values) + { + var newValue = string.Join(Path.PathSeparator, values); + var oldValue = Environment.GetEnvironmentVariable(variable); + if (oldValue != null) + { + newValue = oldValue + $"{Path.PathSeparator}{newValue}"; + } + Environment.SetEnvironmentVariable(variable, newValue); + } } } diff --git a/src/Qir/Execution/Tools/Executable/IClangClient.cs b/src/Qir/Execution/Tools/Executable/IClangClient.cs index f5a1bb38135..87423492187 100644 --- a/src/Qir/Execution/Tools/Executable/IClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/IClangClient.cs @@ -10,6 +10,6 @@ namespace Microsoft.Quantum.Qir.Tools.Executable /// internal interface IClangClient { - Task CreateExecutableAsync(string[] inputFiles, string[] libraries, string libraryPath, string includePath, string outputPath); + Task CreateExecutableAsync(string[] inputFiles, string[] linkedLibraries, string[] libraryPaths, string[] includePaths, string outputPath); } } diff --git a/src/Qir/Execution/Tools/Executable/IQirExecutable.cs b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs index 477dd2cfe2a..e3ad50a6fcb 100644 --- a/src/Qir/Execution/Tools/Executable/IQirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/IQirExecutable.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Serialization; @@ -13,10 +14,10 @@ public interface IQirExecutable /// Builds the executable. /// /// Entry point operation. - /// Directory containing libraries to link. - /// Directory containing files to include. + /// Directories containing libraries to link. + /// Directories containing files to include. /// - Task BuildAsync(EntryPointOperation entryPoint, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory); + Task BuildAsync(EntryPointOperation entryPoint, IList libraryDirectories, IList includeDirectories); /// /// Runs the executable. diff --git a/src/Qir/Execution/Tools/Executable/IQirExecutableGenerator.cs b/src/Qir/Execution/Tools/Executable/IQirExecutableGenerator.cs index 3ddb310f98e..3715a8fed2e 100644 --- a/src/Qir/Execution/Tools/Executable/IQirExecutableGenerator.cs +++ b/src/Qir/Execution/Tools/Executable/IQirExecutableGenerator.cs @@ -14,10 +14,10 @@ internal interface IQirExecutableGenerator /// /// File path to create the executable at. Dependencies will be copied to its directory. /// Location of the source files. - /// Location of the libraries that must be linked. - /// Location of the headers that must be included. + /// Locations of the libraries that must be linked. + /// Locations of the headers that must be included. /// Libraries to link. /// - public Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, IList linkLibraries); + public Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, IList libraryDirectories, IList includeDirectories, IList linkLibraries); } } diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs index 4c6f73c7d2d..9aa7d671b8a 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -49,7 +49,7 @@ internal QirExecutable(FileInfo executableFile, byte[] qirBytecode, ILogger logg this.executableGenerator = executableGenerator; } - public async Task BuildAsync(EntryPointOperation entryPoint, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory) + public async Task BuildAsync(EntryPointOperation entryPoint, IList libraryDirectories, IList includeDirectories) { var sourceDirectory = new DirectoryInfo(SourceDirectoryPath); if (sourceDirectory.Exists) @@ -77,7 +77,7 @@ public async Task BuildAsync(EntryPointOperation entryPoint, DirectoryInfo libra } logger.LogInfo($"Created bytecode file at {bytecodeFile.FullName}."); - await executableGenerator.GenerateExecutableAsync(ExecutableFile, sourceDirectory, libraryDirectory, includeDirectory, LinkLibraries); + await executableGenerator.GenerateExecutableAsync(ExecutableFile, sourceDirectory, libraryDirectories, includeDirectories, LinkLibraries); } public async Task RunAsync(ExecutionInformation executionInformation, Stream output) diff --git a/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs index 80eaf8a768a..3201adeebe1 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs @@ -20,25 +20,25 @@ public QirExecutableGenerator(IClangClient clangClient, ILogger logger) this.logger = logger; } - public async Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, DirectoryInfo libraryDirectory, DirectoryInfo includeDirectory, IList linkLibraries) + public async Task GenerateExecutableAsync(FileInfo executableFile, DirectoryInfo sourceDirectory, IList libraryDirectories, IList includeDirectories, IList linkLibraries) { // Wrap in a Task.Run because FileInfo methods are not asynchronous. await Task.Run(async () => { var binDirectory = executableFile.Directory; - logger.LogInfo($"Creating binary directory at {binDirectory.FullName}."); + logger?.LogInfo($"Creating binary directory at {binDirectory.FullName}."); executableFile.Directory.Create(); // Copy all library contents to bin. - logger.LogInfo("Copying library directory contents into the executable's folder."); - var libraryFiles = libraryDirectory.GetFiles(); - foreach (var file in libraryFiles) + logger?.LogInfo("Copying library directories into the executable's folder."); + + foreach (var dir in libraryDirectories) { - CopyFileIfNotExists(file, binDirectory); + CopyDirectoryContents(dir, binDirectory); } var inputFiles = sourceDirectory.GetFiles().Select(fileInfo => fileInfo.FullName).ToArray(); - await clangClient.CreateExecutableAsync(inputFiles, linkLibraries.ToArray(), libraryDirectory.FullName, includeDirectory.FullName, executableFile.FullName); + await clangClient.CreateExecutableAsync(inputFiles, linkLibraries.ToArray(), libraryDirectories.Select(dir => dir.FullName).ToArray(), includeDirectories.Select(dir => dir.FullName).ToArray(), executableFile.FullName); }); } @@ -48,7 +48,16 @@ private void CopyFileIfNotExists(FileInfo fileToCopy, DirectoryInfo destinationD if (!File.Exists(newPath)) { var newFile = fileToCopy.CopyTo(newPath); - logger.LogInfo($"Copied file {fileToCopy.FullName} to {newFile.FullName}"); + logger?.LogInfo($"Copied file {fileToCopy.FullName} to {newFile.FullName}"); + } + } + + private void CopyDirectoryContents(DirectoryInfo directoryToCopy, DirectoryInfo destinationDirectory) + { + FileInfo[] files = directoryToCopy.GetFiles(); + foreach (var file in files) + { + CopyFileIfNotExists(file, destinationDirectory); } } } diff --git a/src/Qir/Execution/Tools/QirTools.cs b/src/Qir/Execution/Tools/QirTools.cs index e430ce5501b..b79c73072bb 100644 --- a/src/Qir/Execution/Tools/QirTools.cs +++ b/src/Qir/Execution/Tools/QirTools.cs @@ -1,13 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Microsoft.Quantum.Qir.Tools.Executable; -using Microsoft.Quantum.QsCompiler; -using Microsoft.Quantum.QsCompiler.QIR; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.Quantum.Qir.Tools.Executable; +using Microsoft.Quantum.QsCompiler; +using Microsoft.Quantum.QsCompiler.QIR; namespace Microsoft.Quantum.Qir.Tools { @@ -20,13 +21,13 @@ public static class QirTools /// Creates a QIR-based executable from a .NET DLL generated by the Q# compiler. /// /// .NET DLL generated by the Q# compiler. - /// Directory where the libraries to link to are located. - /// Directory where the headers needed for compilation are located. + /// Directory where the libraries to link to are located. + /// Directory where the headers needed for compilation are located. /// Directory where the created executables are placed. public static async Task BuildFromQSharpDll( FileInfo qsharpDll, - DirectoryInfo libraryDirectory, - DirectoryInfo includeDirectory, + IList libraryDirectories, + IList includeDirectories, DirectoryInfo executablesDirectory) { using var qirContentStream = new MemoryStream(); @@ -34,19 +35,19 @@ public static async Task BuildFromQSharpDll( { throw new ArgumentException("The given DLL does not contain QIR byte code."); } - + if (!executablesDirectory.Exists) { executablesDirectory.Create(); } - + var tasks = EntryPointOperationLoader.LoadEntryPointOperations(qsharpDll).Select(entryPointOp => { - var exeFileInfo = new FileInfo(Path.Combine(executablesDirectory.FullName, entryPointOp.Name)); + var exeFileInfo = new FileInfo(Path.Combine(executablesDirectory.FullName, $"{entryPointOp.Name}.exe")); var exe = new QirFullStateExecutable(exeFileInfo, qirContentStream.ToArray()); - return exe.BuildAsync(entryPointOp, libraryDirectory, includeDirectory); + return exe.BuildAsync(entryPointOp, libraryDirectories, includeDirectories); }); - + await Task.WhenAll(tasks); // ToDo: Return list of created file names From 1b57f3371c5173ad2139f004f5894b29a1a881eb Mon Sep 17 00:00:00 2001 From: Scott Carda <55811729+ScottCarda-MS@users.noreply.github.com> Date: Tue, 8 Jun 2021 10:04:17 -0700 Subject: [PATCH 117/145] QIR Command Line Tool - Automatically Use Required Resources (#704) Automated the use of standard required libraries and headers. Added Pack As Tool. --- .../Execution/QirCommandLineTool/Program.cs | 4 +- .../QirCommandLineTool.csproj | 9 ++-- .../QirExecutableTests.cs | 7 ++++ .../Tools/Executable/QirExecutable.cs | 9 ++-- .../Executable/QirExecutableGenerator.cs | 32 ++++++++++++++- .../Executable/QirFullStateExecutable.cs | 37 +++++++++++++---- .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 41 +++++++++++++++++++ src/Qir/Execution/Tools/Utility/ILogger.cs | 6 +++ src/Qir/Execution/Tools/Utility/Logger.cs | 6 +++ 9 files changed, 130 insertions(+), 21 deletions(-) diff --git a/src/Qir/Execution/QirCommandLineTool/Program.cs b/src/Qir/Execution/QirCommandLineTool/Program.cs index 760788508e7..6bdeb704674 100644 --- a/src/Qir/Execution/QirCommandLineTool/Program.cs +++ b/src/Qir/Execution/QirCommandLineTool/Program.cs @@ -43,9 +43,7 @@ private static Command CreateBuildCommand() var buildCommand = new Command("build", "(default) Build the executables from a QIR DLL.") { Handler = CommandHandler.Create((BuildOptions settings) => - { - return QirTools.BuildFromQSharpDll(settings.QSharpDll, settings.LibraryDirectories, settings.IncludeDirectories, settings.ExecutablesDirectory); - }) + QirTools.BuildFromQSharpDll(settings.QSharpDll, settings.LibraryDirectories, settings.IncludeDirectories, settings.ExecutablesDirectory)) }; buildCommand.TreatUnmatchedTokensAsErrors = true; diff --git a/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj b/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj index 868df199d12..bbbd132751f 100644 --- a/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj +++ b/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj @@ -1,5 +1,5 @@ - - + + Exe netcoreapp3.1 @@ -7,9 +7,8 @@ - - - + + diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs index 61750a83d5c..292f1e7d3d9 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Serialization; using Microsoft.Quantum.Qir.Tools.Driver; @@ -27,6 +28,8 @@ public class QirExecutableTests : IDisposable private readonly FileInfo executableFile; private readonly byte[] qirBytecode = { 1, 2, 3, 4, 5 }; private readonly IList linkLibraries; + private readonly IList headerDirectories; + private readonly IList libraryDirectories; public QirExecutableTests() { @@ -46,9 +49,13 @@ public QirExecutableTests() runnerMock = new Mock(); qirExecutable = new Mock(executableFile, qirBytecode, Mock.Of(), driverGeneratorMock.Object, executableGeneratorMock.Object, runnerMock.Object) { CallBase = true }; linkLibraries = new List { "lib1", "lib2" }; + headerDirectories = new List(); + libraryDirectories = new List(); qirExecutable.SetupGet(obj => obj.LinkLibraries).Returns(linkLibraries); qirExecutable.SetupGet(obj => obj.SourceDirectoryPath).Returns(sourceDirectory.FullName); qirExecutable.SetupGet(obj => obj.DriverFileExtension).Returns(".cpp"); + qirExecutable.SetupGet(obj => obj.HeaderDirectories).Returns(headerDirectories); + qirExecutable.SetupGet(obj => obj.LibraryDirectories).Returns(libraryDirectories); } public void Dispose() diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs index 9aa7d671b8a..a962aa46a76 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Serialization; using Microsoft.Quantum.Qir.Tools.Driver; @@ -20,6 +21,9 @@ public abstract class QirExecutable : IQirExecutable public virtual string SourceDirectoryPath => "src"; public abstract string DriverFileExtension { get; } + public abstract IList LinkLibraries { get; } + public abstract IList HeaderDirectories { get; } + public abstract IList LibraryDirectories { get; } protected FileInfo ExecutableFile { get; } @@ -76,8 +80,7 @@ public async Task BuildAsync(EntryPointOperation entryPoint, IList LinkLibraries { get; } } } diff --git a/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs index 3201adeebe1..d95b80cafe5 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -32,13 +33,40 @@ await Task.Run(async () => // Copy all library contents to bin. logger?.LogInfo("Copying library directories into the executable's folder."); + if (!sourceDirectory.Exists) + { + logger?.LogWarning($"Cannot find source directory: {sourceDirectory.FullName}"); + } + + var libDirs = new List(); foreach (var dir in libraryDirectories) { - CopyDirectoryContents(dir, binDirectory); + if (!dir.Exists) + { + logger?.LogWarning($"Cannot find given directory: {dir.FullName}"); + } + else + { + CopyDirectoryContents(dir, binDirectory); + libDirs.Add(dir.FullName); + } + } + + var includeDirs = new List(); + foreach (var dir in includeDirectories) + { + if (!dir.Exists) + { + logger?.LogWarning($"Could not find given directory: {dir.FullName}"); + } + else + { + includeDirs.Add(dir.FullName); + } } var inputFiles = sourceDirectory.GetFiles().Select(fileInfo => fileInfo.FullName).ToArray(); - await clangClient.CreateExecutableAsync(inputFiles, linkLibraries.ToArray(), libraryDirectories.Select(dir => dir.FullName).ToArray(), includeDirectories.Select(dir => dir.FullName).ToArray(), executableFile.FullName); + await clangClient.CreateExecutableAsync(inputFiles, linkLibraries.ToArray(), libDirs.ToArray(), includeDirs.ToArray(), executableFile.FullName); }); } diff --git a/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs index 03362d370a6..de394c70e0f 100644 --- a/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; using System.Collections.Generic; using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; using Microsoft.Quantum.Qir.Tools.Driver; using Microsoft.Quantum.Qir.Utility; @@ -13,20 +16,40 @@ namespace Microsoft.Quantum.Qir.Tools.Executable /// public class QirFullStateExecutable : QirExecutable { + public override string DriverFileExtension => "cpp"; + + public override IList LinkLibraries => new List { + "Microsoft.Quantum.Qir.Runtime", + "Microsoft.Quantum.Qir.QSharp.Foundation", + "Microsoft.Quantum.Qir.QSharp.Core" + }; + + public override IList HeaderDirectories { get; } = new List(); + + public override IList LibraryDirectories { get; } = new List(); + public QirFullStateExecutable(FileInfo executableFile, byte[] qirBytecode, ILogger logger = null) : base(executableFile, qirBytecode, new QirFullStateDriverGenerator(), logger) { - } + var thisModulePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (string.IsNullOrWhiteSpace(thisModulePath)) + { + throw new InvalidOperationException("Could not get a path for the current assembly location."); + } + HeaderDirectories.Add(new DirectoryInfo(Path.Combine(thisModulePath, "runtimes", "any", "native", "include"))); + HeaderDirectories.Add(new DirectoryInfo(Path.Combine(thisModulePath, "Externals", "CLI11"))); - public override IList LinkLibraries => new List { - "Microsoft.Quantum.Qir.Runtime", - "Microsoft.Quantum.Qir.QSharp.Foundation", - "Microsoft.Quantum.Qir.QSharp.Core" - }; + var osID = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win-x64" + : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux-x64" + : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx-x64" + : throw new ArgumentException("Unsupported operating system architecture."); - public override string DriverFileExtension => "cpp"; + LibraryDirectories.Add(new DirectoryInfo(Path.Combine(thisModulePath, "runtimes", osID, "native"))); + LibraryDirectories.Add(new DirectoryInfo(Path.Combine(thisModulePath, "Libraries", osID))); + LibraryDirectories.Add(new DirectoryInfo(Path.Combine(thisModulePath, "Libraries"))); + } } } diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index 8917f61f09e..dad660fc9f0 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -1,5 +1,7 @@  + + netstandard2.1 x64 @@ -50,4 +52,43 @@ + + + runtimes\%(RecursiveDir)%(FileName)%(Extension) + PreserveNewest + false + + + runtimes\any\native\include\%(RecursiveDir)%(FileName)%(Extension) + PreserveNewest + false + + + + + + Libraries\%(FileName)%(Extension) + PreserveNewest + false + + + + + + Libraries\win-x64\%(RecursiveDir)%(FileName)%(Extension) + PreserveNewest + false + + + Libraries\osx-x64\%(RecursiveDir)%(FileName)%(Extension) + PreserveNewest + false + + + Libraries\linux-x64\%(RecursiveDir)%(FileName)%(Extension) + PreserveNewest + false + + + diff --git a/src/Qir/Execution/Tools/Utility/ILogger.cs b/src/Qir/Execution/Tools/Utility/ILogger.cs index 7049bee9582..075fc708947 100644 --- a/src/Qir/Execution/Tools/Utility/ILogger.cs +++ b/src/Qir/Execution/Tools/Utility/ILogger.cs @@ -17,6 +17,12 @@ public interface ILogger /// Message to log. void LogInfo(string message); + /// + /// Logs a message at the "warning" level. + /// + /// Message to log. + void LogWarning(string message); + /// /// Logs a message at the "error" level. /// diff --git a/src/Qir/Execution/Tools/Utility/Logger.cs b/src/Qir/Execution/Tools/Utility/Logger.cs index 4aa2074a760..e5f2fe5b107 100644 --- a/src/Qir/Execution/Tools/Utility/Logger.cs +++ b/src/Qir/Execution/Tools/Utility/Logger.cs @@ -20,6 +20,7 @@ public Logger(IClock clock) // ...{exception type}: {exception message}{Environment.NewLine}{stack trace}. private const string ExceptionMessageFormat = "Exception encountered: {0}: {1}{2}{3}"; private const string InfoLevel = "INFO"; + private const string WarningLevel = "WARNING"; private const string ErrorLevel = "ERROR"; public void LogInfo(string message) @@ -27,6 +28,11 @@ public void LogInfo(string message) Console.WriteLine(LogFormat, clock.Now, InfoLevel, message); } + public void LogWarning(string message) + { + Console.WriteLine(LogFormat, clock.Now, WarningLevel, message); + } + public void LogError(string message) { Console.WriteLine(LogFormat, clock.Now, ErrorLevel, message); From 771098cad94fb6915bf7ca342c351b210efbc6df Mon Sep 17 00:00:00 2001 From: Scott Carda <55811729+ScottCarda-MS@users.noreply.github.com> Date: Mon, 14 Jun 2021 23:04:50 -0700 Subject: [PATCH 118/145] QIR Command Line Tool - Packaging Fixes (#723) * Renamed Tool to `qir-cmd` and changed output folder to `internal_tools` --- Simulation.sln | 38 +++++++++---------- build/pack.ps1 | 3 ++ build/set-env.ps1 | 2 + ...rosoft.Quantum.Qir.CommandLineTool.csproj} | 6 +++ .../Program.cs | 2 +- 5 files changed, 31 insertions(+), 20 deletions(-) rename src/Qir/Execution/{QirCommandLineTool/QirCommandLineTool.csproj => CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj} (66%) rename src/Qir/Execution/{QirCommandLineTool => CommandLineTool}/Program.cs (99%) diff --git a/Simulation.sln b/Simulation.sln index f636b1c1a9a..9e953b35278 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -123,9 +123,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.Tools EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tests.Microsoft.Quantum.Qir.Tools\Tests.Microsoft.Quantum.Qir.Tools.csproj", "{4794FC80-4594-403F-AFEC-4889EFE87EA0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirCommandLineTool", "src\Qir\Execution\QirCommandLineTool\QirCommandLineTool.csproj", "{039D2649-20F6-46C7-8599-C44F3AA2CD4C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirExe", "src\Simulation\Simulators.Tests\TestProjects\QirExe\QirExe.csproj", "{A0B98D0E-FC28-4FD8-8806-4825B9F5489D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QirExe", "src\Simulation\Simulators.Tests\TestProjects\QirExe\QirExe.csproj", "{A0B98D0E-FC28-4FD8-8806-4825B9F5489D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.CommandLineTool", "src\Qir\Execution\CommandLineTool\Microsoft.Quantum.Qir.CommandLineTool.csproj", "{EAABB911-02EE-4A05-B566-0084013FC5CD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -811,22 +811,6 @@ Global {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {4794FC80-4594-403F-AFEC-4889EFE87EA0}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|x64.ActiveCfg = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Debug|x64.Build.0 = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|Any CPU.Build.0 = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|x64.ActiveCfg = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.Release|x64.Build.0 = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {039D2649-20F6-46C7-8599-C44F3AA2CD4C}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -843,6 +827,22 @@ Global {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU {A0B98D0E-FC28-4FD8-8806-4825B9F5489D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|x64.ActiveCfg = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Debug|x64.Build.0 = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|Any CPU.Build.0 = Release|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|x64.ActiveCfg = Release|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.Release|x64.Build.0 = Release|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {EAABB911-02EE-4A05-B566-0084013FC5CD}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -901,8 +901,8 @@ Global {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {C60226E3-98DE-4E92-AED4-B4A93D4CA063} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} {4794FC80-4594-403F-AFEC-4889EFE87EA0} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} - {039D2649-20F6-46C7-8599-C44F3AA2CD4C} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} {A0B98D0E-FC28-4FD8-8806-4825B9F5489D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} + {EAABB911-02EE-4A05-B566-0084013FC5CD} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/build/pack.ps1 b/build/pack.ps1 index a3ff5e9c211..a467e0c0fa5 100644 --- a/build/pack.ps1 +++ b/build/pack.ps1 @@ -99,11 +99,14 @@ Pack-Dotnet '../src/Simulation/Type1Core/Microsoft.Quantum.Type1.Core.csproj' Pack-Dotnet '../src/Simulation/Type2Core/Microsoft.Quantum.Type2.Core.csproj' Pack-Dotnet '../src/Simulation/Type3Core/Microsoft.Quantum.Type3.Core.csproj' Pack-Dotnet '../src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj' -ForcePrerelease +Pack-Dotnet '../src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj' -ForcePrerelease Pack-One '../src/Simulation/Simulators/Microsoft.Quantum.Simulators.nuspec' Pack-One '../src/Quantum.Development.Kit/Microsoft.Quantum.Development.Kit.nuspec' Pack-One '../src/Xunit/Microsoft.Quantum.Xunit.csproj' Pack-One '../src/Qir/Runtime/Microsoft.Quantum.Qir.Runtime.nuspec' -ForcePrerelease +Move-Item -Path (Join-Path $Env:NUGET_OUTDIR Microsoft.Quantum.Qir.CommandLineTool.*) -Destination $Env:INTERNAL_TOOLS_OUTDIR + if (-not $all_ok) { throw "At least one project failed to pack. Check the logs." } diff --git a/build/set-env.ps1 b/build/set-env.ps1 index 39799bdf9f7..52561fdf2af 100644 --- a/build/set-env.ps1 +++ b/build/set-env.ps1 @@ -21,6 +21,8 @@ if ($Env:ENABLE_QIRRUNTIME -ne "false" -and $Env:QIR_DROPS -eq $null) { If ($Env:DROPS_DIR -eq $null) { $Env:DROPS_DIR = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot "..\drops")) } +If ($Env:INTERNAL_TOOLS_OUTDIR -eq $null) { $Env:INTERNAL_TOOLS_OUTDIR = (Join-Path $Env:DROPS_DIR "internal_tools") } +If (-not (Test-Path -Path $Env:INTERNAL_TOOLS_OUTDIR)) { [IO.Directory]::CreateDirectory($Env:INTERNAL_TOOLS_OUTDIR) } If ($Env:NUGET_OUTDIR -eq $null) { $Env:NUGET_OUTDIR = (Join-Path $Env:DROPS_DIR "nugets") } If (-not (Test-Path -Path $Env:NUGET_OUTDIR)) { [IO.Directory]::CreateDirectory($Env:NUGET_OUTDIR) } diff --git a/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj b/src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj similarity index 66% rename from src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj rename to src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj index bbbd132751f..95fd980a0ec 100644 --- a/src/Qir/Execution/QirCommandLineTool/QirCommandLineTool.csproj +++ b/src/Qir/Execution/CommandLineTool/Microsoft.Quantum.Qir.CommandLineTool.csproj @@ -3,7 +3,13 @@ Exe netcoreapp3.1 + + + true + qir-cli + Command-line tool for interacting with QIR. + Quantum QIR diff --git a/src/Qir/Execution/QirCommandLineTool/Program.cs b/src/Qir/Execution/CommandLineTool/Program.cs similarity index 99% rename from src/Qir/Execution/QirCommandLineTool/Program.cs rename to src/Qir/Execution/CommandLineTool/Program.cs index 6bdeb704674..9ffd39908bb 100644 --- a/src/Qir/Execution/QirCommandLineTool/Program.cs +++ b/src/Qir/Execution/CommandLineTool/Program.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; using Microsoft.Quantum.Qir.Tools; -namespace Microsoft.Quantum.CommandLineCompiler +namespace Microsoft.Quantum.Qir.CommandLineTool { class Program { From 21851f9dd03ac3e4feb6a61381d3435f934924ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 15 Jun 2021 23:16:49 -0700 Subject: [PATCH 119/145] Update QIR submitter factory regex. (#728) Co-authored-by: Bettina Heim --- src/Azure/Azure.Quantum.Client/SubmitterFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs index 4a46234c034..b10588ed1fd 100644 --- a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs +++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs @@ -23,7 +23,7 @@ public static class SubmitterFactory /// private static readonly ImmutableList QirSubmitters = ImmutableList.Create( new SubmitterInfo( - new Regex(@"^microsoft\.simulator$"), + new Regex(@"^microsoft\.simulator\.([\w]+\.)*[\w]+$"), "Microsoft.Quantum.Providers.Targets.MicrosoftSimulatorSubmitter, Microsoft.Quantum.Providers.Core", "QirSubmitter")); From 36753dc9fbc7ae586c092b77aa24e4da99338ed5 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 21 Jun 2021 16:39:09 -0700 Subject: [PATCH 120/145] cleaning up solution file --- Simulation.sln | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Simulation.sln b/Simulation.sln index d813d7a71d2..a7fea5b8b3b 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -85,9 +85,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Type3.Cor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.Simulators.Type3", "src\Simulation\Simulators.Type3.Tests\Tests.Microsoft.Quantum.Simulators.Type3.csproj", "{7F80466B-A6B5-4EF1-A9E9-22ABAE3C20C1}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{020356B7-C3FC-4100-AE37-97E5D8288D1D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Qir", "Qir", "{F6C2D4C0-12DC-40E3-9C86-FA5308D9B567}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "qir", "qir", "{F6C2D4C0-12DC-40E3-9C86-FA5308D9B567}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7F7BB60A-5DCB-469E-8546-1BE9E3CAC833}" EndProject @@ -127,13 +125,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirExe", "src\Simulation\Si EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.CommandLineTool", "src\Qir\Execution\CommandLineTool\Microsoft.Quantum.Qir.CommandLineTool.csproj", "{EAABB911-02EE-4A05-B566-0084013FC5CD}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Simulation", "Simulation", "{3CD26906-C7F3-47B8-AF43-FF6BCF1CB3EF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoSubstitution", "src\Simulation\AutoSubstitution\AutoSubstitution.csproj", "{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoSubstitution", "src\Simulation\AutoSubstitution\AutoSubstitution.csproj", "{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.AutoSubstitution", "src\Simulation\AutoSubstitution.Tests\Tests.AutoSubstitution.csproj", "{4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.AutoSubstitution", "src\Simulation\AutoSubstitution.Tests\Tests.AutoSubstitution.csproj", "{4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.AutoSubstitution.Integration", "src\Simulation\AutoSubstitution.Integration.Tests\Tests.AutoSubstitution.Integration.csproj", "{D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.AutoSubstitution.Integration", "src\Simulation\AutoSubstitution.Integration.Tests\Tests.AutoSubstitution.Integration.csproj", "{D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -939,7 +935,6 @@ Global {789C86D9-CE77-40DA-BDDD-979436952512} = {93409CC3-8DF9-45FA-AE21-16A19FDEF650} {7E24885B-D86D-477E-A840-06FA53C33FE1} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4} {7F80466B-A6B5-4EF1-A9E9-22ABAE3C20C1} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4} - {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} = {020356B7-C3FC-4100-AE37-97E5D8288D1D} {7F7BB60A-5DCB-469E-8546-1BE9E3CAC833} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {EAC5EAE7-D1B3-4726-AFDB-73000E62176A} = {7F7BB60A-5DCB-469E-8546-1BE9E3CAC833} {C7531119-9730-497A-9D11-8BBB3761B726} = {EAC5EAE7-D1B3-4726-AFDB-73000E62176A} @@ -959,10 +954,9 @@ Global {4794FC80-4594-403F-AFEC-4889EFE87EA0} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} {A0B98D0E-FC28-4FD8-8806-4825B9F5489D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} {EAABB911-02EE-4A05-B566-0084013FC5CD} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} - {3CD26906-C7F3-47B8-AF43-FF6BCF1CB3EF} = {020356B7-C3FC-4100-AE37-97E5D8288D1D} - {33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F} = {3CD26906-C7F3-47B8-AF43-FF6BCF1CB3EF} - {4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300} = {3CD26906-C7F3-47B8-AF43-FF6BCF1CB3EF} - {D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C} = {3CD26906-C7F3-47B8-AF43-FF6BCF1CB3EF} + {33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4} + {4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4} + {D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} From 21251729dbb1a7a3588266e9afddcdbb4af4c0ef Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 21 Jun 2021 17:46:01 -0700 Subject: [PATCH 121/145] need to declare autosubstitution as private asset for the testing to work --- .../Tests.AutoSubstitution.Integration.csproj | 3 ++- .../AutoSubstitution.Tests/Tests.AutoSubstitution.csproj | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Simulation/AutoSubstitution.Integration.Tests/Tests.AutoSubstitution.Integration.csproj b/src/Simulation/AutoSubstitution.Integration.Tests/Tests.AutoSubstitution.Integration.csproj index 7260a0b8e2c..3d9a1769786 100644 --- a/src/Simulation/AutoSubstitution.Integration.Tests/Tests.AutoSubstitution.Integration.csproj +++ b/src/Simulation/AutoSubstitution.Integration.Tests/Tests.AutoSubstitution.Integration.csproj @@ -4,6 +4,7 @@ Library netcoreapp3.1 x64 + d @@ -17,6 +18,6 @@ - + diff --git a/src/Simulation/AutoSubstitution.Tests/Tests.AutoSubstitution.csproj b/src/Simulation/AutoSubstitution.Tests/Tests.AutoSubstitution.csproj index d2ce8ad57ba..d1195957805 100644 --- a/src/Simulation/AutoSubstitution.Tests/Tests.AutoSubstitution.csproj +++ b/src/Simulation/AutoSubstitution.Tests/Tests.AutoSubstitution.csproj @@ -63,7 +63,7 @@ - + From 1361ad0084d22558d995609c2c914e52ed685e13 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 21 Jun 2021 23:29:48 -0700 Subject: [PATCH 122/145] need to use the same version of system.collection.immutable in the runtime as in the compiler... --- ...Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj | 3 --- src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Simulation/AutoSubstitution.Integration.Tests/Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj b/src/Simulation/AutoSubstitution.Integration.Tests/Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj index 2d969cf0043..e1b8b42bc19 100644 --- a/src/Simulation/AutoSubstitution.Integration.Tests/Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj +++ b/src/Simulation/AutoSubstitution.Integration.Tests/Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj @@ -17,9 +17,6 @@ - - - false false diff --git a/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj b/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj index b3eb209e697..3256cf8bf56 100644 --- a/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj +++ b/src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj @@ -19,7 +19,7 @@ - + From 46874a31f1a466b84904bbd2b8a70f402fd99f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 29 Jun 2021 09:58:59 -0700 Subject: [PATCH 123/145] Remove controller project. --- Simulation.sln | 28 +--- src/Qir/Controller/Constant.cs | 14 -- src/Qir/Controller/Controller.cs | 95 -------------- src/Qir/Controller/ControllerException.cs | 21 --- src/Qir/Controller/ErrorMessages.Designer.cs | 72 ---------- src/Qir/Controller/ErrorMessages.resx | 123 ------------------ src/Qir/Controller/Model/Error.cs | 16 --- src/Qir/Controller/Program.cs | 71 ---------- src/Qir/Controller/QirController.csproj | 47 ------- .../test-cases/internal-error-test.err | 4 - .../test-cases/internal-error-test.in | 1 - src/Qir/Controller/test-cases/no-args-test.in | Bin 27965 -> 0 bytes .../Controller/test-cases/no-args-test.out | 2 - .../test-cases/standalone-input-test.in | Bin 44447 -> 0 bytes .../test-cases/standalone-input-test.out | 14 -- src/Qir/Controller/test-qir-controller.ps1 | 103 --------------- 16 files changed, 3 insertions(+), 608 deletions(-) delete mode 100644 src/Qir/Controller/Constant.cs delete mode 100644 src/Qir/Controller/Controller.cs delete mode 100644 src/Qir/Controller/ControllerException.cs delete mode 100644 src/Qir/Controller/ErrorMessages.Designer.cs delete mode 100644 src/Qir/Controller/ErrorMessages.resx delete mode 100644 src/Qir/Controller/Model/Error.cs delete mode 100644 src/Qir/Controller/Program.cs delete mode 100644 src/Qir/Controller/QirController.csproj delete mode 100644 src/Qir/Controller/test-cases/internal-error-test.err delete mode 100644 src/Qir/Controller/test-cases/internal-error-test.in delete mode 100644 src/Qir/Controller/test-cases/no-args-test.in delete mode 100644 src/Qir/Controller/test-cases/no-args-test.out delete mode 100644 src/Qir/Controller/test-cases/standalone-input-test.in delete mode 100644 src/Qir/Controller/test-cases/standalone-input-test.out delete mode 100644 src/Qir/Controller/test-qir-controller.ps1 diff --git a/Simulation.sln b/Simulation.sln index a7fcd01f96d..66f458ae978 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -111,10 +111,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandaloneInputReference", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-standalone-input-reference", "src\Qir\Samples\StandaloneInputReference\qsharp\qir-standalone-input-reference.csproj", "{D7D34736-A719-4B45-A33F-2723F59EC29D}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Controller", "Controller", "{4E07F247-ED93-4497-8B58-022314308E67}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirController", "src\Qir\Controller\QirController.csproj", "{A77E6661-D143-4E3E-BCD1-8E321A966829}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Execution", "Execution", "{442E66C8-F69F-44E9-9CD9-1F52C37EA41B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools\Microsoft.Quantum.Qir.Tools.csproj", "{C60226E3-98DE-4E92-AED4-B4A93D4CA063}" @@ -125,11 +121,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirExe", "src\Simulation\Si EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.CommandLineTool", "src\Qir\Execution\CommandLineTool\Microsoft.Quantum.Qir.CommandLineTool.csproj", "{EAABB911-02EE-4A05-B566-0084013FC5CD}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoSubstitution", "src\Simulation\AutoSubstitution\Microsoft.Quantum.AutoSubstitution.csproj", "{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.AutoSubstitution", "src\Simulation\AutoSubstitution\Microsoft.Quantum.AutoSubstitution.csproj", "{33D66E90-049F-4A0B-A2B1-79E7E7E0ED0F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.AutoSubstitution", "src\Simulation\AutoSubstitution.Tests\Tests.Microsoft.Quantum.AutoSubstitution.csproj", "{4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.AutoSubstitution", "src\Simulation\AutoSubstitution.Tests\Tests.Microsoft.Quantum.AutoSubstitution.csproj", "{4EBC65DF-3B5E-419B-8E26-3EEF0B5CD300}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.AutoSubstitution.Integration", "src\Simulation\AutoSubstitution.Integration.Tests\Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj", "{D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.AutoSubstitution.Integration", "src\Simulation\AutoSubstitution.Integration.Tests\Tests.Microsoft.Quantum.AutoSubstitution.Integration.csproj", "{D23480EE-88FC-4DF2-86BD-1C5BDD6CD98C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -767,22 +763,6 @@ Global {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU {D7D34736-A719-4B45-A33F-2723F59EC29D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|x64.ActiveCfg = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Debug|x64.Build.0 = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|Any CPU.Build.0 = Release|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|x64.ActiveCfg = Release|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.Release|x64.Build.0 = Release|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {A77E6661-D143-4E3E-BCD1-8E321A966829}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|Any CPU.Build.0 = Debug|Any CPU {C60226E3-98DE-4E92-AED4-B4A93D4CA063}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -947,8 +927,6 @@ Global {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {A7DB7367-9FD6-4164-8263-A05077BE54AB} = {AAFB81D3-BC87-404D-BA64-AF40B2D2E45A} {D7D34736-A719-4B45-A33F-2723F59EC29D} = {A7DB7367-9FD6-4164-8263-A05077BE54AB} - {4E07F247-ED93-4497-8B58-022314308E67} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} - {A77E6661-D143-4E3E-BCD1-8E321A966829} = {4E07F247-ED93-4497-8B58-022314308E67} {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} = {F6C2D4C0-12DC-40E3-9C86-FA5308D9B567} {C60226E3-98DE-4E92-AED4-B4A93D4CA063} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} {4794FC80-4594-403F-AFEC-4889EFE87EA0} = {442E66C8-F69F-44E9-9CD9-1F52C37EA41B} diff --git a/src/Qir/Controller/Constant.cs b/src/Qir/Controller/Constant.cs deleted file mode 100644 index 23d5a8ba351..00000000000 --- a/src/Qir/Controller/Constant.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Qir -{ - public static class Constant - { - // TODO: errors will be added as dependencies are implemented. - public static class ErrorCode - { - public const string InternalError = "InternalError"; - } - } -} diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs deleted file mode 100644 index 93b8b38a8bd..00000000000 --- a/src/Qir/Controller/Controller.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Model; -using Microsoft.Quantum.Qir.Serialization; -using Microsoft.Quantum.Qir.Tools.Executable; -using Microsoft.Quantum.Qir.Utility; - -namespace Microsoft.Quantum.Qir -{ - public static class Controller - { - private const string BinaryDirectoryPath = "bin"; - private const string ExecutableName = "simulation.exe"; - - public static async Task ExecuteAsync( - FileInfo inputFile, - FileInfo outputFile, - DirectoryInfo libraryDirectory, - DirectoryInfo includeDirectory, - FileInfo errorFile, - ILogger logger) - { - try - { - // Step 1: Parse input. - logger.LogInfo("Parsing input."); - using var inputFileStream = inputFile.OpenRead(); - var input = Protocols.DeserializeQirExecutionWrapperFromFastBinary(inputFileStream); - - // Step 2: Create executable. - logger.LogInfo("Creating executable."); - - // For now, only the first execution is used. - var executionInfo = input.Executions[0]; - var bytecodeArray = input.QirBytecode.Array.Skip(input.QirBytecode.Offset).Take(input.QirBytecode.Count).ToList().ToArray(); - var executableFile = new FileInfo(Path.Combine(BinaryDirectoryPath, ExecutableName)); - var executable = new QirFullStateExecutable(executableFile, bytecodeArray, logger); - await executable.BuildAsync(executionInfo.EntryPoint, new[] { libraryDirectory }, new[] { includeDirectory }); - - // Step 3: Run executable. - if (outputFile.Exists) - { - outputFile.Delete(); - } - using var outputStream = outputFile.OpenWrite(); - await executable.RunAsync(executionInfo, outputStream); - } - catch (Exception e) - { - logger.LogError("An error has been encountered. Will write an error to the error file."); - logger.LogException(e); - await WriteExceptionToFileAsync(e, errorFile); - } - } - - private static async Task WriteExceptionToFileAsync(Exception e, FileInfo errorFile) - { - // Create the error object. - Error error; - if (e is ControllerException controllerException) - { - error = new Error - { - Code = controllerException.Code, - Message = controllerException.Message, - }; - } - else - { - error = new Error - { - Code = Constant.ErrorCode.InternalError, - Message = ErrorMessages.InternalError, - }; - } - - // Serialize the error to JSON. - var errorJson = JsonSerializer.Serialize(error, new JsonSerializerOptions - { - WriteIndented = true, - }); - - // Write the error to the error file. - using var errorFileStream = errorFile.OpenWrite(); - using var streamWriter = new StreamWriter(errorFileStream); - await streamWriter.WriteAsync(errorJson); - } - } -} diff --git a/src/Qir/Controller/ControllerException.cs b/src/Qir/Controller/ControllerException.cs deleted file mode 100644 index 05cbd872cf9..00000000000 --- a/src/Qir/Controller/ControllerException.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.Quantum.Qir -{ - /// - /// Exception that represents an error that can be written to an error file. - /// - public class ControllerException : Exception - { - public ControllerException(string message, string code) - : base(message) - { - Code = code; - } - - public string Code { get; } - } -} diff --git a/src/Qir/Controller/ErrorMessages.Designer.cs b/src/Qir/Controller/ErrorMessages.Designer.cs deleted file mode 100644 index dbd8ce8ba5e..00000000000 --- a/src/Qir/Controller/ErrorMessages.Designer.cs +++ /dev/null @@ -1,72 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.Quantum.Qir { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class ErrorMessages { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ErrorMessages() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Quantum.Qir.ErrorMessages", typeof(ErrorMessages).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to An internal error occurred.. - /// - public static string InternalError { - get { - return ResourceManager.GetString("InternalError", resourceCulture); - } - } - } -} diff --git a/src/Qir/Controller/ErrorMessages.resx b/src/Qir/Controller/ErrorMessages.resx deleted file mode 100644 index 6cfb82bccc5..00000000000 --- a/src/Qir/Controller/ErrorMessages.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - An internal error occurred. - - \ No newline at end of file diff --git a/src/Qir/Controller/Model/Error.cs b/src/Qir/Controller/Model/Error.cs deleted file mode 100644 index ee96bff5348..00000000000 --- a/src/Qir/Controller/Model/Error.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Text.Json.Serialization; - -namespace Microsoft.Quantum.Qir.Model -{ - public class Error - { - [JsonPropertyName("code")] - public string Code { get; set; } - - [JsonPropertyName("message")] - public string Message { get; set; } - } -} diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs deleted file mode 100644 index df24e0632f9..00000000000 --- a/src/Qir/Controller/Program.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.CommandLine; -using System.CommandLine.Invocation; -using System.IO; -using Microsoft.Quantum.Qir.Utility; - -namespace Microsoft.Quantum.Qir -{ - class Program - { - static void Main(string[] args) - { - var logger = new Logger(new Clock()); - logger.LogInfo("QIR controller beginning."); - - var rootCommand = new RootCommand( - description: "Builds and runs QIR executable."); - - // Create and add options to the root command. - var inputOption = new Option( - aliases: new string[] { "--input"}) - { - Description = "Path to the file that contains the input.", - IsRequired = true - }; - - rootCommand.AddOption(inputOption); - var outputOption = new Option( - aliases: new string[] { "--output"}) - { - Description = "Path to the file to which the output will be written.", - IsRequired = true - }; - - rootCommand.AddOption(outputOption); - - var libraryDirectoryOption = new Option( - aliases: new string[] { "--libraryDirectory" }) - { - Description = "Path to the directory containing the libraries that must be linked to the driver executable.", - IsRequired = true - }; - - rootCommand.AddOption(libraryDirectoryOption); - var includeDirectoryOption = new Option( - aliases: new string[] { "--includeDirectory" }) - { - Description = "Path to the directory containing headers that must be included by the C++ driver.", - IsRequired = true - }; - - rootCommand.AddOption(includeDirectoryOption); - var errorOption = new Option( - aliases: new string[] { "--error",}) - { - Description = "Path to the file to which errors will be logged.", - IsRequired = true - }; - - rootCommand.AddOption(errorOption); - - // Bind to a handler and invoke. - rootCommand.Handler = CommandHandler.Create( - async (input, output, libraryDirectory, includeDirectory, error) => - await Controller.ExecuteAsync(input, output, libraryDirectory, includeDirectory, error, logger)); - rootCommand.Invoke(args); - } - } -} diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj deleted file mode 100644 index 8d0768ebcef..00000000000 --- a/src/Qir/Controller/QirController.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - Exe - netcoreapp3.1 - Microsoft.Quantum.Qir - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - ErrorMessages.resx - - - - - - PublicResXFileCodeGenerator - ErrorMessages.Designer.cs - - - - diff --git a/src/Qir/Controller/test-cases/internal-error-test.err b/src/Qir/Controller/test-cases/internal-error-test.err deleted file mode 100644 index cc5c5a256f3..00000000000 --- a/src/Qir/Controller/test-cases/internal-error-test.err +++ /dev/null @@ -1,4 +0,0 @@ -{ - "code": "InternalError", - "message": "An internal error occurred." -} \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/internal-error-test.in b/src/Qir/Controller/test-cases/internal-error-test.in deleted file mode 100644 index 37fc5162678..00000000000 --- a/src/Qir/Controller/test-cases/internal-error-test.in +++ /dev/null @@ -1 +0,0 @@ -any input will do for now, but as errors become more specific, the corresponding test will need to change. \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/no-args-test.in b/src/Qir/Controller/test-cases/no-args-test.in deleted file mode 100644 index a0a93acfb67da63c7f320d45518c24fb37dd588b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27965 zcmeHQ4_Fgdwx1y(2@sNjq74wj@JE|kw+#pwL^L5_!J;o%yKB34NrWKjBE*0etZgR= z8nmn%Ep6$R?u#yUZJ+zSbn9-lwfiN6Rcg@%|8%Xo-6*J3t;LphTea)EH#3uo1QlB8 z+qRkSGxOu*%)RHHd(OS*-Z?i$gd*W+cqkGUiX@h-&{o&2SXNrPP*+TQ9=}>fR@BZkQXNc_K+kb1pEyk z!ZoFARCck8I9Pi2CbW@1DU=s0VL!8k5Eq2xZHmb2$I@fuJkbN;>Bgo)LuXP-ezdh2 zQ*H_=@8Z24gRAB=;qRj9#zxT;=@eVqYRBS@_}(s1?m8Snl;ED8+!cnGuVFu%(%uL@ z`WiReVxo&TG)FY{7h_!=Vv~Z%4pHx15*lYwSQNP3B}O-eg{C(ni+dOREw4EWX_2z? zHmiG*!$gN$QxHo!9wRijD;iU?)%e^ntUTNDa&mjx9v;%6-pq@QT(+L*QvaUc)NPsd zv&s^-ri_iO5u7A+sCkVj1*u#Z-dLEQT=FWP*K3)tQ`jUeze(ZkQzZYP=^-|I-Qu;_ zy24cRb7<1~joW$QXm7aESR7M+58K?X#x6ELXWOQWOF;^M#_QaWpZwd{m8sER?IWR_{bv|0#71H5hw%p*&Sw09uDqv zg}kUud25?n5HurCG!Z9I(P6a5iSW-OT^fY55^0eksvIIAdMjTw6ZAX06gbBzDB>e! zHY+p-aPc}3dtpKR06JKaC&1Bd3wzhDLax46X~{(n&g)7_MTD#=#|%QE4V|#e$#otj z)@Svz?8_Ae@k6K~$G#=<3c^cN_i~;>rp7obRkM-m@I^aZiAY)K)MJA}jWv~nWHxn@ zbs_8}2>;djukfdmEg`9C$l8S$I+iIY9(aRn>OJQOKT;p)* z2~qHgq=({OcEuu81L2oVsI1-mN=6|I_hW_ie$~#=BW#9V`&OAYsK-yt6ueXR$$e;@8?txuR5H~njXkmEh1F0{`J7- z7~l2W+3!#EHv9=re8TYB^Ljn}69|vtg`7uT;#4^p5~-qNM>LUeMDSfuMU&&}R}PnR zeU(K3O_9D}!zaAu;`(a{3K{ZGBCx=z;_WW~hjF0ua~mv~@_^nsC9ba@UUhi8C6gfN zioqTB&L377I2gtdy}k2+pkp&-_T)E^bAJOO&@qe%g2Ns^!!p=d{#4lT&k`Mha&p&X zF7juDWxl$_!HMuA!rEV36>~!4uMV$mJf9b+qIoARe$RTF^YvC|V1W}RydO}Y?)M#W zz?YZ{dPK)V1`8bj>C4;Q?}hi_T$%#!khA}1ngGt{gb}|CFpRl6ZD2nRP2CxwpSjyZ zvjX(9>(3+T=jz13<`kSU#|Jd0{84Aqx)CJ1< z)g@b?oaeS$7kejjpH$E?2Xg~0bNyaxpk=;%d4$><5(6zW^b1v><{x=F&^#Xcw=i(r zn4&rrsG=Q(gMrF4Kd>c`^PQr==1eIF3smNjyDtU!#T4VDV*!3K;SF|Rb1pwWLUS%h z*92I5hxXJP2*MawC(?T8M4E{+Q4Jj$cz1L>JN%`G5v1G%y9EdT(j~2UY*ewWIc)O% zd)TUwW~40i3$skn8v?(?|uu-+8;6Q;O?4|fN zaccdl)lb=Y(Q(OnTe=2#Ve9V7mS(4J>2L41Io|5nmzVd;XZ|N*-F*&OTI!yzecgrT zj_`=^89DhS=yPx^eI3LG&w~3j9wF{LDXxe?bDLE1Mt5@_!ELDL*0wI^pFxBlV}c<< zFpZxl>2M_+*etG)g?ia6@!hQ4E>&(bE4RD8xz50Sg2!zrv>FWDRR-3|daD7q#&$;u zF4zPoWx{Hiuy0T>s1{7aIukxj0%1!+hgMP{TbHxjlGCHg-ocu=+cL9}mD4>Kvr@x- zqLMqk(rN^sgwyN#agZ!agnMeVZz~OO@T~{oLu6x2WVzteh72eW22-=A6T<9EY2~ zS8p{evKkGRx=L=n##$$`*4eGG2Obn&M1-HJ1^qTbpF(&N7hC|Xz@-T%T#^nDg(ZO~ zOme~_?mwAu4wY1hO5_gJj5bS7w>p(-h{pPOJ-5EKq2CgOIB2Q$aUc(myGqJ6wwf0AVS)=z z!D+SNGg*r3pi@GKGYlpR5L)UdsMTKSAk8zup=VeC%f_ zcc`*^+~zalJ)0v3l+cvUBqfkKn3&P05u8;6)e8Hef`w<*f*}WC;xP(47QaGWAS>t#|C0n9Ka31F$IqVb;2apDLsbrOM4EhOIjqQ)o z0st;8jvzVUPL~P4ACj8lzzviIA2e_-YIr`Vrl5`UvBC#0Fz{m;LxqqBN>FpoYhpTO zOEgfRr5?c?1{P3I-y_JUp_73<0?-ccV|u4RWk0F#t{+JGvqU}ljrl)$b|@sGpm2`J zCjS+;#A%*2S%jyt@scPPwtq)-^q-11P2kAp*UlingsmdmycpcatIhveT4R*`pP=`r z{qzoPerTI1+J1xw5Mytj7$_Sua6X|;&&IjvXL=00=x2H~1dokSf|K)+n(_r3=Oc_y zdWwfLfHjLm2+ypH+pUt(a3>AX_-(2rnz~J;Xcol)UQ>L#&oB`onnu~^pa4JuTDi_6 z2ur4FGjJ~1VrU1tL{QKMMkycsgn@$?LuKGOhGBq#=NN_o8s4xr15+*o2Q>^;6B8$3 zd-p=Tv@rr^0aHEFKLKQjL0uwt1=GFEj*lFv{f`H-~UmDBp;2qeD&#NYtZIH zZS(t-F%CN&k!o=S3Hly6qcPW9lhdiu-6lj2X<6;5 zF}AKI6H4HscGE2O0SYQ-vFBSOqkpGXB$NJN<6OlQG`vDX1Ltc4MFmg|Ae_?_+)FYY zapEa)2=ClpWz*Iu77J0zG?pjjza?RztT(vt|}ro!jQ{`3T#ElVSPJBnO^aY_E z|IOVU>t)2o7tXH8dZ*xj-5;Ee=2z~~%HO&7zBdO}$lshbeBO)*K^_kbeC>rlN~sM zl&3jL@Ia%|q_7<`?A9rkvn$VH>V=OB@(Lp3u{;&x=HweN#caVdx)Rz+og6%BA?>7i zl!l%-FN28_T0AQ0R2k|>2E^qyl2(GUg?lq8%LjHwLyyq)3JBxAmA-(=eERant0Gj2 z0$LI5Ta8GHZ=_wkj@L}XT3+*0; zIQ<|PM`>WJ{hhBJgKHSyqTxroh6%>fl8U_VAeMH|^8{mQ?|M8KOOGa&&h?AQs5L>> z@HN5kSo&QUH+p1XO;88d1a>L2CNSk>c-I8ZO(`}rfk zwitBeUZazf^tx|fGAXKx-j~Fq==t%2N>-)dqbNTfYyrof`(I zGGB(`c?h{6R&#QnRAX*>uOtU^QP4HR2hkipL*<)bAQcJfr}7*`*mX&VSt5^oKg@{Q zpWko)brdIK{u?kCu~Kzi9#sBqk)Mnz$FZ$+v(fKLFO`0J897G~WS=rAfEO4zQckLq zGr;8i4KR6sXMK5pzGOdT+zux1ubs*JYiIKQ?7qA|Z?Yfx0@4HX{=6G;tC8>~U%9(2 zYC3apCj)n@7%BtX8HP3nwlfTE4BYK5@s-QK-4=#wDFLaz$b=i(=UNe#?X%CnUHkj> z_Bx59@YyT)a*n8nH0I5bCf^wpEsh{T`yJV@Tm9_!y0yJGpNGn`tIP~h?1>_@>lesE zpRb<}$1i#{Iph@oWBSwrrE5doKYPSsp{Z1Io!%gH(NH6F9emRLEY9TFf#kaV^auu_ zH%G0sEFtV(kR{~J zcFL)@K4)9EgyQxjn)MWPLg;;PfRJqG+m8QQC7buPoYz9_K392!?`4pafZiiSv&ek( zYC`C8plNJ2Sef$@d^vN6S;fqIK6SK`&Sq0UNP3ngq8BXeVWzGtw$t(gy(0HPWn4?A ziKHsyYz%D4Cwx=}UUmC;hZuNO<>MWqp)0nv(Mp%l(rKZgje#xs3^m{4O@d?cXulXX zH%u16tZSt|FDLq#zrTn@NdJT`cdhhzxq|$%F^hc}7z((w zcrgF%$D054Ls=&U-&c-pA1XNCjy&H6<3&0g{LhXTe`s-0Oa1uAMV1E+`|_WHanX+} zE(-1=2KNzz`-tPekN880r-S1~aJ&eP7vn!(ybShV=yPA+r~N&T#7rHJWi>FzV|V(F z$9fXxpPED;kF`9_qmI}XvLGan$Ff#AyvJi*8Q^%V`h9Z0(P5fB^$@l72(n9$QpaPJ zv%wKpcofmY`4R&uI4T7=UD((YMd#rta~=8fe0eyNqRQzEnN$eL*D`;`5~$Y?ZOWPT z)Nx!t*sd%RAEkFa8K^7*Qjo`wQ3kqZ`*@WMbU}$pULY|A+e}6EK5EfS8lntT7G*Hh zj8^zQD7fc0`ZKS=xhgnU1?Q^qpR0ngZSY*rkL~vXf;o8KJO>ZPFm!ASe=vjoeKGZf z&#B)RV}poJ<8qThUezZc+W{U%QvORo1!}7=VtnvJLf~2WPMge+0RUXfaRiwG?&$(7 zxpBguIjyf(5t1hEm)fU@)U&)r3)%?jSK+OHe2ci}UlCoK-X(tWHh zh|E@DrJHY>{%@@5P`oL7UGz4~PfR(Nqr2SMrrZN}3>+#n&Hf;U*Z7D@d2*sOqrs#) zcxPe%I#a>NqROEcP4|Bo+tmJ=spzY?oh@&fia&`z+Opp?|GyKyY&maIpO=VMTrn;9 zC{g}Ugn8i=e9=P^^G~lO*H6eXFB(i~{p$nfN1mCq^T^N5i?2>Px~9tfix=+tQumBm zGawbM{Ed0ZXLrjdZ#S0@O<9!nwz=ZkJ@se0VcX&LC^%&GGEhb|tL1bt_*<=AQKc{P zelGHUKJ5K`q+pq$u3>?;dZ|vWHP-31RZ4@QN?)d})7Mm&mZr_qEvqp$%+pqDm+F@3 zs_Ou0B);^Kh|>Ze9+59&q=z#{B4&+5oIVm!J`yo|Bx0IuMCypmOiRDTPl1<~E~zPR zC@o!1|6;fiXsou*sIOjHT4vN~>vY4uTc)e61*#oJrJh(}D2GoNbrm|JuDVQDT2`~7 zx^AAn%ve)fQvpi$N%Nq7*@`Nv&nTkWSW^ZHuQ8UE7Sz}2s%t@qf}bsi-P@q5sV>*U z9@bV>H564t`D*oLBMPrI8nq3jlqA|Jy|$K=Vwl8bT0`9mqi!^eRaM$0Rkz?=t_PxO zp{Qm4qUx^~b=)+eBvmn<YZjDWR#!Ewv2`m9z~DyozcSzfUUT&73K(0Rv8Jj@S6-~IsMD2~mX0_!(2nxB z5tyjXcne;yJQV9N!F;uovIUNpX{DtLbQLPE+Xs%sz?-2%dcVGz5b0wO81UXi;Oj<% zQCgwCdSwl;!|TUHvP(ubzMHZ7jX>k(ovQJ6e^>!<%W-W0=){|u#I!M(1mN|KR--U? z!0K;3w~zp^`WGB%{=gV-Z2sWO(V2h77}^SW{YAQ20|4u2+e)(f7d+m559+#^?3rUw z3E=gY{1(NIRwba+VcmbTg0sdTFW?=mynuDI@{+9n1>c4)EUGA|s@2^%0As=+eT5Ei z-v0P!m;|?PIDOs=y>5t2Y=f1z(x@Tm0x${nVUn-)EmAUq8)k6LEHJ8GFpUjL$fTL>fn-)6V? Xy0jEbUOHoqAua7**}ZVj-+TQZ4{$0q diff --git a/src/Qir/Controller/test-cases/no-args-test.out b/src/Qir/Controller/test-cases/no-args-test.out deleted file mode 100644 index be77bba6b31..00000000000 --- a/src/Qir/Controller/test-cases/no-args-test.out +++ /dev/null @@ -1,2 +0,0 @@ -Success! -() diff --git a/src/Qir/Controller/test-cases/standalone-input-test.in b/src/Qir/Controller/test-cases/standalone-input-test.in deleted file mode 100644 index d8402d40302c2d3b4fb6a9d439d261cce3fa853e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44447 zcmeHw4P4XJ`uO*|jctwr8=&$!Ho!ze-Nt~;m)dwyOsrwnPrD`?+fa;`fuLY%dlN{p zrdNx~es>fVdh7mXVOrUB15_&P;#+B1LB2$0Muzu#%kqED_ibY%Q%nE9-;I5AdpPI$ zKIeI!^PJ~A=bY#J{RRdg9F!A)j0!-c`PJI8s_N2$f_tm9WqNH%d70tfYNN5dvdW;J zRc5TNT2@eyQ)8&q6)!X3e+P094i{X?E-tIOUt3ab;DsP40zO2Uscp=O5z0S%c~1Z4EUuK8jYYp)RIJCu{RMCZB$`-c?n5^PF#x>l2}>>hz*Q@jmE9{I)9g7l#)d7XOa$@rqENd z&&fL>KUCo}Ps7jg;R#z&mN{XA zs*5p;$&)HJqBich0CuE+v98c0%%Np&49sNkrQvdR#B7e#(vWNH6eVPb);IE08)^D3 z_V#dL){F+>yQtJ+i%3pNwo4vyF5DpO>H>5h6C%hm@GFgHbA7;F>C;as(VP|~I;SNIy)Q8feNdl;8oK!=Rb+TXdP73Ml&+JUiEELPMnq^AnG}}Z z#?AItLsSCNaEiNpt$kla0@BqY4xxI@$eYBQgdVZ~VZsxr?Ja+Ro zsnf>pxla^c6%mp2S2mZ{b{}VrofjK>Hre|42kcd&RjT@SE}(lA*}xxud>%+F=WwV5@3$gk`S3P2-qZ zD9&WlXGMwh86YDsTaDxdeP_;X2E+Z!Dpx-PbE0i9CN}Pb4(Ox z3VM71)_15m=anHB>>GwT{RA*d`fVvNv) zMx3SfxDf7gv`d53y^U-VBlJb4*wB}_^a5ghDuql}@GLH(>tBaC2;i|hkz=CAP!o5x z1ki*Za|9CZUYWJT6uU73=^7Y|djW*kfI726>B1I+VI;scXH5 zxv05^D}XjraqDBO1rcV zCx$Qz5lFs)dEAHmVYLr=Vf1P*@~z3Hi_AmF)IOS@% zf1D>6%Dp41%8PuG+;p)HC%;XbasA|vx_r3TM3s1vhpNx+DDfx+{<5q0G2sCwygPe&QqRL9rh*Wj@U0S$*wbNs}KlJAIgW$?e08Qr7LuOq~}q z$kLE`yWKM6bJlH_g#wd>F}hqHoeNAjNQ!MD)ZiG4PE?>>x-c6D5h4rw&Kwg4 zn+PQM0||Z?o550gl@%h~t;WgRv%UoH`}uTxtQQ{AfQnl-?iG&yr*|Q2`sm%vFMGTT zA!g`7*VlBRSE&T4o2Q9-eyjuPWf&an&$;IFZj}2dwMvUr{jj9S((-6&u7|%niqX(E}gXI+i;VY zM6iS2eaRlU!mA7sg05UTXU)80ep(t#-jd~Ah+(c+lb#zO^dbPYl$5edm5eWA@EX`h zuj$-l?Zxyl9fIQ1J(}pZL+- zqj&{nG01BXOr>|_)ED%_0Fe4XMSV4;Q#IL_=Aq+g%t~KHZT>lUPfs9qF#w>VDrZD(AnV^0o{i(9gE9ff;`Kc~$S9| z|K95_&I4^mKXH!!_n2MAU~hS#CX3!sTbE&>B2fc-{OHb{Nn5KiQWaU6O$=2m~pOqQqlx4z@Ab^ew)_roQAn&13sl)rg|7Fhkw zV^Ya(KNW3zB50AnG8Lt5ewgpI4I|FGJBLwbT*ha9}7srv7y@DzmL`X8 z`|B&OhBwpLFVX^AXvsNYQ7y7#OM71Aly-glR?~xT)E&S0T5wCyzaJd?`unOkr)~Mj z+_vGVFRRlD4%07O*!{svtkV~ai&%$>?tbd!PZvMb^x)*Ll~v8_F8x&Wr;c+g7qAZH zTweXUwX#45RM=LoXgX$u#>j8{xZ2zmP-2K?GnX4-?X9J2-X%ytm^{~7$I zvQ06aeKAGh==6pxxviry)5NN+VJ&N_;GRK3zTpKAnu1fgnSyqA><7&;MdAPq%^KZJ zpWc-yQZLIS@Rc4o>BD z#(pLOOW@dct)NK!*wo$DsXbYWHu|*P)@e5S)b4@sz*OIR68>MOywsorR>H)>eR zlUU0y1pu-uO!Woq`ihA9%BK3-CUeU9f#CDK!53Y@=fw2FuI89i%`x5B_X%yxd!m?5 zbL@Ls=7;tyMOT)h3H#pFA>WiGZ=g@z)G-+}df77d2z{!vgS)@D-Z;O$(rB$(!m82K zS4GrUIqD-nxHsfH5^_Nue99htQW?@G3_b^>5GKW*a0}YOie3a(^nw$;F{k=s&!U2& zhMX>`~=Daml zd3VQDXV!F}kjw4UPGwDP0DpEg?&SbU>sJ7N*sPUFtjZ?y!jrtfrCi3GPEG z!KuEn$NFNyCPPtfsRpVIIRzCQ@})X>&}lNWYLl>@uc-%IL%HW0w{*zc z(5Wrf=~#qz5cnoI@3Xq6wOFTa0Ub)8?yyb+oonxaenTrnkQxyCgfUbp(2Zq)|84p7 z1Z13&n}7^TXv&nV*nRmW1KZvE)vS#X(T|i2NRF5jyO?p&k8rEA=f39N&y3584SNws znQ54aqvS6*K%i`Voj|#WqwHU!!ci);hX|BIZ3IeADb~=;m+r$+HWYtEpoG3bpll{l ziphpP!BOVjzY|Bx@iXJTdFFe4;eAtByw^9NA|F2vBo8)(%k%$&tI%M6!XFQo_1Rxj+_7pB2XF z_9#-=UQ*and$g9&+@rkc@2dY_Gl@t|E_XTtd>(6bC$RwMOX`9IhB=KSKEuWyLW}WkB;af>#J7Jyf zhuJR>T3FUA*h>r&^TU+gs2<_INOlGBGlektn1Pu@4^+G2D7zVm>i`J&Aii8L4kSB6^aa%!KYQdANso~7sv6ik zNO^_v)Oc>VOn{r(AMPh`j{scKlF`SwyGZ7g@w7<L%X5t+1^Y79SrT61C)d*g_KHf&m5#!T}usZ zbRD~wWYrZPASbP9R~IlW+?rl#phnNGE@3cfO_SmqI!JH6jvCq%j|bD%nWG=iN4gB@STYe2UJ`L_Nw^CtKxa8qC%PQ3R%Hp$u@Gx zD?mjnSz+f~uAnNmI^$j@E5H?Bu)MB#*sJ1ss$#1vu9mE@bAH@FRe&~(WCb8~i0MVD zgscFKZ>K6i;}4M);EH&v0+5RHD5{~JPy)F4U^AiDmiEV?kecl0Tdco1u(3rxZTgS5b$W3|dq`3Dyuw9*ucu2=1L zW%6gh+Lj!?DRL#OeI7uuN|o$h+tUxb;^*)WMND?8Z7;HtLX;D`0#m}Zr_uL&)$UAq zX_3Im4IZ6h8`;a^eIKkt*P2e|-k&DH7 za7z%xdE>-1WkMSG0#RPrXy&uEC1)f@__GR~Pwy`hfTA?42#~-Bhl5$NAtsftb8eoQ z#Es^e`Jfzk|0SyK>@Dv51ufzdC4+{N#_C+-AO_yVHpVh{Y-fr}tQK|Adm=l6%y#DM z+;%X-!O`fR=wc-5dv=DixpQZjtmdomYK%xC#E8F5#{IH zi?~E|*y&!xCcq=AMLfz87BD_`f>VD6IYM1y+ld&m!Zp_I0r#fQR(FR+eAz_n4rL@h zXXjgKK!hdq9_I`$7h$*^!9QfOaZnhnOc$Z%a4|xLvzg8hxF&sKq zuR6)*izU^A2A5XffVFr591wb{_X&o^Qu&@ah=YFK{oDT-QM_ z&?ccFip!<{il(U?O29C-ib-zEw$JEY?h=U`weH9wO>`56Q0XAHO2 z&j@#gH}Hn{Ge5f~-V8tUsBpy3{QiDs!m(fSGxlESXCfLH50`uiZJ%^5zrUYhPYQ@9 z<|xe1uy=+8<9kk+?g@60wWN z$NT};ND*a|VeEnkiS2@v)?4mlj#56RjPx-VZ>^6p?h4=Z3u~miMK{IAysRGaF~8Nv z`0vF$_KRyI-WPC`$wO2eRg{)Vu@XTJSggXoVmz0sQ_aT{G279vXn#@@Z+{hnQC# z%wjE@+}WQrrxb#0c%B+~MHAjh>;x~hj{)c0*f9_Qa|m#&Iy9RE zl^#$Xn&m0Yg69VCz8JhiW(az+ZP^q53=a@;?-$tR>sk3O%N^+gp@bpK=ev0a+Csr@ z|Hh|T;=7kk!7HIucpokVzhoc&-ZJAE6#rYa=275(9~Y#0gyfj_B<4RAY0%;(}KGrZuR$V1NLE!kpnm%51r z-IFh6iOABp}=|uLE=9B;2Cvv{>nVkJ! z#7X5Ib=d4QLI~3saDIv9we^7`L?lF zcZSCjho!CPY#T~spe=QUY6*06lzm?tekA~B5TGjAw0Ap2uag2zIZmoHn*v)rxDF54 z;=y&0AZ#L{gw%P9q?7{r1Zd}Iz9SIqoI5?B=AftaU~-$@+$5wVv&!)FvEYCtTnX1u_&)NYxn zj0QQHYPwAh_6(XslH7u4R{|8|O?g>)4DAJn(59!q`BMdZqm9Ot;=TEHPiP+V&!3E| zcND*MN+>_zL`6c_vy1?AaG$DHz^UrOlbue{<}hXu*03cn;)yys`kT%JX9K=`$K@8* zN-!?Z!*Pkp;XNq7*}fG!8-6pd?5P;b$^MO2Q%s_b7aEZ}rD%=;fN0zG2bA5 z^TA3mWM&6vGJ>LcnJT1%nQh{^@D!eNv^n!4=as!2LtA@xlU1GH!L;@8T;S+FhS3vU zzxOq2qz(ki`18n-x|pvar%wq;P{8sGCk5RmV7$fM#jP)cPxy=Q~!VBsgbn|wRrf$u4P7IYF1Tq)Ye-NQ};#v z57o*@Oik{4jl|T$=h)rp6_?>>iI4UBt__BZso%xo#}2SQXu;M8;cGnWgWk|N*!sX# z0oDi8J{Y<_Fbm=O0LzKKY?;mY2M)Gm&SxCLBW;^?HrRfG%TRk@IzQ$k9Kk57$R?v| zEuR84{A{?A`fYiJBkPLm&&|Bs*KWWb$^V(Pm<+7N;3kGj-U)WovAgBobcMMOQfsmI z$yMv!r2VzDFJKU+*kW10cx7wfX^zx_w z@q6~W!K{UEth+)z8|zWvZYlgu=AOO9Ei=f&HbSIxD&U9 zHlJ~VpwWI008tve@6~d5-a#2f`>2 z8FRo>df+8+);_Y2e|`7$jLeZEbL5TO4>q#q_-*HB|0!o5BmQH=e~kDKHuF};*ps|s zY;4bBNdBXpQVA11;BdLE1A&)4`Gb=^`Gc3K{6Q*dP?fyNlRr4<$scri@&^a0 z{6Q>f5I?}w!2CgM+wMz8AocK-p(NZs3>OiH* z18%W-N^SW|^XNMawY5J5)l zcldGL1T^HE7lh~QVR=E=vm7f^Y!F~(;$fZ=m8#;dZ)UphS(!$^?)sz z_rx3{7uFsy^B#t$lmaaaDBMgB2)5Em+)N5=RV}HZO7EFQf;119d5_FfDr*9hgC`%C z88>upNEg5)x~EqwPswfvkFt@4ZLr>PrQq2|OeZ~mGm{W}e8M4jr678h60fwSGkySu z0zO*dNFLoEIgjo?W$iSwH-G(m^CR=_@bm6S+(?F-|GVSH|G44MOItI7X$Cx#)jheZQ%c_Mx+%v*-t*f<*T^neE(%m!Rwk4;Y= z@PJKwDcnsSunBUE<6_L?$wRifda`t|(@KH^9&j+*Q<`lpmh(pT2Cw~@yCZYg$lNtD zcisBAYb5rC_oI*8PxME9PQgfS-*3z9i$!7Vy8wH40({MHqMA2POd}pv6Oa#YkwacB zwO`gODeV|!F-Os?j4{N6XTEoG>g*P!K*GV_gpiD8cMxwvP%_3VD|3*@!3ppk2-ur3 z%FvY11nb{p(}fl-QZ%YAYd%^u%JN~l$$Wd>tEFt~e>rn`5s6Ma{_2UQ`Ujo1aK?p( z1q}-RPZnnI@%o?Q$GM+ zcM<+?W8h*T|dGNluVmx6G@ zwitsU|IVa<0Fjj+fxU6T`X^q{=`Lk?eNcmjZCYSC9l8R1Ctg922R<2KeWzi)T8aeJ zcF{u_%uy+NT(2nKFL7iV!;+pQw4RtON5@00Yw|gqc4L-0 z7`#wU2_MCEQ8Oli$pFbs>X0JIr$Ppio^`^qN_H2sp6rsm{S5)#q1pJVqlY>53-Iz9 z9=OQFyyN+hlctc@jhyGzETdyVKKVQ~wcwG=3gP*auCl0d4>EW|P3Cr45zl;5a_Q~G2GAC-DbP&&?PSb?s3COpgv@L%v?NB$jx& z$)3_L(OJFn_u*S}PND2Wc@Ko6$G~eY*W_I(k8`UQb`4&+IGw<~b2XP$Av%2J^PMD_ zf8}GCfBD=-yny3NRt0=9%AIBB(RH$%TpfG^&x&TE(H{a5StvJq@X8L)t9mL%;crm6 z0v-^Cy|ZTt;Ci3H2_NTo7%)}AC*H8KItT~uTpfS|dsdAmfYlKgTVH$LA>?^;P@TZe zc>Hxp6wj)=AAcQCCzRLoI-uuVd^!D};FT{i=2Xp<^1rlWe`Y|30zO(Hf{gd_J=k;3 z3EzV~kO%mlPAPa5&}!%2{bS;Q4{G|^1%`0|XQ&Tyaq6KDQV~8VWrz>T_Vqy`A0PAp z?t^UZ+vmSp%A?O8>VsH|cEQoWegOADnjt<&J$sZij95Y7cV@ImY~zCNgr@Iku>AN21bK4@?_ zAGBkr4+_P75ISZ?=4i|Z+1HRhXh~nYRsi7F?dFB;0^WI% z-PZ>_5|8;H_OrMTG7a%TB5xn0@%SJk<%1S``=E9oAJpjWgQi`ee9)b*g`Bhx@j+Np zR%uTHc=r|tmiHu(j}vp(+UZltTavc0COQd^*Xpiqq3eQhfe6;+p{eb!2J)?8)D>dKu*4TzMtIP||N3`ZVXMXTPWdFs#mSQir~mR1@KN+R}g?PHu`& z@3O2#_ualLLj10!5j~l5EJA(U@;Lh8#7hz4vlcu0{iLKw@eh_iqhC$VjT8r2H=|EW zmPCqgw?2iQmNrBRr&^yzPo=g-@@89~MgJx1isUV_K8OC8-XGbs()t(ld149Pf_d8Ns`8TZ#kJ~6gT7d&t-3b4MQLe8MTJFTU8=57 zCY4JHGoaD41I>Ys4zWMtVorl6&h}ou1+d0RLB8|45?UFq|Z=Db*Xx- zTwas`^efgD4MSJ0t*k26mZ*%z5~%Ou^0I;g$s9vzd1dV!ZJBnlq0~@T1&W5llMYvy z>VNUDc(UOxP8+T;eYnDm;R@x$6)J`+l!%8d9ac<<^jeHNr^ZmJD_&+GjlHm3Ut3U6 zK@N*bphRtDrM9-9+NcM1U7#%~)-Eg1l~+Uc4nbR1RasoNxIkBFfOtdeN)5}Ffll!$ zC9WVSR~m{8m4-5%VOZ+LpuMW{0^*XP)XA31%iz!}yVl_+HRv*mBt;U5R+lDA7iVZ? z83uzvk*bqRe*Usii_~T6&?lNL-k1(8&tZ(zQhf zd4^1!F4sv6iXyq;y0s)O(t-Ixq1EXN6|yv~PODSs(`5!=!!n@vLhW^H=>{f^t82*! zC*SK-lOk0v)+-A2pyRc&!gO(AhD=eU$k3-Nqeod5hDXRXQU48= zQ{f-fEH+dXEGu4VD3IuV1|A;tze3g#!OY! z#$TGg@v7l%dbqgd-r~~g5+Zgcbg!-~*MU&29K;PdH6WB)1_Emk*}yQnHmkf$UkoE{ z5JS|?DuY4MvSJ-MEGgwy6oU&u>`_vy^S%JYZ{8Q&G=5Y#LpPJYR=?E8Sg6j`l^cDd zXR5AL3px{ATMkrl)7ZIb0x~h_25+4&0bbD20c}a;upI2N2meB(CK!yy9I zU%|y1B~blWYLbG2xrQPvx*oPt1s5$?_0^h@UI$A6*PA6Dg$!9SU41SZGHAV=!p*ag zn>|9ZKm)+cZ>j)5_gCx5)a&R;fQt?2Yp_Fr>fPzT!T~__ChTvRz=nR=YC+|-S*`3k zWCgh1EL}|ifO@U6;;7z)Z+72{9c~Y6DbrI835+*A0qg0@cVf_f5Jd_zrV_UzuDY} zVSF0DnoVY0hfM<9Yc(|ab&v(P-ehlrdT*LR{C;zwZ^r?afl{v4bBgOwF~Id6^uI#Z zyElFv^;!u_#Mi+vM7|!v*UB=a3vj(j-yD0x8@ZbHBp{l_cj2!gB!S4@O#d3;Yt{## z>!XjWlD?kU8SJcIJI?_3nt8@?z149oTME7>AYj5WRF)gPCMwS%2(fMMw_8AL)4}b6 gmEdBZYrSg0`Qq@E!!O&fpMQyDl6Vr#=fyt%4^BGPRR910 diff --git a/src/Qir/Controller/test-cases/standalone-input-test.out b/src/Qir/Controller/test-cases/standalone-input-test.out deleted file mode 100644 index 73833a0e784..00000000000 --- a/src/Qir/Controller/test-cases/standalone-input-test.out +++ /dev/null @@ -1,14 +0,0 @@ -Exercise Supported Inputs Reference -intValue: 42 -intArray: [9223372036854775807, 4, 4, 2, 3] (5) -doubleValue: 3.14000000000000012 -doubleArray: [0.59999999999999998, 0.40000000000000002, 43.20000000000000284] (3) -boolValue: true -boolArray: [true, false, true, true, false] (5) -pauliValue: PauliZ -pauliArray: [PauliX, PauliI, PauliY, PauliY, PauliZ] (5) -rangeValue: 3..12..27 -resultValue: One -resultArray: [One, One, Zero, One] (4) -stringValue: string value -() diff --git a/src/Qir/Controller/test-qir-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 deleted file mode 100644 index 85c4edcbf7b..00000000000 --- a/src/Qir/Controller/test-qir-controller.ps1 +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -$all_ok = $True - -Write-Host "##[info]Test QIR Controller" - -$buildConfiguration = $Env:BUILD_CONFIGURATION -$controllerProject = (Join-Path $PSScriptRoot QirController.csproj) -$testCasesFolder = (Join-Path $PSScriptRoot "test-cases") -$testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") -$includeDirectory = (Join-Path $testArtifactsFolder "include") -$headerPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Common\externals\CLI11"), (Join-Path $PSScriptRoot "..\..\Qir\Runtime\public")) -$libraryPaths = @((Join-Path $PSScriptRoot "..\..\Qir\Runtime\bin\$buildConfiguration\bin"), (Join-Path $PSScriptRoot "..\..\Simulation\Simulators\bin\$buildConfiguration\netstandard2.1"), $Env:NATIVE_SIMULATOR) -$includeDirectory = (Join-Path $testArtifactsFolder "include") -$libraryDirectory = (Join-Path $testArtifactsFolder "library") - -if (($IsWindows) -or ((Test-Path Env:AGENT_OS) -and ($Env:AGENT_OS.StartsWith("Win")))) -{ - Write-Host "On Windows build using Clang" - - if (!(Get-Command clang -ErrorAction SilentlyContinue) -and (choco find --idonly -l llvm) -contains "llvm") { - # LLVM was installed by Chocolatey, so add the install location to the path. - $env:PATH += ";$($env:SystemDrive)\Program Files\LLVM\bin" - Write-Host "Adding clang to path. Path: $env:PATH" - } -} - -if (!(Test-Path $testArtifactsFolder -PathType Container)) { - New-Item -ItemType Directory -Force -Path $testArtifactsFolder -} -Get-ChildItem -Path $testArtifactsFolder | Remove-Item -Force -Recurse - -# Copy includes to the include folder -New-Item -ItemType "directory" -Path $includeDirectory -Force -foreach ( $path in $headerPaths ) -{ - Get-ChildItem $path -File | - Foreach-Object { - Copy-Item $_.FullName -Destination (Join-Path $includeDirectory $_.Name) - } -} - -# Copy libraries to the library folder -New-Item -ItemType "directory" -Path $libraryDirectory -Force -foreach ( $path in $libraryPaths ) -{ - Get-ChildItem $path -File | - Foreach-Object { - Copy-Item $_.FullName -Destination (Join-Path $libraryDirectory $_.Name) - } -} - -# Go through each input file in the test cases folder. -Get-ChildItem $testCasesFolder -Filter *.in | -Foreach-Object { - - # Get the paths to the output and error files to pass to the QIR controller. - $testPassed = $True - $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) - $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) - dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile --includeDirectory $includeDirectory --libraryDirectory $libraryDirectory - - # Compare the expected content of the output and error files vs the actual content. - $expectedOutputFile = (Join-Path $testCasesFolder ($_.BaseName + ".out")) - $expectedErrorFile = (Join-Path $testCasesFolder ($_.BaseName + ".err")) - - if ((Test-Path $expectedOutputFile)) { - $expectedOutput = Get-Content -Path $expectedOutputFile -Raw - $actualOutput = Get-Content -Path $outputFile -Raw - if (-not ($expectedOutput -ceq $actualOutput)) { - Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" - Write-Host "##[info]Expected output:" - Write-Host $expectedOutput - Write-Host "##[info]Actual output:" - Write-Host $actualOutput - $testPassed = $False - } - } - if ((Test-Path $expectedErrorFile)) { - $expectedError = Get-Content -Path $expectedErrorFile -Raw - $actualError = Get-Content -Path $errorFile -Raw - if (-not ($expectedError -ceq $actualError)) { - Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" - Write-Host "##[info]Expected error:" - Write-Host $expectedError - Write-Host "##[info]Actual error:" - Write-Host $actualError - $testPassed = $False - } - } - - if ($testPassed) { - Write-Host "##[info]Test case '$($_.BaseName)' passed" - } - else { - $script:all_ok = $False - } -} - -if (-not $all_ok) { - throw "At least one project failed testing. Check the logs." -} From 4765bda9f64a1ecede1407417ee35f425c754478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 29 Jun 2021 11:44:55 -0700 Subject: [PATCH 124/145] Remove test for controller. --- build/test.ps1 | 3 --- 1 file changed, 3 deletions(-) diff --git a/build/test.ps1 b/build/test.ps1 index a1483f24933..b85f7bae111 100644 --- a/build/test.ps1 +++ b/build/test.ps1 @@ -56,9 +56,6 @@ if ($Env:ENABLE_QIRRUNTIME -ne "false") { $script:all_ok = $False } - $qirController = (Join-Path $PSScriptRoot "../src/Qir/Controller") - & "$qirController/test-qir-controller.ps1" - if ($LastExitCode -ne 0) { $script:all_ok = $False } From 54a4d6ba74eade33f3b806b95e5d55b72e919ceb Mon Sep 17 00:00:00 2001 From: "Stefan J. Wernli" Date: Tue, 29 Jun 2021 17:57:33 -0700 Subject: [PATCH 125/145] Fix QIR Simulator dll load (#760) * Fix QIR Simulator dll load Since the packaged Fullstate Simulator always uses the Windows style dll name and local development (or xplat pipelines) need to handle the platform specific library name, we will imitiate the loading patterns from .NET and try both when not on Windows. * Fix warning as error --- .../lib/Simulators/FullstateSimulator.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp b/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp index e242cfec42d..8724a7b6a3a 100644 --- a/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp +++ b/src/Qir/Runtime/lib/Simulators/FullstateSimulator.cpp @@ -29,12 +29,11 @@ typedef void* QUANTUM_SIMULATOR; namespace { -#ifdef _WIN32 const char* FULLSTATESIMULATORLIB = "Microsoft.Quantum.Simulator.Runtime.dll"; -#elif __APPLE__ -const char* FULLSTATESIMULATORLIB = "libMicrosoft.Quantum.Simulator.Runtime.dylib"; -#else -const char* FULLSTATESIMULATORLIB = "libMicrosoft.Quantum.Simulator.Runtime.so"; +#if defined(__APPLE__) +const char* XPLATFULLSTATESIMULATORLIB = "libMicrosoft.Quantum.Simulator.Runtime.dylib"; +#elif !defined(_WIN32) +const char* XPLATFULLSTATESIMULATORLIB = "libMicrosoft.Quantum.Simulator.Runtime.so"; #endif QUANTUM_SIMULATOR LoadQuantumSimulator() @@ -52,8 +51,12 @@ QUANTUM_SIMULATOR LoadQuantumSimulator() handle = ::dlopen(FULLSTATESIMULATORLIB, RTLD_LAZY); if (handle == nullptr) { - throw std::runtime_error( - std::string("Failed to load ") + FULLSTATESIMULATORLIB + " (" + ::dlerror() + ")"); + handle = ::dlopen(XPLATFULLSTATESIMULATORLIB, RTLD_LAZY); + if (handle == nullptr) + { + throw std::runtime_error( + std::string("Failed to load ") + XPLATFULLSTATESIMULATORLIB + " (" + ::dlerror() + ")"); + } } #endif return handle; From 0ece8a753b7351c139034d7b4444a7104a47ea7b Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Tue, 29 Jun 2021 19:02:32 -0700 Subject: [PATCH 126/145] updating package references and fixing qirexe --- global.json | 2 +- .../Microsoft.Quantum.AutoSubstitution.csproj | 2 +- .../TestProjects/QirExe/QirExe.csproj | 15 +++------------ src/Xunit/Microsoft.Quantum.Xunit.nuspec | 2 +- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/global.json b/global.json index 62bca5f3c81..361bac8f2df 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Quantum.Sdk": "0.18.2106149090-alpha" + "Microsoft.Quantum.Sdk": "0.18.210628594-pull" } } diff --git a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj index 4b7b82f55fa..fe54c16f2d9 100644 --- a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj +++ b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj index f507980d701..e47db616807 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj @@ -2,23 +2,14 @@ Exe netcoreapp3.1 - - - - false - true false + false + false + true - - - - - - - diff --git a/src/Xunit/Microsoft.Quantum.Xunit.nuspec b/src/Xunit/Microsoft.Quantum.Xunit.nuspec index 2de29fd3572..7482a1509ee 100644 --- a/src/Xunit/Microsoft.Quantum.Xunit.nuspec +++ b/src/Xunit/Microsoft.Quantum.Xunit.nuspec @@ -22,7 +22,7 @@ - + From 43e5fd2e80949b3898489d5437520e4320f57b0c Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Tue, 29 Jun 2021 19:11:03 -0700 Subject: [PATCH 127/145] updating tests --- src/Simulation/EntryPointDriver.Tests/Tests.fs | 1 + src/Simulation/Simulators.Tests/CoreTests.cs | 1 + .../Simulators.Tests/TestProjects/QirExe/QirExe.csproj | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index ae20d535b00..f251d15c077 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -897,6 +897,7 @@ let ``Submit supports Q# submitters`` () = Base URI: Location: myLocation Credential: Default + AadToken: Job Name: Shots: 500 Output: FriendlyUri diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 33deec89207..1fe87bc91d5 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -104,6 +104,7 @@ public void SubmitsQir() "Base URI: ", "Location: myLocation", "Credential: Default", + "AadToken: ", "Job Name: ", "Shots: 500", "Output: FriendlyUri", diff --git a/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj index e47db616807..307a706b6d5 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QirExe/QirExe.csproj @@ -5,7 +5,7 @@ false false false - true + microsoft.simulator.fullstate From f2cda5e0f30ce46a7cc5479151027aef244f779f Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Tue, 29 Jun 2021 20:34:26 -0700 Subject: [PATCH 128/145] fixing link --- src/Qir/Runtime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Runtime/README.md b/src/Qir/Runtime/README.md index 94781ecb430..3430ce20473 100644 --- a/src/Qir/Runtime/README.md +++ b/src/Qir/Runtime/README.md @@ -30,7 +30,7 @@ while on macOS, `prerequisites.ps1` relies on the [`brew` package manager](https 1. Add all three to your/system `%PATH%`. 1. Install VS 2019 and enable "Desktop development with C++" component (Clang uses MSVC's standard library on Windows). 1. Install clang-tidy and clang-format if your Clang/LLVM packages didn't include the tools. -1. Install the same version of dotnet as specified by qsharp-runtime [README](../../../README.md) +1. Install the same version of dotnet as specified by qsharp-runtime [README](../../../../README.md) *Building from Visual Studio and VS Code is **not** supported. Running cmake from the editors will likely default to MSVC or clang-cl and fail.* From 68e990cd0913877960f58e668f563d7fd8721d28 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Tue, 29 Jun 2021 22:21:55 -0700 Subject: [PATCH 129/145] package update --- global.json | 2 +- .../AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj | 2 +- src/Xunit/Microsoft.Quantum.Xunit.nuspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/global.json b/global.json index 361bac8f2df..a42245d3dc3 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Quantum.Sdk": "0.18.210628594-pull" + "Microsoft.Quantum.Sdk": "0.18.210628645-alpha" } } diff --git a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj index fe54c16f2d9..d055b0e9981 100644 --- a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj +++ b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/Xunit/Microsoft.Quantum.Xunit.nuspec b/src/Xunit/Microsoft.Quantum.Xunit.nuspec index 7482a1509ee..ec6a377f57c 100644 --- a/src/Xunit/Microsoft.Quantum.Xunit.nuspec +++ b/src/Xunit/Microsoft.Quantum.Xunit.nuspec @@ -22,7 +22,7 @@ - + From 8c6428957e219ab94884b1088976f6fd13b5668a Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Tue, 29 Jun 2021 23:03:20 -0700 Subject: [PATCH 130/145] missed a package that needed updating --- .../Tests.Microsoft.Quantum.EntryPointDriver.fsproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj index 3c6b61029c0..62963c97091 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj +++ b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj @@ -23,7 +23,7 @@ - + From 45e7a17656d44e8005d289aa8f23f7cdd3b1b131 Mon Sep 17 00:00:00 2001 From: bettinaheim <34236215+bettinaheim@users.noreply.github.com> Date: Wed, 30 Jun 2021 00:58:05 -0700 Subject: [PATCH 131/145] Fixing link (#762) --- src/Qir/Runtime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Runtime/README.md b/src/Qir/Runtime/README.md index 3430ce20473..94781ecb430 100644 --- a/src/Qir/Runtime/README.md +++ b/src/Qir/Runtime/README.md @@ -30,7 +30,7 @@ while on macOS, `prerequisites.ps1` relies on the [`brew` package manager](https 1. Add all three to your/system `%PATH%`. 1. Install VS 2019 and enable "Desktop development with C++" component (Clang uses MSVC's standard library on Windows). 1. Install clang-tidy and clang-format if your Clang/LLVM packages didn't include the tools. -1. Install the same version of dotnet as specified by qsharp-runtime [README](../../../../README.md) +1. Install the same version of dotnet as specified by qsharp-runtime [README](../../../README.md) *Building from Visual Studio and VS Code is **not** supported. Running cmake from the editors will likely default to MSVC or clang-cl and fail.* From c48964f4b9bc05d5a7afbbdc4ecdbdde34e74269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 30 Jun 2021 19:34:33 -0700 Subject: [PATCH 132/145] Address Robin's feedback. --- .gitignore | 4 ---- build/test.ps1 | 4 ---- 2 files changed, 8 deletions(-) diff --git a/.gitignore b/.gitignore index 02e6c5fb0ee..96ada8e2b36 100644 --- a/.gitignore +++ b/.gitignore @@ -343,10 +343,6 @@ ASALocalRun/ dbw_test -# Controller test artifacts -/src/Qir/Controller/test-artifacts/ -/src/Qir/Controller/src - # out folders out/ diff --git a/build/test.ps1 b/build/test.ps1 index b85f7bae111..211c5931bd6 100644 --- a/build/test.ps1 +++ b/build/test.ps1 @@ -55,10 +55,6 @@ if ($Env:ENABLE_QIRRUNTIME -ne "false") { if ($LastExitCode -ne 0) { $script:all_ok = $False } - - if ($LastExitCode -ne 0) { - $script:all_ok = $False - } } else { Write-Host "Skipping test of qir runtime because ENABLE_QIRRUNTIME variable is set to: $Env:ENABLE_QIRRUNTIME." } From 59c04367976d2f20e749457aacf51151cff99a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 2 Jul 2021 15:54:59 -0700 Subject: [PATCH 133/145] Address Dmitry's feedback. --- .../Azure.Quantum.Client/SubmitterFactory.cs | 2 +- .../LoggerTests.cs | 39 ++++++++++----- .../QirDriverGeneratorTests.cs | 8 +-- .../QirExecutableGeneratorTests.cs | 36 +++++--------- .../QirExecutableTests.cs | 14 ++---- .../FullStateDriverGenerator/UseBoolArg.cpp | 8 +-- .../UseBoolArrayArg.cpp | 8 +-- .../FullStateDriverGenerator/UseDoubleArg.cpp | 8 +-- .../UseDoubleArrayArg.cpp | 8 +-- .../UseIntegerArg.cpp | 8 +-- .../UseIntegerArrayArg.cpp | 8 +-- .../FullStateDriverGenerator/UseMiscArgs.cpp | 8 +-- .../FullStateDriverGenerator/UseNoArgs.cpp | 8 +-- .../FullStateDriverGenerator/UsePauliArg.cpp | 8 +-- .../UsePauliArrayArg.cpp | 8 +-- .../FullStateDriverGenerator/UseRangeArg.cpp | 8 +-- .../UseRangeArrayArg.cpp | 8 +-- .../FullStateDriverGenerator/UseResultArg.cpp | 8 +-- .../UseResultArrayArg.cpp | 8 +-- .../FullStateDriverGenerator/UseStringArg.cpp | 8 +-- .../Tests.Microsoft.Quantum.Qir.Tools/Util.cs | 49 +++++++++++++++++-- .../Tools/Driver/IQirSimulatorInitializer.cs | 4 +- .../Execution/Tools/Driver/QirCppDriver.cs | 8 +-- .../Execution/Tools/Driver/QirCppDriver.tt | 8 +-- .../QirFullStateSimulatorInitializer.cs | 4 +- src/Qir/Execution/Tools/README.md | 25 ++++++++++ 26 files changed, 206 insertions(+), 111 deletions(-) create mode 100644 src/Qir/Execution/Tools/README.md diff --git a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs index b10588ed1fd..d4e303cf707 100644 --- a/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs +++ b/src/Azure/Azure.Quantum.Client/SubmitterFactory.cs @@ -23,7 +23,7 @@ public static class SubmitterFactory /// private static readonly ImmutableList QirSubmitters = ImmutableList.Create( new SubmitterInfo( - new Regex(@"^microsoft\.simulator\.([\w]+\.)*[\w]+$"), + new Regex(@"\Amicrosoft\.simulator\.([\w]+\.)*[\w]+\z"), "Microsoft.Quantum.Providers.Targets.MicrosoftSimulatorSubmitter, Microsoft.Quantum.Providers.Core", "QirSubmitter")); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs index 1df4bf96552..85df2dcc7bd 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs @@ -20,6 +20,8 @@ public LoggerTests() logger = new Logger(clockMock.Object); } + // N.B. Since the logger is meant for internal use, these tests do not verify whether the logger produced a + // specific output. Instead it is verified that the produced output contains certain elements. [Fact] public void TestLogInfo() { @@ -27,11 +29,15 @@ public void TestLogInfo() var message = "some message"; var time = DateTimeOffset.MinValue; clockMock.SetupGet(obj => obj.Now).Returns(time); - var expectedLog = $"{time} [INFO]: some message" + Environment.NewLine; Console.SetOut(consoleOutput); logger.LogInfo(message); var actualLog = consoleOutput.ToString(); - Assert.Equal(expectedLog, actualLog); + + // Verify that the expected elements are present in the produced output. + Assert.Contains(time.ToString(), actualLog); + Assert.Contains("INFO", actualLog); + Assert.Contains(message, actualLog); + Assert.EndsWith(Environment.NewLine, actualLog); } [Fact] @@ -41,11 +47,15 @@ public void TestLogError() var message = "some message"; var time = DateTimeOffset.MinValue; clockMock.SetupGet(obj => obj.Now).Returns(time); - var expectedLog = $"{time} [ERROR]: some message" + Environment.NewLine; Console.SetOut(consoleOutput); logger.LogError(message); var actualLog = consoleOutput.ToString(); - Assert.Equal(expectedLog, actualLog); + + // Verify that the expected elements are present in the produced output. + Assert.Contains(time.ToString(), actualLog); + Assert.Contains("ERROR", actualLog); + Assert.Contains(message, actualLog); + Assert.EndsWith(Environment.NewLine, actualLog); } [Fact] @@ -55,13 +65,15 @@ public void TestLogExceptionWithoutStackTrace() var time = DateTimeOffset.MinValue; clockMock.SetupGet(obj => obj.Now).Returns(time); var exception = new InvalidOperationException(); - var expectedLog = $"{time} [ERROR]: " + - "Exception encountered: System.InvalidOperationException: " + - exception.Message + Environment.NewLine + exception.StackTrace + Environment.NewLine; Console.SetOut(consoleOutput); logger.LogException(exception); var actualLog = consoleOutput.ToString(); - Assert.Equal(expectedLog, actualLog); + + // Verify that the expected elements are present in the produced output. + Assert.Contains(time.ToString(), actualLog); + Assert.Contains("ERROR", actualLog); + Assert.Contains(exception.Message, actualLog); + Assert.EndsWith(Environment.NewLine, actualLog); } [Fact] @@ -81,13 +93,16 @@ public void TestLogExceptionWithStackTrace() exception = thrownException; } - var expectedLog = $"{time} [ERROR]: " + - "Exception encountered: System.InvalidOperationException: " + - exception.Message + Environment.NewLine + exception.StackTrace + Environment.NewLine; Console.SetOut(consoleOutput); logger.LogException(exception); var actualLog = consoleOutput.ToString(); - Assert.Equal(expectedLog, actualLog); + + // Verify that the expected elements are present in the produced output. + Assert.Contains(time.ToString(), actualLog); + Assert.Contains("ERROR", actualLog); + Assert.Contains(exception.Message, actualLog); + Assert.Contains(exception.StackTrace, actualLog); + Assert.EndsWith(Environment.NewLine, actualLog); } } } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs index 03a0859093e..ece6d0e22fd 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -143,7 +143,7 @@ public class QirDriverGeneratorTests }; private static string RemoveLineEndings(string str) => - str.Replace("\r\n", string.Empty).Replace("\n", string.Empty).Replace("\r", string.Empty); + str.Replace("\n", string.Empty).Replace("\r", string.Empty); [Theory] [InlineData("UseNoArgs")] @@ -167,11 +167,7 @@ public void GenerateFullStateSimulatorDriver(string testCase) var driverGenerator = new QirFullStateDriverGenerator(); var driverFileName = $"{testCase}.cpp"; var verificationCppSourceCode = RemoveLineEndings(File.ReadAllText(Path.Combine(TestCasesDirectory, driverFileName))); - if (!Directory.Exists(TestArtifactsDirectory)) - { - Directory.CreateDirectory(TestArtifactsDirectory); - } - + Directory.CreateDirectory(TestArtifactsDirectory); var generatedStream = File.Create(Path.Combine(TestArtifactsDirectory, driverFileName)); driverGenerator.GenerateAsync(entryPointOperation, generatedStream).Wait(); var generatedStreamReader = new StreamReader(generatedStream, Encoding.UTF8); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs index fd88b7550f6..2a51b7c71a9 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs @@ -38,8 +38,8 @@ public QirExecutableGeneratorTests() libraryDirectory.Create(); libraryFiles = new List() { - CreateFile("lib1", libraryDirectory, "lib1 contents"), - CreateFile("lib2", libraryDirectory, "lib2 contents"), + Util.CreateBinaryFile(libraryDirectory, "lib1", new byte[]{0x01, 0x23, 0x45, 0x67}), + Util.CreateBinaryFile(libraryDirectory, "lib2", new byte[]{0x89, 0xAB, 0xCD, 0xEF}), }; includeDirectory = new DirectoryInfo($"{prefix}-include"); includeDirectory.Create(); @@ -47,18 +47,18 @@ public QirExecutableGeneratorTests() sourceDirectory.Create(); sourceFiles = new List() { - CreateFile("src1.cpp", sourceDirectory, "src1 contents"), - CreateFile("src2.bc", sourceDirectory, "src2 contents"), + Util.CreateTextFile(sourceDirectory, "src1.cpp", "src1 contents"), + Util.CreateBinaryFile(sourceDirectory, "src2.bc", new byte[]{0xFE, 0xDC, 0xBA, 0x98}), }; linkLibraries = new List { "lib1", "lib2" }; } public void Dispose() { - Util.DeleteDirectory(sourceDirectory); - Util.DeleteDirectory(includeDirectory); - Util.DeleteDirectory(libraryDirectory); - Util.DeleteDirectory(binDirectory); + sourceDirectory.Delete(true); + includeDirectory.Delete(true); + libraryDirectory.Delete(true); + binDirectory.Delete(true); } [Fact] @@ -79,35 +79,25 @@ public async Task TestGenerateExecutable() Assert.True(FilesWereCopied(libraryFiles.ToArray(), binDirectory)); } - private static FileInfo CreateFile(string fileName, DirectoryInfo directory, string contents) - { - var filePath = Path.Combine(directory.FullName, fileName); - var fileInfo = new FileInfo(filePath); - using var fileStream = fileInfo.OpenWrite(); - using var streamWriter = new StreamWriter(fileStream); - streamWriter.Write(contents); - return fileInfo; - } - private static bool FilesWereCopied(FileInfo[] files, DirectoryInfo destinationDirectory) { var destinationDirectoryFiles = destinationDirectory.GetFiles(); + + // N.B. Runtime is (number of FileInfo objects passed in) * (number of files in destination directory). foreach (var file in files) { + // Make sure that the file was copied and that the contents is the same. var copiedFile = destinationDirectoryFiles.FirstOrDefault(fileInfo => fileInfo.Name == file.Name); if (copiedFile == null) { return false; } - using var originalFileReader = file.OpenText(); - var originalFileContents = originalFileReader.ReadToEnd(); - using var copiedFileReader = copiedFile.OpenText(); - var copiedFileContents = copiedFileReader.ReadToEnd(); - if (originalFileContents != copiedFileContents) + if (!Util.CompareFiles(file, copiedFile)) { return false; } + } return true; diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs index 292f1e7d3d9..95f5f9a666b 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -60,10 +60,10 @@ public QirExecutableTests() public void Dispose() { - Util.DeleteDirectory(sourceDirectory); - Util.DeleteDirectory(includeDirectory); - Util.DeleteDirectory(libraryDirectory); - Util.DeleteDirectory(binDirectory); + sourceDirectory.Delete(true); + includeDirectory.Delete(true); + libraryDirectory.Delete(true); + binDirectory.Delete(true); } [Fact] @@ -84,11 +84,7 @@ public async Task TestBuild() // Verify that the "bytecode" file was created correctly. var bytecodeFilePath = new FileInfo(Path.Combine(sourceDirectory.FullName, "qir.bc")); using var bytecodeFileStream = bytecodeFilePath.OpenRead(); - Assert.Equal(bytecodeFileStream.Length, qirBytecode.Length); - for (var i = 0; i < bytecodeFileStream.Length; ++i) - { - Assert.Equal(qirBytecode[i], bytecodeFileStream.ReadByte()); - } + Assert.True(Util.CompareStreams(new MemoryStream(qirBytecode), bytecodeFileStream)); // Verify that the driver was written to the correct file. var driver = new FileInfo(Path.Combine(sourceDirectory.FullName, "driver.cpp")); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp index ac2d8510044..e1ea3cc80c4 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp index 49ba88538d7..3b1c27e9881 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp index c07687f1e4e..9b847e44b1e 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp index 707c2095bc9..ee753a6c3f6 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp index 6d4d4614f9a..b9b18b6235c 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp index e3cc2f8bf60..0eb3b81b596 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp index 28373859dbf..b0477cdb41f 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp index eb6597a7f4f..94da475abcc 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp index 134db56ea44..6695c31bbbf 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp index 22b27411fe6..01558e453bd 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp index 3b89eb0ab7c..6c2bedc708f 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp index 354999a5251..249090ed143 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp index 516888b83b0..12d5aedb661 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp index 2f5f36c09e1..b89c1b380b9 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp index bdfc37c878b..9caaeddbc23 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp @@ -1,7 +1,9 @@ -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs index e027bbe5403..011e3643ac2 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs @@ -5,15 +5,54 @@ namespace Tests.Microsoft.Quantum.Qir.Tools { - public static class Util + internal static class Util { - public static void DeleteDirectory(DirectoryInfo directory) + public static bool CompareFiles(FileInfo fileA, FileInfo fileB) { - foreach (var file in directory.GetFiles()) + if (fileA.FullName == fileB.FullName) { - file.Delete(); + return true; } - directory.Delete(); + + using var fileStreamA = fileA.OpenRead(); + using var fileStreamB = fileB.OpenRead(); + return CompareStreams(fileStreamA, fileStreamB); + } + + public static bool CompareStreams(Stream streamA, Stream streamB) + { + if (streamA.Length != streamB.Length) + { + return false; + } + + (streamA.Position, streamB.Position) = (0, 0); + (int byteA, int byteB) = (0, 0); + while ((byteA == byteB) && (byteA != -1)) + { + (byteA, byteB) = (streamA.ReadByte(), streamB.ReadByte()); + } + + return byteA == byteB; + } + + public static FileInfo CreateBinaryFile(DirectoryInfo directory, string fileName, byte[] contents) + { + var filePath = Path.Combine(directory.FullName, fileName); + var fileInfo = new FileInfo(filePath); + using var fileStream = fileInfo.OpenWrite(); + fileStream.Write(contents); + return fileInfo; + } + + public static FileInfo CreateTextFile(DirectoryInfo directory, string fileName, string contents) + { + var filePath = Path.Combine(directory.FullName, fileName); + var fileInfo = new FileInfo(filePath); + using var fileStream = fileInfo.OpenWrite(); + using var streamWriter = new StreamWriter(fileStream); + streamWriter.Write(contents); + return fileInfo; } } } diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs index 1ed263c814d..b9de81eee33 100644 --- a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -11,8 +11,8 @@ public interface IQirSimulatorInitializer { public string Generate(); - public IList Headers { get; } + public IEnumerable Headers { get; } - public IList LinkLibraries { get; } + public IEnumerable LinkLibraries { get; } } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index c1eb3cec1d3..e6a01b9238e 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -24,10 +24,12 @@ public partial class QirCppDriver : QirCppDriverBase /// public virtual string TransformText() { - this.Write(@"//------------------------------------------------------------------------------ -// This code was generated by a tool. + this.Write(@"//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index a99fa9716e7..e28033531f5 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -1,10 +1,12 @@ <#@ template language="C#" linePragmas="false" #> <#@ import namespace="System.IO" #> <#@ import namespace="Microsoft.Quantum.QsCompiler.BondSchemas.Execution" #> -//------------------------------------------------------------------------------ -// This code was generated by a tool. +//---------------------------------------------------------------------------------------------------------------------- // -//------------------------------------------------------------------------------ +// This code was generated by the Microsoft.Quantum.Qir.Tools package. +// The purpose of this source code file is to provide an entry-point for executing a QIR program. +// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. +//---------------------------------------------------------------------------------------------------------------------- #include #include diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs index 12bea984368..6d2172f6bb8 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs @@ -13,10 +13,10 @@ public class QirFullStateSimulatorInitializer : IQirSimulatorInitializer { public string Generate() => new QirCppFullStateSimulatorInitializer().TransformText(); - public IList Headers => new List { + public IEnumerable Headers => new [] { "SimFactory.hpp" }; - public IList LinkLibraries => new List(); + public IEnumerable LinkLibraries => new string[0]; } } diff --git a/src/Qir/Execution/Tools/README.md b/src/Qir/Execution/Tools/README.md new file mode 100644 index 00000000000..8672fa65d42 --- /dev/null +++ b/src/Qir/Execution/Tools/README.md @@ -0,0 +1,25 @@ +# Microsoft.Quantum.Qir.Tools + +QIR executables are built by generating a C++ driver that is compiled and linked with the compiled QIR bitcode. + +## Driver + +This folder contains the implementation for the C++ driver generation. + +The C++ driver provides an entry-point for executing a QIR program. It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program. + +C++ is generated using [Visual Studio T4 text templates](https://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2019). *\*.tt* files represent the text templates. When the Microsoft.Quantum.Qir.Tools project is built using Visual Studio, a *\*.cs* (C\#) file is generated per each *\*.tt* file. The generated *\*.cs* file implements a class named as the template filename that provides a `TransformText` method used to generate the final text. + +**Note**: Generated *\*.cs* files are included in source control because T4 text templates are not cross-platform and cannot be generated during build pipelines. + +## Executable + +This folder contains the implementation for building and running QIR executables. + +## Externals + +This folder contains third-party components used to build and run QIR executables. + +## Utility + +This folder contains utility general-purpose classes used across the Microsoft.Quantum.Qir.Tools project. From cb251d80e2af221139e0e06a29f4f844c2bdcc1e Mon Sep 17 00:00:00 2001 From: bettinaheim <34236215+bettinaheim@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:23:36 -0700 Subject: [PATCH 134/145] Adding entry point operation loader (#766) --- .../Tools/EntryPointOperationLoader.cs | 94 +++++++++++++++++++ .../Tools/Executable/QirExecutable.cs | 22 ++--- .../Executable/QirFullStateExecutable.cs | 4 +- src/Qir/Execution/Tools/QirTools.cs | 6 +- 4 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 src/Qir/Execution/Tools/EntryPointOperationLoader.cs diff --git a/src/Qir/Execution/Tools/EntryPointOperationLoader.cs b/src/Qir/Execution/Tools/EntryPointOperationLoader.cs new file mode 100644 index 00000000000..7713ff0d03f --- /dev/null +++ b/src/Qir/Execution/Tools/EntryPointOperationLoader.cs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Quantum.Qir.Serialization; +using Microsoft.Quantum.QsCompiler; +using Microsoft.Quantum.QsCompiler.SyntaxTokens; +using Microsoft.Quantum.QsCompiler.SyntaxTree; +using Microsoft.Quantum.QsCompiler.QIR; + +namespace Microsoft.Quantum.Qir.Tools +{ + using QsTypeKind = QsTypeKind; + + internal static class EntryPointLoader + { + /// + /// Loads the entry point operations found in the syntax tree included as a resource from . + /// + /// The file info of a .NET DLL from which to load entry point operations from. + /// + /// A list of entry point operation objects representing the QIR entry point operations. + /// + /// does not exist. + /// does not contain a Q# syntax tree. + /// Encounters invalid parameters for an entry point. + public static IList LoadEntryPointOperations(FileInfo assemblyFileInfo) + { + if (!AssemblyLoader.LoadReferencedAssembly(assemblyFileInfo.FullName, out var compilation)) + { + throw new ArgumentException("Unable to read the Q# syntax tree from the given DLL."); + } + + return GenerateEntryPointOperations(compilation); + } + + private static IList GenerateEntryPointOperations(QsCompilation compilation) + { + var globals = compilation.Namespaces.GlobalCallableResolutions(); + + return compilation.EntryPoints.Select(ep => new EntryPointOperation() + { + Name = NameGeneration.InteropFriendlyWrapperName(ep), + Parameters = GetParams(globals[ep]), + }).ToList(); + } + + private static List GetParams(QsCallable callable) + { + return SyntaxGenerator.ExtractItems(callable.ArgumentTuple) + .Where(sym => !sym.Type.Resolution.IsUnitType) + .Select(sym => MakeParameter(sym)) + .ToList(); + } + + private static Parameter MakeParameter(LocalVariableDeclaration parameter) + { + var type = MapResolvedTypeToDataType(parameter.Type); + var arrayType = parameter.Type.Resolution is QsTypeKind.ArrayType innerType + ? (DataType?)MapResolvedTypeToDataType(innerType.Item) + : null; + + if (arrayType == DataType.ArrayType) + { + throw new ArgumentException("Multi-dimensional arrays are not supported types of entry point parameters."); + } + + return new Parameter() + { + Name = parameter.VariableName is QsLocalSymbol.ValidName name + ? name.Item + : throw new ArgumentException("Encountered invalid name for parameter."), + Type = type, + ArrayType = arrayType, + }; + } + + private static DataType MapResolvedTypeToDataType(ResolvedType rt) => rt.Resolution.Tag switch + { + QsTypeKind.Tags.Bool => DataType.BoolType, + QsTypeKind.Tags.Int => DataType.IntegerType, + QsTypeKind.Tags.Double => DataType.DoubleType, + QsTypeKind.Tags.Pauli => DataType.PauliType, + QsTypeKind.Tags.Range => DataType.RangeType, + QsTypeKind.Tags.Result => DataType.ResultType, + QsTypeKind.Tags.String => DataType.StringType, + QsTypeKind.Tags.ArrayType => DataType.ArrayType, + _ => throw new ArgumentException($"Invalid type ({rt.Resolution.Tag}) for entry point parameter"), + }; + } +} diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs index a962aa46a76..118fef8ed9c 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -17,7 +17,7 @@ namespace Microsoft.Quantum.Qir.Tools.Executable public abstract class QirExecutable : IQirExecutable { private const string DriverFileName = "driver"; - private const string BytecodeFileName = "qir.bc"; + private const string BitcodeFileName = "qir.bc"; public virtual string SourceDirectoryPath => "src"; public abstract string DriverFileExtension { get; } @@ -27,15 +27,15 @@ public abstract class QirExecutable : IQirExecutable protected FileInfo ExecutableFile { get; } - private readonly byte[] qirBytecode; + private readonly byte[] qirBitcode; private readonly ILogger logger; private readonly IQuantumExecutableRunner runner; private readonly IQirDriverGenerator driverGenerator; private readonly IQirExecutableGenerator executableGenerator; - public QirExecutable(FileInfo executableFile, byte[] qirBytecode, IQirDriverGenerator driverGenerator, ILogger logger = null) + public QirExecutable(FileInfo executableFile, byte[] qirBitcode, IQirDriverGenerator driverGenerator, ILogger logger = null) : this(executableFile, - qirBytecode, + qirBitcode, logger ?? new Logger(new Clock()), driverGenerator, new QirExecutableGenerator(new ClangClient(logger), logger), @@ -43,10 +43,10 @@ public QirExecutable(FileInfo executableFile, byte[] qirBytecode, IQirDriverGene { } - internal QirExecutable(FileInfo executableFile, byte[] qirBytecode, ILogger logger, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner runner) + internal QirExecutable(FileInfo executableFile, byte[] qirBitcode, ILogger logger, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner runner) { ExecutableFile = executableFile; - this.qirBytecode = qirBytecode; + this.qirBitcode = qirBitcode; this.logger = logger; this.runner = runner; this.driverGenerator = driverGenerator; @@ -73,13 +73,13 @@ public async Task BuildAsync(EntryPointOperation entryPoint, IList LibraryDirectories { get; } = new List(); - public QirFullStateExecutable(FileInfo executableFile, byte[] qirBytecode, ILogger logger = null) + public QirFullStateExecutable(FileInfo executableFile, byte[] qirBitcode, ILogger logger = null) : base(executableFile, - qirBytecode, + qirBitcode, new QirFullStateDriverGenerator(), logger) { diff --git a/src/Qir/Execution/Tools/QirTools.cs b/src/Qir/Execution/Tools/QirTools.cs index b79c73072bb..1b1990c3f95 100644 --- a/src/Qir/Execution/Tools/QirTools.cs +++ b/src/Qir/Execution/Tools/QirTools.cs @@ -31,9 +31,9 @@ public static async Task BuildFromQSharpDll( DirectoryInfo executablesDirectory) { using var qirContentStream = new MemoryStream(); - if (!AssemblyLoader.LoadQirByteCode(qsharpDll, qirContentStream)) + if (!AssemblyLoader.LoadQirBitcode(qsharpDll, qirContentStream)) { - throw new ArgumentException("The given DLL does not contain QIR byte code."); + throw new ArgumentException("The given DLL does not contain QIR bitcode."); } if (!executablesDirectory.Exists) @@ -41,7 +41,7 @@ public static async Task BuildFromQSharpDll( executablesDirectory.Create(); } - var tasks = EntryPointOperationLoader.LoadEntryPointOperations(qsharpDll).Select(entryPointOp => + var tasks = EntryPointLoader.LoadEntryPointOperations(qsharpDll).Select(entryPointOp => { var exeFileInfo = new FileInfo(Path.Combine(executablesDirectory.FullName, $"{entryPointOp.Name}.exe")); var exe = new QirFullStateExecutable(exeFileInfo, qirContentStream.ToArray()); From cd623e4d7b29c300796cd538affea2cbe8a8e48e Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 2 Jul 2021 17:45:23 -0700 Subject: [PATCH 135/145] updating package version --- global.json | 2 +- src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj | 2 +- .../Tests.Microsoft.Quantum.EntryPointDriver.fsproj | 2 +- src/Xunit/Microsoft.Quantum.Xunit.nuspec | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/global.json b/global.json index a42245d3dc3..1b1065ef3a4 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Quantum.Sdk": "0.18.210628645-alpha" + "Microsoft.Quantum.Sdk": "0.18.210728751-alpha" } } diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index dad660fc9f0..bbdb6d356e8 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj index 62963c97091..99ff11340a7 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj +++ b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj @@ -23,7 +23,7 @@ - + diff --git a/src/Xunit/Microsoft.Quantum.Xunit.nuspec b/src/Xunit/Microsoft.Quantum.Xunit.nuspec index ec6a377f57c..23929c5008b 100644 --- a/src/Xunit/Microsoft.Quantum.Xunit.nuspec +++ b/src/Xunit/Microsoft.Quantum.Xunit.nuspec @@ -22,7 +22,7 @@ - + From 3ab4d8e37b8801a268a8065df10b9bf4a5bb5704 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 5 Jul 2021 15:37:47 -0700 Subject: [PATCH 136/145] missed a package number update --- .../AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj index d055b0e9981..199782d00e4 100644 --- a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj +++ b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj @@ -19,7 +19,7 @@ - + From 84fd28fd49af7b6fdaa2640ab5e112bc5528b990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 7 Jul 2021 00:13:24 -0700 Subject: [PATCH 137/145] Fix namespaces to be backwards compatible. --- src/Simulation/EntryPointDriver/Azure/Azure.cs | 2 +- src/Simulation/EntryPointDriver/Azure/AzureSettings.cs | 2 +- src/Simulation/EntryPointDriver/Azure/OutputFormat.cs | 2 +- src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs | 2 +- src/Simulation/EntryPointDriver/Azure/QirSubmission.cs | 2 +- src/Simulation/EntryPointDriver/Driver.cs | 2 +- src/Simulation/EntryPointDriver/IEntryPoint.cs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 6b84bc35462..3dbae6a96c8 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -11,7 +11,7 @@ using Microsoft.Quantum.Simulation.Common.Exceptions; using static Microsoft.Quantum.EntryPointDriver.Driver; -namespace Microsoft.Quantum.EntryPointDriver.Azure +namespace Microsoft.Quantum.EntryPointDriver { using Environment = System.Environment; diff --git a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs index 79be1d8b29a..fa69b063cc7 100644 --- a/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs +++ b/src/Simulation/EntryPointDriver/Azure/AzureSettings.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Microsoft.Quantum.EntryPointDriver.Azure +namespace Microsoft.Quantum.EntryPointDriver { using Environment = System.Environment; diff --git a/src/Simulation/EntryPointDriver/Azure/OutputFormat.cs b/src/Simulation/EntryPointDriver/Azure/OutputFormat.cs index 2602a2a96af..0e899927a09 100644 --- a/src/Simulation/EntryPointDriver/Azure/OutputFormat.cs +++ b/src/Simulation/EntryPointDriver/Azure/OutputFormat.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -namespace Microsoft.Quantum.EntryPointDriver.Azure +namespace Microsoft.Quantum.EntryPointDriver { /// /// The information to show in the output after the job is submitted. diff --git a/src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs b/src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs index da6663218f7..df9722a4221 100644 --- a/src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs +++ b/src/Simulation/EntryPointDriver/Azure/QSharpSubmission.cs @@ -3,7 +3,7 @@ using Microsoft.Quantum.Simulation.Core; -namespace Microsoft.Quantum.EntryPointDriver.Azure +namespace Microsoft.Quantum.EntryPointDriver { /// /// A Q# entry point submission. diff --git a/src/Simulation/EntryPointDriver/Azure/QirSubmission.cs b/src/Simulation/EntryPointDriver/Azure/QirSubmission.cs index b8d491e290a..d85acc0388a 100644 --- a/src/Simulation/EntryPointDriver/Azure/QirSubmission.cs +++ b/src/Simulation/EntryPointDriver/Azure/QirSubmission.cs @@ -5,7 +5,7 @@ using System.Collections.Immutable; using System.IO; -namespace Microsoft.Quantum.EntryPointDriver.Azure +namespace Microsoft.Quantum.EntryPointDriver { /// /// A QIR entry point submission. diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 2999b3c3ce1..077ff710df2 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.Quantum.EntryPointDriver.Azure; +using Microsoft.Quantum.EntryPointDriver; using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Simulation/EntryPointDriver/IEntryPoint.cs b/src/Simulation/EntryPointDriver/IEntryPoint.cs index 16e2241feff..5c21bdadc21 100644 --- a/src/Simulation/EntryPointDriver/IEntryPoint.cs +++ b/src/Simulation/EntryPointDriver/IEntryPoint.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.Quantum.EntryPointDriver.Azure; +using Microsoft.Quantum.EntryPointDriver; using System.Collections.Generic; using System.CommandLine; using System.CommandLine.Parsing; From c2a0ef5722b3c95b9c4466f5cb26a7565feb18c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 7 Jul 2021 01:12:45 -0700 Subject: [PATCH 138/145] Rename some interfaces. --- .../Execution/Tools/Driver/IQirSimulatorInitializer.cs | 2 +- src/Qir/Execution/Tools/Driver/QirCppDriver.cs | 6 +++--- src/Qir/Execution/Tools/Driver/QirCppDriver.tt | 8 ++++---- src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs | 6 +++--- src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs | 8 ++++---- .../Tools/Driver/QirFullStateSimulatorInitializer.cs | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs index b9de81eee33..f4d02caee24 100644 --- a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -7,7 +7,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { - public interface IQirSimulatorInitializer + public interface IQirRuntimeInitializer { public string Generate(); diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index e6a01b9238e..92f6a860a1b 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -43,7 +43,7 @@ public virtual string TransformText() #include ""QirContext.hpp"" "); - foreach (var header in SimulatorInitializer.Headers) { + foreach (var header in RuntimeInitializer.Headers) { this.Write("#include \""); this.Write(this.ToStringHelper.ToStringWithCulture(header)); this.Write("\"\r\n"); @@ -157,8 +157,8 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write("\r\n"); } this.Write("); // QIR interop function.\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n CLI::App " + - "app(\"QIR Standalone Entry Point\");\r\n\r\n // Initialize simulator.\r\n"); - var initializerReader = new StringReader(SimulatorInitializer.Generate()); + "app(\"QIR Standalone Entry Point\");\r\n\r\n // Initialize runtime.\r\n"); + var initializerReader = new StringReader(RuntimeInitializer.Generate()); string line; while((line = initializerReader.ReadLine()) != null) { this.Write(" "); diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index e28033531f5..76e7d9312a6 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -1,6 +1,6 @@ <#@ template language="C#" linePragmas="false" #> <#@ import namespace="System.IO" #> -<#@ import namespace="Microsoft.Quantum.QsCompiler.BondSchemas.Execution" #> +<#@ import namespace="Microsoft.Quantum.Qir.Serialization" #> //---------------------------------------------------------------------------------------------------------------------- // // This code was generated by the Microsoft.Quantum.Qir.Tools package. @@ -19,7 +19,7 @@ #include "QirRuntime.hpp" #include "QirContext.hpp" -<# foreach (var header in SimulatorInitializer.Headers) { #> +<# foreach (var header in RuntimeInitializer.Headers) { #> #include "<#= header #>" <# } #> @@ -157,8 +157,8 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. -<# var initializerReader = new StringReader(SimulatorInitializer.Generate()); + // Initialize runtime. +<# var initializerReader = new StringReader(RuntimeInitializer.Generate()); string line; while((line = initializerReader.ReadLine()) != null) { #> <#= line #> diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs index b66eca09a57..af2b2ce0b02 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -9,12 +9,12 @@ public partial class QirCppDriver { public readonly EntryPointOperation EntryPoint; - public readonly IQirSimulatorInitializer SimulatorInitializer; + public readonly IQirRuntimeInitializer RuntimeInitializer; - public QirCppDriver(EntryPointOperation entryPoint, IQirSimulatorInitializer simulatorInitializer) + public QirCppDriver(EntryPointOperation entryPoint, IQirRuntimeInitializer runtimeInitializer) { EntryPoint = entryPoint; - SimulatorInitializer = simulatorInitializer; + RuntimeInitializer = runtimeInitializer; } } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index 26db40b0c90..11b8caccce5 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -13,18 +13,18 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public class QirCppDriverGenerator : IQirDriverGenerator { - private readonly IQirSimulatorInitializer SimulatorInitalizer; + private readonly IQirRuntimeInitializer RuntimeInitalizer; private delegate string StringConversion(ArgumentValue value); - public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) + public QirCppDriverGenerator(IQirRuntimeInitializer runtimeInitializer) { - SimulatorInitalizer = simulatorInitializer; + RuntimeInitalizer = runtimeInitializer; } public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream) { - var qirCppDriver = new QirCppDriver(entryPointOperation, SimulatorInitalizer); + var qirCppDriver = new QirCppDriver(entryPointOperation, RuntimeInitalizer); var cppSource = qirCppDriver.TransformText(); await stream.WriteAsync(Encoding.UTF8.GetBytes(cppSource)); await stream.FlushAsync(); diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs index 6d2172f6bb8..190dc93cf07 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { - public class QirFullStateSimulatorInitializer : IQirSimulatorInitializer + public class QirFullStateSimulatorInitializer : IQirRuntimeInitializer { public string Generate() => new QirCppFullStateSimulatorInitializer().TransformText(); From 945aab13b90ffe4261e421dacd75635a56920689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 7 Jul 2021 02:30:56 -0700 Subject: [PATCH 139/145] Make NoOpQirSubmitter internal. --- src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs index 185df32c64d..b604a1565bc 100644 --- a/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs +++ b/src/Simulation/EntryPointDriver/Mock/NoOpQirSubmitter.cs @@ -12,7 +12,7 @@ namespace Microsoft.Quantum.EntryPointDriver.Mock /// /// A QIR submitter that does nothing. /// - public class NoOpQirSubmitter : IQirSubmitter + internal class NoOpQirSubmitter : IQirSubmitter { /// /// The target for the no-op QIR submitter. From 094a8b09240905e0ba4ab52325d28945f1a90c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 7 Jul 2021 03:11:08 -0700 Subject: [PATCH 140/145] Update package number. --- global.json | 2 +- src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj | 2 +- .../AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj | 2 +- .../Tests.Microsoft.Quantum.EntryPointDriver.fsproj | 2 +- src/Xunit/Microsoft.Quantum.Xunit.nuspec | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/global.json b/global.json index 1b1065ef3a4..b1cbde009e2 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Quantum.Sdk": "0.18.210728751-alpha" + "Microsoft.Quantum.Sdk": "0.18.2107150698-alpha" } } diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index bbdb6d356e8..d5c150b132f 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj index 199782d00e4..eefc1572c40 100644 --- a/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj +++ b/src/Simulation/AutoSubstitution/Microsoft.Quantum.AutoSubstitution.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj index 99ff11340a7..858e1e71edb 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj +++ b/src/Simulation/EntryPointDriver.Tests/Tests.Microsoft.Quantum.EntryPointDriver.fsproj @@ -23,7 +23,7 @@ - + diff --git a/src/Xunit/Microsoft.Quantum.Xunit.nuspec b/src/Xunit/Microsoft.Quantum.Xunit.nuspec index 23929c5008b..50e8aeb5e18 100644 --- a/src/Xunit/Microsoft.Quantum.Xunit.nuspec +++ b/src/Xunit/Microsoft.Quantum.Xunit.nuspec @@ -22,7 +22,7 @@ - + From 0b074694629853cdc9a2001756f773f29cbb170b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 7 Jul 2021 13:29:54 -0700 Subject: [PATCH 141/145] Fixed test cases. --- .../TestCases/FullStateDriverGenerator/UseBoolArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseDoubleArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseIntegerArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseMiscArgs.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseNoArgs.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UsePauliArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseRangeArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseResultArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp | 2 +- .../TestCases/FullStateDriverGenerator/UseStringArg.cpp | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp index e1ea3cc80c4..c7d4e5c5806 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp @@ -39,7 +39,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp index 3b1c27e9881..20356a2a536 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp index 9b847e44b1e..fdee7680b61 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp @@ -29,7 +29,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp index ee753a6c3f6..a171287a3ad 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp @@ -54,7 +54,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp index b9b18b6235c..57e6493971f 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp @@ -29,7 +29,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp index 0eb3b81b596..5445c51b136 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp @@ -54,7 +54,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp index b0477cdb41f..f8246aca5b0 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp @@ -104,7 +104,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp index 94da475abcc..b4d70bf263b 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp @@ -28,7 +28,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp index 6695c31bbbf..f512ea18504 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp @@ -42,7 +42,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp index 01558e453bd..e8a18e06d0d 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp @@ -67,7 +67,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp index 6c2bedc708f..c0fae41a14f 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp @@ -60,7 +60,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp index 249090ed143..aae5780698a 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp @@ -95,7 +95,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp index 12d5aedb661..c3fa773f201 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -39,7 +39,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp index b89c1b380b9..7d1b992b905 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp index 9caaeddbc23..3063ea96f06 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp @@ -35,7 +35,7 @@ int main(int argc, char* argv[]) { CLI::App app("QIR Standalone Entry Point"); - // Initialize simulator. + // Initialize runtime. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); From 5f4636e4a260ea9632fa13581dd01d7da32267be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 7 Jul 2021 22:24:35 -0700 Subject: [PATCH 142/145] Remove custom utils from Microsoft.Quantum.Qir.Tools package that would be public and do not need to. --- .../LoggerTests.cs | 108 ------------------ .../QirExecutableGeneratorTests.cs | 3 +- .../QirExecutableTests.cs | 3 +- .../Execution/Tools/Executable/ClangClient.cs | 10 +- .../Tools/Executable/QirExecutable.cs | 20 ++-- .../Executable/QirExecutableGenerator.cs | 14 ++- .../Executable/QirFullStateExecutable.cs | 6 +- .../Executable/QuantumExecutableRunner.cs | 12 +- .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 1 + src/Qir/Execution/Tools/Utility/Clock.cs | 12 -- src/Qir/Execution/Tools/Utility/IClock.cs | 15 --- src/Qir/Execution/Tools/Utility/ILogger.cs | 38 ------ src/Qir/Execution/Tools/Utility/Logger.cs | 47 -------- 13 files changed, 39 insertions(+), 250 deletions(-) delete mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs delete mode 100644 src/Qir/Execution/Tools/Utility/Clock.cs delete mode 100644 src/Qir/Execution/Tools/Utility/IClock.cs delete mode 100644 src/Qir/Execution/Tools/Utility/ILogger.cs delete mode 100644 src/Qir/Execution/Tools/Utility/Logger.cs diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs deleted file mode 100644 index 85df2dcc7bd..00000000000 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/LoggerTests.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using Microsoft.Quantum.Qir.Utility; -using Moq; -using Xunit; - -namespace Tests.Microsoft.Quantum.Qir.Tools -{ - public class LoggerTests - { - private readonly Mock clockMock; - private readonly Logger logger; - - public LoggerTests() - { - clockMock = new Mock(); - logger = new Logger(clockMock.Object); - } - - // N.B. Since the logger is meant for internal use, these tests do not verify whether the logger produced a - // specific output. Instead it is verified that the produced output contains certain elements. - [Fact] - public void TestLogInfo() - { - using var consoleOutput = new StringWriter(); - var message = "some message"; - var time = DateTimeOffset.MinValue; - clockMock.SetupGet(obj => obj.Now).Returns(time); - Console.SetOut(consoleOutput); - logger.LogInfo(message); - var actualLog = consoleOutput.ToString(); - - // Verify that the expected elements are present in the produced output. - Assert.Contains(time.ToString(), actualLog); - Assert.Contains("INFO", actualLog); - Assert.Contains(message, actualLog); - Assert.EndsWith(Environment.NewLine, actualLog); - } - - [Fact] - public void TestLogError() - { - using var consoleOutput = new StringWriter(); - var message = "some message"; - var time = DateTimeOffset.MinValue; - clockMock.SetupGet(obj => obj.Now).Returns(time); - Console.SetOut(consoleOutput); - logger.LogError(message); - var actualLog = consoleOutput.ToString(); - - // Verify that the expected elements are present in the produced output. - Assert.Contains(time.ToString(), actualLog); - Assert.Contains("ERROR", actualLog); - Assert.Contains(message, actualLog); - Assert.EndsWith(Environment.NewLine, actualLog); - } - - [Fact] - public void TestLogExceptionWithoutStackTrace() - { - using var consoleOutput = new StringWriter(); - var time = DateTimeOffset.MinValue; - clockMock.SetupGet(obj => obj.Now).Returns(time); - var exception = new InvalidOperationException(); - Console.SetOut(consoleOutput); - logger.LogException(exception); - var actualLog = consoleOutput.ToString(); - - // Verify that the expected elements are present in the produced output. - Assert.Contains(time.ToString(), actualLog); - Assert.Contains("ERROR", actualLog); - Assert.Contains(exception.Message, actualLog); - Assert.EndsWith(Environment.NewLine, actualLog); - } - - [Fact] - public void TestLogExceptionWithStackTrace() - { - using var consoleOutput = new StringWriter(); - var time = DateTimeOffset.MinValue; - clockMock.SetupGet(obj => obj.Now).Returns(time); - Exception exception; - try - { - throw new InvalidOperationException(); - } - // Throw exception to generate stack trace. - catch (Exception thrownException) - { - exception = thrownException; - } - - Console.SetOut(consoleOutput); - logger.LogException(exception); - var actualLog = consoleOutput.ToString(); - - // Verify that the expected elements are present in the produced output. - Assert.Contains(time.ToString(), actualLog); - Assert.Contains("ERROR", actualLog); - Assert.Contains(exception.Message, actualLog); - Assert.Contains(exception.StackTrace, actualLog); - Assert.EndsWith(Environment.NewLine, actualLog); - } - } -} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs index 2a51b7c71a9..61af04407e8 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Qir.Tools.Executable; -using Microsoft.Quantum.Qir.Utility; using Moq; using Xunit; @@ -28,7 +27,7 @@ public class QirExecutableGeneratorTests : IDisposable public QirExecutableGeneratorTests() { clangClientMock = new Mock(); - executableGenerator = new QirExecutableGenerator(clangClientMock.Object, Mock.Of()); + executableGenerator = new QirExecutableGenerator(clangClientMock.Object, null); // Set up files. var prefix = Guid.NewGuid().ToString(); diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs index 95f5f9a666b..c838efaa0d5 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -9,7 +9,6 @@ using Microsoft.Quantum.Qir.Serialization; using Microsoft.Quantum.Qir.Tools.Driver; using Microsoft.Quantum.Qir.Tools.Executable; -using Microsoft.Quantum.Qir.Utility; using Moq; using Xunit; @@ -47,7 +46,7 @@ public QirExecutableTests() driverGeneratorMock = new Mock(); executableGeneratorMock = new Mock(); runnerMock = new Mock(); - qirExecutable = new Mock(executableFile, qirBytecode, Mock.Of(), driverGeneratorMock.Object, executableGeneratorMock.Object, runnerMock.Object) { CallBase = true }; + qirExecutable = new Mock(executableFile, qirBytecode, driverGeneratorMock.Object, executableGeneratorMock.Object, runnerMock.Object, null) { CallBase = true }; linkLibraries = new List { "lib1", "lib2" }; headerDirectories = new List(); libraryDirectories = new List(); diff --git a/src/Qir/Execution/Tools/Executable/ClangClient.cs b/src/Qir/Execution/Tools/Executable/ClangClient.cs index a8e74f2a404..4f4fca743b8 100644 --- a/src/Qir/Execution/Tools/Executable/ClangClient.cs +++ b/src/Qir/Execution/Tools/Executable/ClangClient.cs @@ -5,7 +5,9 @@ using System.Diagnostics; using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Utility; +using Microsoft.Extensions.Logging; + +#nullable enable namespace Microsoft.Quantum.Qir.Tools.Executable { @@ -14,9 +16,9 @@ internal class ClangClient : IClangClient private const string LinkFlag = " -l "; private const string LibraryPathFlag = " -L "; private const string IncludePathFlag = " -I "; - private readonly ILogger logger; + private readonly ILogger? logger; - public ClangClient(ILogger logger) + public ClangClient(ILogger? logger) { this.logger = logger; } @@ -30,7 +32,7 @@ public async Task CreateExecutableAsync(string[] inputFiles, string[] linkedLibr var libraryPathsArg = $"{LibraryPathFlag} {string.Join(LibraryPathFlag, libraryPaths)}"; var includePathsArg = $"{IncludePathFlag} {string.Join(IncludePathFlag, includePaths)}"; var arguments = $"{inputsArg} {includePathsArg} {libraryPathsArg} {linkedLibrariesArg} -o {outputPath} -std=c++17 -v"; - logger?.LogInfo($"Invoking clang with the following arguments: {arguments}"); + logger?.LogInformation($"Invoking clang with the following arguments: {arguments}"); var taskCompletionSource = new TaskCompletionSource(); using var process = new Process(); AddPathsToEnvironmentVariable("DYLD_LIBRARY_PATH", libraryPaths); diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs index 118fef8ed9c..985404dfc55 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -5,9 +5,11 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Microsoft.Quantum.Qir.Serialization; using Microsoft.Quantum.Qir.Tools.Driver; -using Microsoft.Quantum.Qir.Utility; + +#nullable enable namespace Microsoft.Quantum.Qir.Tools.Executable { @@ -28,22 +30,22 @@ public abstract class QirExecutable : IQirExecutable protected FileInfo ExecutableFile { get; } private readonly byte[] qirBitcode; - private readonly ILogger logger; + private readonly ILogger? logger; private readonly IQuantumExecutableRunner runner; private readonly IQirDriverGenerator driverGenerator; private readonly IQirExecutableGenerator executableGenerator; - public QirExecutable(FileInfo executableFile, byte[] qirBitcode, IQirDriverGenerator driverGenerator, ILogger logger = null) + public QirExecutable(FileInfo executableFile, byte[] qirBitcode, IQirDriverGenerator driverGenerator, ILogger? logger = null) : this(executableFile, qirBitcode, - logger ?? new Logger(new Clock()), driverGenerator, new QirExecutableGenerator(new ClangClient(logger), logger), - new QuantumExecutableRunner(logger)) + new QuantumExecutableRunner(logger), + logger) { } - internal QirExecutable(FileInfo executableFile, byte[] qirBitcode, ILogger logger, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner runner) + internal QirExecutable(FileInfo executableFile, byte[] qirBitcode, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner runner, ILogger? logger) { ExecutableFile = executableFile; this.qirBitcode = qirBitcode; @@ -62,7 +64,7 @@ public async Task BuildAsync(EntryPointOperation entryPoint, IList { var binDirectory = executableFile.Directory; - logger?.LogInfo($"Creating binary directory at {binDirectory.FullName}."); + logger?.LogInformation($"Creating binary directory at {binDirectory.FullName}."); executableFile.Directory.Create(); // Copy all library contents to bin. - logger?.LogInfo("Copying library directories into the executable's folder."); + logger?.LogInformation("Copying library directories into the executable's folder."); if (!sourceDirectory.Exists) { @@ -76,7 +78,7 @@ private void CopyFileIfNotExists(FileInfo fileToCopy, DirectoryInfo destinationD if (!File.Exists(newPath)) { var newFile = fileToCopy.CopyTo(newPath); - logger?.LogInfo($"Copied file {fileToCopy.FullName} to {newFile.FullName}"); + logger?.LogInformation($"Copied file {fileToCopy.FullName} to {newFile.FullName}"); } } diff --git a/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs b/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs index 0f38107394e..4c4328ef34f 100644 --- a/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirFullStateExecutable.cs @@ -6,8 +6,10 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; +using Microsoft.Extensions.Logging; using Microsoft.Quantum.Qir.Tools.Driver; -using Microsoft.Quantum.Qir.Utility; + +#nullable enable namespace Microsoft.Quantum.Qir.Tools.Executable { @@ -28,7 +30,7 @@ public class QirFullStateExecutable : QirExecutable public override IList LibraryDirectories { get; } = new List(); - public QirFullStateExecutable(FileInfo executableFile, byte[] qirBitcode, ILogger logger = null) + public QirFullStateExecutable(FileInfo executableFile, byte[] qirBitcode, ILogger? logger = null) : base(executableFile, qirBitcode, new QirFullStateDriverGenerator(), diff --git a/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs b/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs index 987d6212799..ba6b5d85331 100644 --- a/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs +++ b/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs @@ -4,22 +4,24 @@ using System.Diagnostics; using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.Qir.Utility; +using Microsoft.Extensions.Logging; + +#nullable enable namespace Microsoft.Quantum.Qir.Tools.Executable { internal class QuantumExecutableRunner : IQuantumExecutableRunner { - private readonly ILogger logger; + private readonly ILogger? logger; - public QuantumExecutableRunner(ILogger logger) + public QuantumExecutableRunner(ILogger? logger) { this.logger = logger; } public async Task RunExecutableAsync(FileInfo executableFile, Stream stream, string arguments) { - logger.LogInfo($"Invoking executable {executableFile.FullName} with the following arguments: {arguments}"); + logger?.LogInformation($"Invoking executable {executableFile.FullName} with the following arguments: {arguments}"); using var process = new Process(); process.StartInfo = new ProcessStartInfo { @@ -34,7 +36,7 @@ public async Task RunExecutableAsync(FileInfo executableFile, Stream stream, str process.WaitForExit(); using var streamWriter = new StreamWriter(stream); await streamWriter.WriteAsync(output); - logger.LogInfo($"Executable has finished running. Result code: {process.ExitCode}"); + logger?.LogInformation($"Executable has finished running. Result code: {process.ExitCode}"); } } } diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index d5c150b132f..5b15362c7dc 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Qir/Execution/Tools/Utility/Clock.cs b/src/Qir/Execution/Tools/Utility/Clock.cs deleted file mode 100644 index 7f1fdc8c78e..00000000000 --- a/src/Qir/Execution/Tools/Utility/Clock.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.Quantum.Qir.Utility -{ - public class Clock : IClock - { - public DateTimeOffset Now => DateTimeOffset.Now; - } -} diff --git a/src/Qir/Execution/Tools/Utility/IClock.cs b/src/Qir/Execution/Tools/Utility/IClock.cs deleted file mode 100644 index da69204b74a..00000000000 --- a/src/Qir/Execution/Tools/Utility/IClock.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.Quantum.Qir.Utility -{ - /// - /// Mockable clock interface. - /// - public interface IClock - { - public DateTimeOffset Now { get; } - } -} diff --git a/src/Qir/Execution/Tools/Utility/ILogger.cs b/src/Qir/Execution/Tools/Utility/ILogger.cs deleted file mode 100644 index 075fc708947..00000000000 --- a/src/Qir/Execution/Tools/Utility/ILogger.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.Quantum.Qir.Utility -{ - /// - /// Logger for internal traces and errors. - /// - /// For now, this thinly wraps console logging. In the future, this might be extended to log to files or other systems. - public interface ILogger - { - /// - /// Logs a message at the "information" level. - /// - /// Message to log. - void LogInfo(string message); - - /// - /// Logs a message at the "warning" level. - /// - /// Message to log. - void LogWarning(string message); - - /// - /// Logs a message at the "error" level. - /// - /// Message to log. - void LogError(string message); - - /// - /// Formats an exception into an error log. Logs the exception type, message, and stack trace. - /// - /// Exception to log. - void LogException(Exception e); - } -} diff --git a/src/Qir/Execution/Tools/Utility/Logger.cs b/src/Qir/Execution/Tools/Utility/Logger.cs deleted file mode 100644 index e5f2fe5b107..00000000000 --- a/src/Qir/Execution/Tools/Utility/Logger.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.Quantum.Qir.Utility -{ - public class Logger : ILogger - { - private readonly IClock clock; - - public Logger(IClock clock) - { - this.clock = clock; - } - - // {timestamp} [{log level}]: {message}. - private const string LogFormat = "{0} [{1}]: {2}"; - - // ...{exception type}: {exception message}{Environment.NewLine}{stack trace}. - private const string ExceptionMessageFormat = "Exception encountered: {0}: {1}{2}{3}"; - private const string InfoLevel = "INFO"; - private const string WarningLevel = "WARNING"; - private const string ErrorLevel = "ERROR"; - - public void LogInfo(string message) - { - Console.WriteLine(LogFormat, clock.Now, InfoLevel, message); - } - - public void LogWarning(string message) - { - Console.WriteLine(LogFormat, clock.Now, WarningLevel, message); - } - - public void LogError(string message) - { - Console.WriteLine(LogFormat, clock.Now, ErrorLevel, message); - } - - public void LogException(Exception e) - { - var message = string.Format(ExceptionMessageFormat, e.GetType(), e.Message, Environment.NewLine, e.StackTrace); - LogError(message); - } - } -} From ae3b3e127ed736e81ca69631619fae78248fb175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 8 Jul 2021 01:26:58 -0700 Subject: [PATCH 143/145] Addressed more feedback from Dmitry. --- .../Tests.Microsoft.Quantum.Qir.Tools/Util.cs | 13 ++++--------- .../Tools/Executable/QirExecutableGenerator.cs | 4 ++-- src/Qir/Execution/Tools/QirTools.cs | 12 +++++------- .../Submitters/IQuantumMachineExecutionContext.cs | 2 +- src/Simulation/EntryPointDriver/Azure/Azure.cs | 10 +++++----- src/Simulation/EntryPointDriver/Driver.cs | 2 +- 6 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs index 011e3643ac2..e5e81c30241 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs @@ -38,20 +38,15 @@ public static bool CompareStreams(Stream streamA, Stream streamB) public static FileInfo CreateBinaryFile(DirectoryInfo directory, string fileName, byte[] contents) { - var filePath = Path.Combine(directory.FullName, fileName); - var fileInfo = new FileInfo(filePath); - using var fileStream = fileInfo.OpenWrite(); - fileStream.Write(contents); + var fileInfo = new FileInfo(Path.Combine(directory.FullName, fileName)); + File.WriteAllBytes(fileInfo.FullName, contents); return fileInfo; } public static FileInfo CreateTextFile(DirectoryInfo directory, string fileName, string contents) { - var filePath = Path.Combine(directory.FullName, fileName); - var fileInfo = new FileInfo(filePath); - using var fileStream = fileInfo.OpenWrite(); - using var streamWriter = new StreamWriter(fileStream); - streamWriter.Write(contents); + var fileInfo = new FileInfo(Path.Combine(directory.FullName, fileName)); + File.WriteAllText(fileInfo.FullName, contents); return fileInfo; } } diff --git a/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs index 8ef8c488adc..6db49cb64a9 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutableGenerator.cs @@ -49,7 +49,7 @@ await Task.Run(async () => } else { - CopyDirectoryContents(dir, binDirectory); + CopyDirectoryFilesIfNotExist(dir, binDirectory); libDirs.Add(dir.FullName); } } @@ -82,7 +82,7 @@ private void CopyFileIfNotExists(FileInfo fileToCopy, DirectoryInfo destinationD } } - private void CopyDirectoryContents(DirectoryInfo directoryToCopy, DirectoryInfo destinationDirectory) + private void CopyDirectoryFilesIfNotExist(DirectoryInfo directoryToCopy, DirectoryInfo destinationDirectory) { FileInfo[] files = directoryToCopy.GetFiles(); foreach (var file in files) diff --git a/src/Qir/Execution/Tools/QirTools.cs b/src/Qir/Execution/Tools/QirTools.cs index 1b1990c3f95..e80c18d4275 100644 --- a/src/Qir/Execution/Tools/QirTools.cs +++ b/src/Qir/Execution/Tools/QirTools.cs @@ -18,7 +18,7 @@ namespace Microsoft.Quantum.Qir.Tools public static class QirTools { /// - /// Creates a QIR-based executable from a .NET DLL generated by the Q# compiler. + /// Creates QIR-based executables from a .NET DLL generated by the Q# compiler. /// /// .NET DLL generated by the Q# compiler. /// Directory where the libraries to link to are located. @@ -35,12 +35,10 @@ public static async Task BuildFromQSharpDll( { throw new ArgumentException("The given DLL does not contain QIR bitcode."); } - - if (!executablesDirectory.Exists) - { - executablesDirectory.Create(); - } - + + executablesDirectory.Create(); + + // Concurrently build an executable for each entry point operation. var tasks = EntryPointLoader.LoadEntryPointOperations(qsharpDll).Select(entryPointOp => { var exeFileInfo = new FileInfo(Path.Combine(executablesDirectory.FullName, $"{entryPointOp.Name}.exe")); diff --git a/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs b/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs index 2b70bba8678..9a7924929fa 100644 --- a/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs +++ b/src/Simulation/Core/Submitters/IQuantumMachineExecutionContext.cs @@ -8,7 +8,7 @@ namespace Microsoft.Quantum.Runtime /// /// Interface to provide configuration details to manage execution. /// - [Obsolete("No longer used.")] + [Obsolete("No longer used. Some of these options might be supported in the future by the SubmissionOptions class.")] public interface IQuantumMachineExecutionContext { /// diff --git a/src/Simulation/EntryPointDriver/Azure/Azure.cs b/src/Simulation/EntryPointDriver/Azure/Azure.cs index 3dbae6a96c8..0b58729ae77 100644 --- a/src/Simulation/EntryPointDriver/Azure/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure/Azure.cs @@ -34,7 +34,7 @@ public static class Azure public static Task Submit( AzureSettings settings, QSharpSubmission qsSubmission, QirSubmission? qirSubmission) { - Log(settings, settings.ToString()); + LogIfVerbose(settings, settings.ToString()); if ((settings.Location is null) && (settings.BaseUri is null)) { @@ -83,7 +83,7 @@ public static Task Submit( private static async Task SubmitQSharpMachine( AzureSettings settings, IQuantumMachine machine, QSharpSubmission submission) { - Log(settings, "Submitting Q# entry point using a quantum machine."); + LogIfVerbose(settings, "Submitting Q# entry point using a quantum machine."); if (settings.DryRun) { @@ -111,7 +111,7 @@ private static async Task SubmitQSharpMachine( private static async Task SubmitQSharp( AzureSettings settings, IQSharpSubmitter submitter, QSharpSubmission submission) { - Log(settings, "Submitting Q# entry point."); + LogIfVerbose(settings, "Submitting Q# entry point."); if (settings.DryRun) { @@ -133,7 +133,7 @@ private static async Task SubmitQSharp( private static async Task SubmitQir( AzureSettings settings, IQirSubmitter submitter, QirSubmission submission) { - Log(settings, "Submitting QIR entry point."); + LogIfVerbose(settings, "Submitting QIR entry point."); if (settings.DryRun) { @@ -248,7 +248,7 @@ private static void DisplayError(string summary, string? message) /// /// The Azure Quantum submission settings. /// The message. - private static void Log(AzureSettings settings, string message) + private static void LogIfVerbose(AzureSettings settings, string message) { if (settings.Verbose) { diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 077ff710df2..6533d034506 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -95,7 +95,7 @@ public sealed class Driver /// The job name option. /// private static readonly OptionInfo JobNameOption = new OptionInfo( - ImmutableList.Create("--job-name"), "", "The name of the submitted job."); + ImmutableList.Create("--job-name"), string.Empty, "The name of the submitted job."); /// /// The shots option. From b938c448eab13d96f39145afa07efa455ac9c2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 8 Jul 2021 03:12:17 -0700 Subject: [PATCH 144/145] Rename interface and class for consistency. --- .../Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs | 4 ++-- ...{IQuantumExecutableRunner.cs => IQirExecutableRunner.cs} | 4 ++-- src/Qir/Execution/Tools/Executable/QirExecutable.cs | 6 +++--- .../{QuantumExecutableRunner.cs => QirExecutableRunner.cs} | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename src/Qir/Execution/Tools/Executable/{IQuantumExecutableRunner.cs => IQirExecutableRunner.cs} (83%) rename src/Qir/Execution/Tools/Executable/{QuantumExecutableRunner.cs => QirExecutableRunner.cs} (91%) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs index c838efaa0d5..6ab9b829604 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs @@ -22,7 +22,7 @@ public class QirExecutableTests : IDisposable private readonly DirectoryInfo binDirectory; private readonly Mock driverGeneratorMock; private readonly Mock executableGeneratorMock; - private readonly Mock runnerMock; + private readonly Mock runnerMock; private readonly Mock qirExecutable; private readonly FileInfo executableFile; private readonly byte[] qirBytecode = { 1, 2, 3, 4, 5 }; @@ -45,7 +45,7 @@ public QirExecutableTests() executableFile = new FileInfo(Path.Combine(binDirectory.FullName, "executable")); driverGeneratorMock = new Mock(); executableGeneratorMock = new Mock(); - runnerMock = new Mock(); + runnerMock = new Mock(); qirExecutable = new Mock(executableFile, qirBytecode, driverGeneratorMock.Object, executableGeneratorMock.Object, runnerMock.Object, null) { CallBase = true }; linkLibraries = new List { "lib1", "lib2" }; headerDirectories = new List(); diff --git a/src/Qir/Execution/Tools/Executable/IQuantumExecutableRunner.cs b/src/Qir/Execution/Tools/Executable/IQirExecutableRunner.cs similarity index 83% rename from src/Qir/Execution/Tools/Executable/IQuantumExecutableRunner.cs rename to src/Qir/Execution/Tools/Executable/IQirExecutableRunner.cs index 292cb394737..7f2b4766ab2 100644 --- a/src/Qir/Execution/Tools/Executable/IQuantumExecutableRunner.cs +++ b/src/Qir/Execution/Tools/Executable/IQirExecutableRunner.cs @@ -6,10 +6,10 @@ namespace Microsoft.Quantum.Qir.Tools.Executable { - internal interface IQuantumExecutableRunner + internal interface IQirExecutableRunner { /// - /// Runs a quantum program executable with the given arguments. + /// Runs a QIR executable with the given arguments. /// /// Location of the executable to run. /// Stream to write program output. diff --git a/src/Qir/Execution/Tools/Executable/QirExecutable.cs b/src/Qir/Execution/Tools/Executable/QirExecutable.cs index 985404dfc55..9400c58b912 100644 --- a/src/Qir/Execution/Tools/Executable/QirExecutable.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutable.cs @@ -31,7 +31,7 @@ public abstract class QirExecutable : IQirExecutable private readonly byte[] qirBitcode; private readonly ILogger? logger; - private readonly IQuantumExecutableRunner runner; + private readonly IQirExecutableRunner runner; private readonly IQirDriverGenerator driverGenerator; private readonly IQirExecutableGenerator executableGenerator; @@ -40,12 +40,12 @@ public QirExecutable(FileInfo executableFile, byte[] qirBitcode, IQirDriverGener qirBitcode, driverGenerator, new QirExecutableGenerator(new ClangClient(logger), logger), - new QuantumExecutableRunner(logger), + new QirExecutableRunner(logger), logger) { } - internal QirExecutable(FileInfo executableFile, byte[] qirBitcode, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQuantumExecutableRunner runner, ILogger? logger) + internal QirExecutable(FileInfo executableFile, byte[] qirBitcode, IQirDriverGenerator driverGenerator, IQirExecutableGenerator executableGenerator, IQirExecutableRunner runner, ILogger? logger) { ExecutableFile = executableFile; this.qirBitcode = qirBitcode; diff --git a/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs b/src/Qir/Execution/Tools/Executable/QirExecutableRunner.cs similarity index 91% rename from src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs rename to src/Qir/Execution/Tools/Executable/QirExecutableRunner.cs index ba6b5d85331..ea1a0d5a47f 100644 --- a/src/Qir/Execution/Tools/Executable/QuantumExecutableRunner.cs +++ b/src/Qir/Execution/Tools/Executable/QirExecutableRunner.cs @@ -10,11 +10,11 @@ namespace Microsoft.Quantum.Qir.Tools.Executable { - internal class QuantumExecutableRunner : IQuantumExecutableRunner + internal class QirExecutableRunner : IQirExecutableRunner { private readonly ILogger? logger; - public QuantumExecutableRunner(ILogger? logger) + public QirExecutableRunner(ILogger? logger) { this.logger = logger; } From f64ece98fb881a0e58a250f69ec6e383b3632076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 8 Jul 2021 03:24:57 -0700 Subject: [PATCH 145/145] Renamed folder for consitency. --- Simulation.sln | 2 +- .../QirDriverGeneratorTests.cs | 0 .../QirExecutableGeneratorTests.cs | 0 .../QirExecutableTests.cs | 0 .../TestCases/FullStateDriverGenerator/UseBoolArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseDoubleArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseIntegerArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseMiscArgs.cpp | 0 .../TestCases/FullStateDriverGenerator/UseNoArgs.cpp | 0 .../TestCases/FullStateDriverGenerator/UsePauliArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseRangeArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseResultArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp | 0 .../TestCases/FullStateDriverGenerator/UseStringArg.cpp | 0 .../Tests.Microsoft.Quantum.Qir.Tools.csproj | 0 .../{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/Util.cs | 0 21 files changed, 1 insertion(+), 1 deletion(-) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/QirDriverGeneratorTests.cs (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/QirExecutableGeneratorTests.cs (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/QirExecutableTests.cs (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseBoolArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseNoArgs.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UsePauliArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseRangeArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseResultArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/TestCases/FullStateDriverGenerator/UseStringArg.cpp (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/Tests.Microsoft.Quantum.Qir.Tools.csproj (100%) rename src/Qir/Execution/{Tests.Microsoft.Quantum.Qir.Tools => Tools.Tests}/Util.cs (100%) diff --git a/Simulation.sln b/Simulation.sln index ad0c19a1e7f..5d4f6e60d76 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -107,7 +107,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Execution", "Execution", "{ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools\Microsoft.Quantum.Qir.Tools.csproj", "{C60226E3-98DE-4E92-AED4-B4A93D4CA063}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tests.Microsoft.Quantum.Qir.Tools\Tests.Microsoft.Quantum.Qir.Tools.csproj", "{4794FC80-4594-403F-AFEC-4889EFE87EA0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Microsoft.Quantum.Qir.Tools", "src\Qir\Execution\Tools.Tests\Tests.Microsoft.Quantum.Qir.Tools.csproj", "{4794FC80-4594-403F-AFEC-4889EFE87EA0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirExe", "src\Simulation\Simulators.Tests\TestProjects\QirExe\QirExe.csproj", "{A0B98D0E-FC28-4FD8-8806-4825B9F5489D}" EndProject diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tools.Tests/QirDriverGeneratorTests.cs similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs rename to src/Qir/Execution/Tools.Tests/QirDriverGeneratorTests.cs diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs b/src/Qir/Execution/Tools.Tests/QirExecutableGeneratorTests.cs similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableGeneratorTests.cs rename to src/Qir/Execution/Tools.Tests/QirExecutableGeneratorTests.cs diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs b/src/Qir/Execution/Tools.Tests/QirExecutableTests.cs similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirExecutableTests.cs rename to src/Qir/Execution/Tools.Tests/QirExecutableTests.cs diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseBoolArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseBoolArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseNoArgs.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseNoArgs.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UsePauliArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UsePauliArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseRangeArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseRangeArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseResultArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseResultArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp b/src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseStringArg.cpp similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp rename to src/Qir/Execution/Tools.Tests/TestCases/FullStateDriverGenerator/UseStringArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools.Tests/Tests.Microsoft.Quantum.Qir.Tools.csproj similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj rename to src/Qir/Execution/Tools.Tests/Tests.Microsoft.Quantum.Qir.Tools.csproj diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs b/src/Qir/Execution/Tools.Tests/Util.cs similarity index 100% rename from src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Util.cs rename to src/Qir/Execution/Tools.Tests/Util.cs