Repository: microsoft/qsharp
Pull request #1523 (2024-05-14 18:09:19)

Use RCA based code generation for all scenarios
new QSC option:
```
  -p, --profile <PROFILE>
          Target QIR profile for code generation

          Possible values:
          - unrestricted: This is the default profile, which allows all operations
          - base:         This profile restricts the set of operations to those that are supported by the Base profile
          - adaptive-ri:  This profile restricts the set of operations to those that are supported by the AdaptiveRI profile
```

github-actions[bot]: ## Benchmark for d09ed47
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| Array append evaluation | 341.8±2.90µs | 343.1±2.14µs | +0.38% |
| Array literal evaluation | 171.2±1.96µs | 170.5±0.97µs | -0.41% |
| Array update evaluation | 427.3±10.96µs | 428.2±4.35µs | +0.21% |
| Core + Standard library compilation | 20.7±1.59ms | 20.3±1.53ms | -1.93% |
| Deutsch-Jozsa evaluation | **5.0±0.05ms** | 5.1±0.04ms | **+2.00%** |
| Large file parity evaluation | 34.4±0.14ms | 34.4±0.32ms | 0.00% |
| Large input file compilation | 13.7±0.96ms | 13.8±0.97ms | +0.73% |
| Large input file compilation (interpreter) | 50.8±2.35ms | 52.0±3.19ms | +2.36% |
| Large nested iteration | 33.5±0.37ms | 33.6±0.15ms | +0.30% |
| Perform Runtime Capabilities Analysis (RCA) on Deutsch-Jozsa sample | 1635.1±152.62µs | 1642.5±195.13µs | +0.45% |
| Perform Runtime Capabilities Analysis (RCA) on large file sample | 8.4±0.20ms | 8.5±0.45ms | +1.19% |
| Perform Runtime Capabilities Analysis (RCA) on teleport sample | 1486.9±149.86µs | 1504.6±215.66µs | +1.19% |
| Perform Runtime Capabilities Analysis (RCA) on the core and std libraries | 29.0±0.61ms | 29.2±0.59ms | +0.69% |
| Teleport evaluation | 87.6±3.72µs | 88.0±3.85µs | +0.46% |

  </details>
  
github-actions[bot]: ## Benchmark for 70916c3
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| Array append evaluation | **346.9±11.16µs** | 377.5±1.31µs | **+8.82%** |
| Array literal evaluation | **189.8±1.36µs** | 192.3±0.75µs | **+1.32%** |
| Array update evaluation | **429.5±4.83µs** | 445.0±2.90µs | **+3.61%** |
| Core + Standard library compilation | 17.6±0.55ms | 17.9±0.84ms | +1.70% |
| Deutsch-Jozsa evaluation | **5.0±0.05ms** | 5.1±0.13ms | **+2.00%** |
| Large file parity evaluation | 33.9±0.15ms | 33.8±0.31ms | -0.29% |
| Large input file compilation | 12.8±0.61ms | **11.8±0.27ms** | **-7.81%** |
| Large input file compilation (interpreter) | **47.4±2.12ms** | 50.6±1.36ms | **+6.75%** |
| Large nested iteration | **34.2±1.68ms** | 35.4±0.47ms | **+3.51%** |
| Perform Runtime Capabilities Analysis (RCA) on Deutsch-Jozsa sample | 1587.8±89.94µs | 1544.6±97.97µs | -2.72% |
| Perform Runtime Capabilities Analysis (RCA) on large file sample | 8.3±0.15ms | **8.1±0.21ms** | **-2.41%** |
| Perform Runtime Capabilities Analysis (RCA) on teleport sample | 1430.8±60.78µs | 1399.4±61.97µs | -2.19% |
| Perform Runtime Capabilities Analysis (RCA) on the core and std libraries | 28.1±0.28ms | 28.0±0.40ms | -0.36% |
| Teleport evaluation | 87.4±3.73µs | 88.1±3.74µs | +0.80% |

  </details>
  
github-actions[bot]: ## Benchmark for 99b6716
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| Array append evaluation | 333.8±1.42µs | **327.4±7.09µs** | **-1.92%** |
| Array literal evaluation | 189.7±1.57µs | **168.9±1.35µs** | **-10.96%** |
| Array update evaluation | 411.3±1.42µs | **405.4±3.58µs** | **-1.43%** |
| Core + Standard library compilation | 22.8±1.46ms | **22.1±0.62ms** | **-3.07%** |
| Deutsch-Jozsa evaluation | **5.0±0.04ms** | 5.2±0.19ms | **+4.00%** |
| Large file parity evaluation | **34.2±0.09ms** | 34.5±0.09ms | **+0.88%** |
| Large input file compilation | 15.7±0.56ms | 16.1±1.03ms | +2.55% |
| Large input file compilation (interpreter) | 58.4±2.46ms | **53.3±1.72ms** | **-8.73%** |
| Large nested iteration | 33.0±0.19ms | **32.5±0.64ms** | **-1.52%** |
| Perform Runtime Capabilities Analysis (RCA) on Deutsch-Jozsa sample | 1689.8±177.16µs | 1693.2±214.29µs | +0.20% |
| Perform Runtime Capabilities Analysis (RCA) on large file sample | 8.8±0.19ms | 8.7±0.14ms | -1.14% |
| Perform Runtime Capabilities Analysis (RCA) on teleport sample | 1542.9±202.77µs | 1556.9±315.98µs | +0.91% |
| Perform Runtime Capabilities Analysis (RCA) on the core and std libraries | 29.5±0.28ms | 29.3±0.29ms | -0.68% |
| Teleport evaluation | 88.2±4.19µs | 90.9±8.32µs | +3.06% |

  </details>
  
github-actions[bot]: ## Benchmark for 28b0da9
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| Array append evaluation | **324.2±1.20µs** | 331.1±1.67µs | **+2.13%** |
| Array literal evaluation | **170.7±0.80µs** | 193.2±6.63µs | **+13.18%** |
| Array update evaluation | **404.7±0.97µs** | 412.5±3.07µs | **+1.93%** |
| Core + Standard library compilation | 20.2±0.74ms | 19.7±0.96ms | -2.48% |
| Deutsch-Jozsa evaluation | **5.0±0.05ms** | 5.1±0.05ms | **+2.00%** |
| Large file parity evaluation | **34.0±0.36ms** | 34.2±0.11ms | **+0.59%** |
| Large input file compilation | 13.3±0.51ms | 13.3±0.55ms | 0.00% |
| Large input file compilation (interpreter) | 50.0±1.25ms | 50.2±1.46ms | +0.40% |
| Large nested iteration | **32.3±0.20ms** | 32.6±0.24ms | **+0.93%** |
| Perform Runtime Capabilities Analysis (RCA) on Deutsch-Jozsa sample | 1591.2±86.26µs | 1585.8±78.15µs | -0.34% |
| Perform Runtime Capabilities Analysis (RCA) on large file sample | 7.9±0.09ms | 7.9±0.13ms | 0.00% |
| Perform Runtime Capabilities Analysis (RCA) on teleport sample | 1430.2±55.01µs | 1432.9±61.90µs | +0.19% |
| Perform Runtime Capabilities Analysis (RCA) on the core and std libraries | 28.0±0.82ms | 28.1±0.49ms | +0.36% |
| Teleport evaluation | 88.6±9.05µs | 90.5±8.39µs | +2.14% |

  </details>
  
github-actions[bot]: ## Benchmark for 96a96c3
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| Array append evaluation | 335.8±4.34µs | 336.6±4.03µs | +0.24% |
| Array literal evaluation | **189.7±1.09µs** | 191.9±3.77µs | **+1.16%** |
| Array update evaluation | 412.3±3.67µs | 414.4±8.81µs | +0.51% |
| Core + Standard library compilation | 20.5±0.87ms | 21.2±1.00ms | +3.41% |
| Deutsch-Jozsa evaluation | 5.0±0.05ms | 5.0±0.22ms | 0.00% |
| Large file parity evaluation | 34.1±0.78ms | 34.1±0.06ms | 0.00% |
| Large input file compilation | 13.6±0.35ms | 13.4±0.43ms | -1.47% |
| Large input file compilation (interpreter) | 50.2±1.65ms | 51.0±3.22ms | +1.59% |
| Large nested iteration | 32.9±0.51ms | 32.8±0.26ms | -0.30% |
| Perform Runtime Capabilities Analysis (RCA) on Deutsch-Jozsa sample | 1590.4±99.55µs | 1595.4±82.06µs | +0.31% |
| Perform Runtime Capabilities Analysis (RCA) on large file sample | 8.0±0.11ms | 7.9±0.10ms | -1.25% |
| Perform Runtime Capabilities Analysis (RCA) on teleport sample | 1444.4±78.92µs | 1448.6±109.42µs | +0.29% |
| Perform Runtime Capabilities Analysis (RCA) on the core and std libraries | **28.0±0.27ms** | 28.3±0.33ms | **+1.07%** |
| Teleport evaluation | 87.4±3.78µs | 88.2±3.64µs | +0.92% |

  </details>
  
github-actions[bot]: ## Benchmark for 8082d25
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| Array append evaluation | 336.1±4.52µs | **326.6±4.24µs** | **-2.83%** |
| Array literal evaluation | 189.8±0.78µs | **170.1±8.62µs** | **-10.38%** |
| Array update evaluation | 411.6±2.96µs | **405.2±5.19µs** | **-1.55%** |
| Core + Standard library compilation | 24.1±2.56ms | **20.5±0.94ms** | **-14.94%** |
| Deutsch-Jozsa evaluation | 5.1±0.08ms | 5.1±0.06ms | 0.00% |
| Large file parity evaluation | **34.2±0.10ms** | 34.4±0.33ms | **+0.58%** |
| Large input file compilation | 15.6±1.20ms | **13.7±0.40ms** | **-12.18%** |
| Large input file compilation (interpreter) | 53.4±2.84ms | **51.0±1.66ms** | **-4.49%** |
| Large nested iteration | 33.0±0.86ms | **32.3±0.21ms** | **-2.12%** |
| Perform Runtime Capabilities Analysis (RCA) on Deutsch-Jozsa sample | 1638.2±122.61µs | 1661.1±231.34µs | +1.40% |
| Perform Runtime Capabilities Analysis (RCA) on large file sample | 8.6±0.37ms | 8.5±0.31ms | -1.16% |
| Perform Runtime Capabilities Analysis (RCA) on teleport sample | 1513.3±250.87µs | 1485.6±109.37µs | -1.83% |
| Perform Runtime Capabilities Analysis (RCA) on the core and std libraries | 28.9±0.63ms | **28.3±0.46ms** | **-2.08%** |
| Teleport evaluation | 88.3±3.61µs | 91.3±4.02µs | +3.40% |

  </details>
  
github-actions[bot]: ## Benchmark for dd69774
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| Array append evaluation | 328.1±2.68µs | 326.8±4.25µs | -0.40% |
| Array literal evaluation | 173.9±1.20µs | **168.4±1.44µs** | **-3.16%** |
| Array update evaluation | 414.7±2.99µs | **405.7±4.12µs** | **-2.17%** |
| Core + Standard library compilation | 19.0±0.35ms | 18.7±0.36ms | -1.58% |
| Deutsch-Jozsa evaluation | 5.0±0.05ms | 5.0±0.05ms | 0.00% |
| Large file parity evaluation | **33.9±0.21ms** | 34.2±0.48ms | **+0.88%** |
| Large input file compilation | 12.4±0.20ms | 12.3±0.24ms | -0.81% |
| Large input file compilation (interpreter) | 49.2±1.66ms | **46.3±1.08ms** | **-5.89%** |
| Large nested iteration | 33.3±0.61ms | **32.1±0.16ms** | **-3.60%** |
| Perform Runtime Capabilities Analysis (RCA) on Deutsch-Jozsa sample | 1554.6±29.43µs | 1564.9±48.36µs | +0.66% |
| Perform Runtime Capabilities Analysis (RCA) on large file sample | 7.7±0.10ms | 7.7±0.08ms | 0.00% |
| Perform Runtime Capabilities Analysis (RCA) on teleport sample | 1418.0±35.11µs | 1420.9±44.17µs | +0.20% |
| Perform Runtime Capabilities Analysis (RCA) on the core and std libraries | 27.4±0.33ms | 27.5±0.70ms | +0.36% |
| Teleport evaluation | 88.1±3.66µs | 89.4±5.95µs | +1.48% |

  </details>
  

Patch:
diff --git a/compiler/qsc/src/bin/qsc.rs b/compiler/qsc/src/bin/qsc.rs
index 83bd128a..9dcfd733 100644
--- a/compiler/qsc/src/bin/qsc.rs
+++ b/compiler/qsc/src/bin/qsc.rs
@@ -6,14 +6,16 @@ allocator::assign_global!();
 use clap::{crate_version, ArgGroup, Parser, ValueEnum};
 use log::info;
 use miette::{Context, IntoDiagnostic, Report};
-use qsc::compile::compile;
-use qsc_codegen::qir_base;
+use qsc::hir::PackageId;
+use qsc::{compile::compile, PassContext};
+use qsc_codegen::qir::fir_to_qir;
 use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
 use qsc_frontend::{
     compile::{PackageStore, SourceContents, SourceMap, SourceName},
     error::WithSource,
 };
-use qsc_hir::hir::{Package, PackageId};
+use qsc_hir::hir::Package;
+use qsc_partial_eval::ProgramEntry;
 use qsc_passes::PackageType;
 use qsc_project::{FileSystem, Manifest, StdFs};
 use std::{
@@ -24,6 +26,28 @@ use std::{
     string::String,
 };
 
+#[derive(clap::ValueEnum, Clone, Debug, Default, PartialEq)]
+pub enum Profile {
+    /// This is the default profile, which allows all operations.
+    #[default]
+    Unrestricted,
+    /// This profile restricts the set of operations to those that are supported by the Base profile.
+    Base,
+    /// This profile restricts the set of operations to those that are supported by the AdaptiveRI profile.
+    AdaptiveRI,
+}
+
+// convert Profile into qsc::target::Profile
+impl From<Profile> for qsc::target::Profile {
+    fn from(profile: Profile) -> Self {
+        match profile {
+            Profile::Unrestricted => qsc::target::Profile::Unrestricted,
+            Profile::Base => qsc::target::Profile::Base,
+            Profile::AdaptiveRI => qsc::target::Profile::AdaptiveRI,
+        }
+    }
+}
+
 #[derive(Debug, Parser)]
 #[command(version = concat!(crate_version!(), " (", env!("QSHARP_GIT_HASH"), ")"), arg_required_else_help(false))]
 #[clap(group(ArgGroup::new("input").args(["entry", "sources"]).required(false).multiple(true)))]
@@ -48,6 +72,10 @@ struct Cli {
     #[arg(short, long)]
     entry: Option<String>,
 
+    /// Target QIR profile for code generation
+    #[arg(short, long)]
+    profile: Option<Profile>,
+
     /// Q# source files to compile, or `-` to read from stdin.
     #[arg()]
     sources: Vec<PathBuf>,
@@ -72,11 +100,12 @@ fn main() -> miette::Result<ExitCode> {
     let cli = Cli::parse();
     let mut store = PackageStore::new(qsc::compile::core());
     let mut dependencies = Vec::new();
-
-    let (package_type, capabilities) = if cli.emit.contains(&Emit::Qir) {
-        (PackageType::Exe, TargetCapabilityFlags::empty())
+    let profile: qsc::target::Profile = cli.profile.unwrap_or_default().into();
+    let capabilities = profile.into();
+    let package_type = if cli.emit.contains(&Emit::Qir) {
+        PackageType::Exe
     } else {
-        (PackageType::Lib, TargetCapabilityFlags::all())
+        PackageType::Lib
     };
 
     if !cli.nostdlib {
@@ -124,8 +153,21 @@ fn main() -> miette::Result<ExitCode> {
         match emit {
             Emit::Hir => emit_hir(&unit.package, out_dir)?,
             Emit::Qir => {
+                if package_type != PackageType::Exe {
+                    eprintln!("QIR generation is only supported for executable packages");
+                    return Ok(ExitCode::FAILURE);
+                }
+                if capabilities == TargetCapabilityFlags::all() {
+                    eprintln!("QIR generation is not supported for unrestricted profile");
+                    return Ok(ExitCode::FAILURE);
+                }
                 if errors.is_empty() {
-                    emit_qir(out_dir, &store, package_id)?;
+                    if let Err(reports) = emit_qir(out_dir, &store, package_id, capabilities) {
+                        for report in reports {
+                            eprintln!("{report:?}");
+                        }
+                        return Ok(ExitCode::FAILURE);
+                    }
                 }
             }
         }
@@ -172,11 +214,36 @@ fn emit_hir(package: &Package, dir: impl AsRef<Path>) -> miette::Result<()> {
         .with_context(|| format!("could not emit HIR file `{}`", path.display()))
 }
 
-fn emit_qir(out_dir: &Path, store: &PackageStore, package_id: PackageId) -> Result<(), Report> {
-    let path = out_dir.join("qir.ll");
-    let result = qir_base::generate_qir(store, package_id);
-    match result {
+fn emit_qir(
+    out_dir: &Path,
+    store: &PackageStore,
+    package_id: PackageId,
+    capabilities: TargetCapabilityFlags,
+) -> Result<(), Vec<Report>> {
+    let (fir_store, fir_package_id) = qsc_passes::lower_hir_to_fir(store, package_id);
+    let package = fir_store.get(fir_package_id);
+    let entry = ProgramEntry {
+        exec_graph: package.entry_exec_graph.clone(),
+        expr: (
+            fir_package_id,
+            package
+                .entry
+                .expect("package must have an entry expression"),
+        )
+            .into(),
+    };
+
+    let results = PassContext::run_fir_passes_on_fir(&fir_store, fir_package_id, capabilities);
+    if results.is_err() {
+        let errors = results.expect_err("should have errors");
+        let errors = errors.into_iter().map(Report::new).collect();
+        return Err(errors);
+    }
+    let compute_properties = results.expect("should have compute properties");
+
+    match fir_to_qir(&fir_store, capabilities, Some(compute_properties), &entry) {
         Ok(qir) => {
+            let path = out_dir.join("qir.ll");
             info!(
                 "Writing QIR output file to: {}",
                 path.to_str().unwrap_or_default()
@@ -184,10 +251,14 @@ fn emit_qir(out_dir: &Path, store: &PackageStore, package_id: PackageId) -> Resu
             fs::write(&path, qir)
                 .into_diagnostic()
                 .with_context(|| format!("could not emit QIR file `{}`", path.display()))
+                .map_err(|err| vec![err])
         }
-        Err((error, _)) => {
+        Err(error) => {
             let unit = store.get(package_id).expect("package should be in store");
-            Err(Report::new(WithSource::from_map(&unit.sources, error)))
+            Err(vec![Report::new(WithSource::from_map(
+                &unit.sources,
+                error,
+            ))])
         }
     }
 }
diff --git a/compiler/qsc/src/codegen.rs b/compiler/qsc/src/codegen.rs
index 80b893b2..7203f9c7 100644
--- a/compiler/qsc/src/codegen.rs
+++ b/compiler/qsc/src/codegen.rs
@@ -6,18 +6,23 @@ mod tests;
 
 use qsc_codegen::qir::fir_to_qir;
 use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
-use qsc_frontend::compile::{PackageStore, SourceMap};
+use qsc_frontend::{
+    compile::{PackageStore, SourceMap},
+    error::WithSource,
+};
 use qsc_partial_eval::ProgramEntry;
 use qsc_passes::{PackageType, PassContext};
-use qsc_rca::Analyzer;
 
-use crate::compile;
+use crate::{compile, interpret::Error};
 
 pub fn get_qir(
     sources: SourceMap,
     language_features: LanguageFeatures,
     capabilities: TargetCapabilityFlags,
-) -> Result<String, String> {
+) -> Result<String, Vec<Error>> {
+    if capabilities == TargetCapabilityFlags::all() {
+        return Err(vec![Error::UnsupportedRuntimeCapabilities]);
+    }
     let core = compile::core();
     let mut package_store = PackageStore::new(core);
     let std = compile::std(&package_store, capabilities);
@@ -34,15 +39,7 @@ pub fn get_qir(
 
     // Ensure it compiles before trying to add it to the store.
     if !errors.is_empty() {
-        // This will happen when QIR generation is attempted on a program that has errors.
-        // This can happen in the playground.
-        let mut error_message =
-            String::from("Failed to generate QIR. Could not compile sources.:\n");
-        for error in errors {
-            error_message.push_str(&format!("{error}\n"));
-        }
-
-        return Err(error_message);
+        return Err(errors.iter().map(|e| Error::Compile(e.clone())).collect());
     }
 
     let package_id = package_store.insert(unit);
@@ -59,20 +56,26 @@ pub fn get_qir(
             .into(),
     };
 
-    let compute_properties = if capabilities == TargetCapabilityFlags::empty() {
-        // baseprofchk already handled compliance, run the analyzer to get the compute properties.
-        let analyzer = Analyzer::init(&fir_store);
-        Ok(analyzer.analyze_all())
-    } else {
-        PassContext::run_fir_passes_on_fir(&fir_store, fir_package_id, capabilities)
-    };
-
-    let Ok(compute_properties) = compute_properties else {
-        // This should never happen, as the program should be checked for errors before trying to
-        // generate code for it. But just in case, simply report the failure.
-        return Err("Failed to generate QIR. Could not generate compute properties.".to_string());
-    };
+    let compute_properties =
+        PassContext::run_fir_passes_on_fir(&fir_store, fir_package_id, capabilities).map_err(
+            |errors| {
+                let source_package = package_store
+                    .get(package_id)
+                    .expect("package should be in store");
+                errors
+                    .iter()
+                    .map(|e| Error::Pass(WithSource::from_map(&source_package.sources, e.clone())))
+                    .collect::<Vec<_>>()
+            },
+        )?;
 
-    fir_to_qir(&fir_store, capabilities, Some(compute_properties), &entry)
-        .map_err(|e| e.to_string())
+    fir_to_qir(&fir_store, capabilities, Some(compute_properties), &entry).map_err(|e| {
+        let source_package = package_store
+            .get(package_id)
+            .expect("package should be in store");
+        vec![Error::PartialEvaluation(WithSource::from_map(
+            &source_package.sources,
+            e,
+        ))]
+    })
 }
diff --git a/compiler/qsc/src/compile.rs b/compiler/qsc/src/compile.rs
index 246238d2..a0964bea 100644
--- a/compiler/qsc/src/compile.rs
+++ b/compiler/qsc/src/compile.rs
@@ -52,7 +52,7 @@ pub fn compile_ast(
         capabilities,
         vec![],
     );
-    process_compile_unit(store, package_type, capabilities, unit)
+    process_compile_unit(store, package_type, unit)
 }
 
 /// Compiles a package from its source representation.
@@ -72,7 +72,7 @@ pub fn compile(
         capabilities,
         language_features,
     );
-    process_compile_unit(store, package_type, capabilities, unit)
+    process_compile_unit(store, package_type, unit)
 }
 
 #[must_use]
@@ -80,7 +80,6 @@ pub fn compile(
 fn process_compile_unit(
     store: &PackageStore,
     package_type: PackageType,
-    capabilities: TargetCapabilityFlags,
     mut unit: CompileUnit,
 ) -> (CompileUnit, Vec<Error>) {
     let mut errors = Vec::new();
@@ -89,7 +88,7 @@ fn process_compile_unit(
     }
 
     if errors.is_empty() {
-        for error in run_default_passes(store.core(), &mut unit, package_type, capabilities) {
+        for error in run_default_passes(store.core(), &mut unit, package_type) {
             errors.push(WithSource::from_map(&unit.sources, error.into()));
         }
     }
@@ -126,7 +125,7 @@ pub fn core() -> CompileUnit {
 #[must_use]
 pub fn std(store: &PackageStore, capabilities: TargetCapabilityFlags) -> CompileUnit {
     let mut unit = qsc_frontend::compile::std(store, capabilities);
-    let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib, capabilities);
+    let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib);
     if pass_errors.is_empty() {
         unit
     } else {
diff --git a/compiler/qsc/src/incremental.rs b/compiler/qsc/src/incremental.rs
index 536affb1..1629e5e8 100644
--- a/compiler/qsc/src/incremental.rs
+++ b/compiler/qsc/src/incremental.rs
@@ -79,7 +79,7 @@ impl Compiler {
             store,
             source_package_id,
             frontend,
-            passes: PassContext::new(capabilities),
+            passes: PassContext::default(),
         })
     }
 
@@ -97,7 +97,7 @@ impl Compiler {
             store,
             source_package_id,
             frontend,
-            passes: PassContext::new(capabilities),
+            passes: PassContext::default(),
         })
     }
 
diff --git a/compiler/qsc/src/interpret.rs b/compiler/qsc/src/interpret.rs
index ffbca883..0eacf510 100644
--- a/compiler/qsc/src/interpret.rs
+++ b/compiler/qsc/src/interpret.rs
@@ -40,7 +40,7 @@ use qsc_circuit::{
     operations::entry_expr_for_qubit_operation, Builder as CircuitBuilder, Circuit,
     Config as CircuitConfig,
 };
-use qsc_codegen::{qir::fir_to_qir, qir_base::BaseProfSim};
+use qsc_codegen::qir::fir_to_qir;
 use qsc_data_structures::{
     functors::FunctorApp,
     language_features::LanguageFeatures,
@@ -409,56 +409,45 @@ impl Interpreter {
         if self.capabilities == TargetCapabilityFlags::all() {
             return Err(vec![Error::UnsupportedRuntimeCapabilities]);
         }
-        if self.capabilities == TargetCapabilityFlags::empty() {
-            let mut sim = BaseProfSim::new();
-            let mut stdout = std::io::sink();
-            let mut out = GenericReceiver::new(&mut stdout);
 
-            let val = self.run_with_sim(&mut sim, &mut out, expr)??;
+        // Compile the expression. This operation will set the expression as
+        // the entry-point in the FIR store.
+        let (graph, compute_properties) = self.compile_entry_expr(expr)?;
 
-            Ok(sim.finish(&val))
-        } else {
-            // Compile the expression. This operation will set the expression as
-            // the entry-point in the FIR store.
-            let (graph, compute_properties) = self.compile_entry_expr(expr)?;
-
-            let Some(compute_properties) = compute_properties else {
-                // This can only happen if capability analysis was not run. This would be a bug
-                // and we are in a bad state and can't proceed.
-                panic!(
-                    "internal error: compute properties not set after lowering entry expression"
-                );
-            };
-            let package = self.fir_store.get(self.package);
-            let entry = ProgramEntry {
-                exec_graph: graph.into(),
-                expr: (
-                    self.package,
-                    package
-                        .entry
-                        .expect("package must have an entry expression"),
-                )
-                    .into(),
-            };
-            // Generate QIR
-            fir_to_qir(
-                &self.fir_store,
-                self.capabilities,
-                Some(compute_properties),
-                &entry,
+        let Some(compute_properties) = compute_properties else {
+            // This can only happen if capability analysis was not run. This would be a bug
+            // and we are in a bad state and can't proceed.
+            panic!("internal error: compute properties not set after lowering entry expression");
+        };
+        let package = self.fir_store.get(self.package);
+        let entry = ProgramEntry {
+            exec_graph: graph.into(),
+            expr: (
+                self.package,
+                package
+                    .entry
+                    .expect("package must have an entry expression"),
             )
-            .map_err(|e| {
-                let source_package = self
-                    .compiler
-                    .package_store()
-                    .get(map_fir_package_to_hir(self.package))
-                    .expect("package should exist in the package store");
-                vec![Error::PartialEvaluation(WithSource::from_map(
-                    &source_package.sources,
-                    e,
-                ))]
-            })
-        }
+                .into(),
+        };
+        // Generate QIR
+        fir_to_qir(
+            &self.fir_store,
+            self.capabilities,
+            Some(compute_properties),
+            &entry,
+        )
+        .map_err(|e| {
+            let source_package = self
+                .compiler
+                .package_store()
+                .get(map_fir_package_to_hir(self.package))
+                .expect("package should exist in the package store");
+            vec![Error::PartialEvaluation(WithSource::from_map(
+                &source_package.sources,
+                e,
+            ))]
+        })
     }
 
     /// Generates a circuit representation for the program.
diff --git a/compiler/qsc_codegen/src/lib.rs b/compiler/qsc_codegen/src/lib.rs
index 8fb76b4e..b4023885 100644
--- a/compiler/qsc_codegen/src/lib.rs
+++ b/compiler/qsc_codegen/src/lib.rs
@@ -2,6 +2,5 @@
 // Licensed under the MIT License.
 
 pub mod qir;
-pub mod qir_base;
 pub mod qsharp;
 pub mod remapper;
diff --git a/compiler/qsc_codegen/src/qir_base.rs b/compiler/qsc_codegen/src/qir_base.rs
deleted file mode 100644
index 5a57a5d8..00000000
--- a/compiler/qsc_codegen/src/qir_base.rs
+++ /dev/null
@@ -1,552 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-#[cfg(test)]
-mod tests;
-
-use crate::remapper::{HardwareId, Remapper};
-use num_bigint::BigUint;
-use num_complex::Complex;
-use qsc_eval::{
-    backend::Backend, debug::Frame, eval, output::GenericReceiver, val::Value, Env, Error,
-};
-use qsc_fir::fir;
-use qsc_frontend::compile::PackageStore;
-use qsc_hir::hir::{self};
-use qsc_lowerer::map_hir_package_to_fir;
-use rustc_hash::FxHashSet;
-use std::fmt::{Display, Write};
-
-/// # Errors
-///
-/// This function will return an error if execution was unable to complete.
-/// # Panics
-///
-/// This function will panic if compiler state is invalid or in out-of-memory conditions.
-pub fn generate_qir(
-    store: &PackageStore,
-    package: hir::PackageId,
-) -> std::result::Result<String, (Error, Vec<Frame>)> {
-    let mut fir_store = fir::PackageStore::new();
-    for (id, unit) in store {
-        fir_store.insert(
-            map_hir_package_to_fir(id),
-            qsc_lowerer::Lowerer::new().lower_package(&unit.package),
-        );
-    }
-
-    let package = map_hir_package_to_fir(package);
-    let unit = fir_store.get(package);
-
-    let mut sim = BaseProfSim::default();
-    let mut stdout = std::io::sink();
-    let mut out = GenericReceiver::new(&mut stdout);
-    let result = eval(
-        package,
-        None,
-        unit.entry_exec_graph.clone(),
-        &fir_store,
-        &mut Env::default(),
-        &mut sim,
-        &mut out,
-    );
-    match result {
-        Ok(val) => Ok(sim.finish(&val)),
-        Err((err, stack)) => Err((err, stack)),
-    }
-}
-
-pub struct BaseProfSim {
-    instrs: String,
-    decls: String,
-    decl_names: FxHashSet<String>,
-    remapper: Remapper,
-}
-
-impl Default for BaseProfSim {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-impl BaseProfSim {
-    #[must_use]
-    pub fn new() -> Self {
-        let mut sim = BaseProfSim {
-            instrs: String::new(),
-            decls: String::new(),
-            decl_names: FxHashSet::default(),
-            remapper: Remapper::default(),
-        };
-        sim.instrs.push_str(include_str!("./qir_base/prefix.ll"));
-        sim
-    }
-
-    #[must_use]
-    pub fn finish(mut self, val: &Value) -> String {
-        for (mapped_q, id) in self.remapper.measurements() {
-            writeln!(
-                self.instrs,
-                "  call void @__quantum__qis__mz__body({}, {}) #1",
-                Qubit(*mapped_q),
-                Result(*id),
-            )
-            .expect("writing to string should succeed");
-        }
-        self.write_output_recording(val)
-            .expect("writing to string should succeed");
-
-        write!(
-            self.instrs,
-            include_str!("./qir_base/postfix.ll"),
-            self.decls,
-            self.remapper.num_qubits(),
-            self.remapper.num_measurements()
-        )
-        .expect("writing to string should succeed");
-
-        self.instrs
-    }
-
-    fn map(&mut self, qubit: usize) -> HardwareId {
-        self.remapper.map(qubit)
-    }
-
-    fn write_output_recording(&mut self, val: &Value) -> std::fmt::Result {
-        match val {
-            Value::Array(arr) => {
-                self.write_array_recording(arr.len())?;
-                for val in arr.iter() {
-                    self.write_output_recording(val)?;
-                }
-            }
-            Value::Result(r) => {
-                self.write_result_recording(r.unwrap_id());
-            }
-            Value::Tuple(tup) => {
-                self.write_tuple_recording(tup.len())?;
-                for val in tup.iter() {
-                    self.write_output_recording(val)?;
-                }
-            }
-            _ => panic!("unexpected value type: {val:?}"),
-        }
-        Ok(())
-    }
-
-    fn write_result_recording(&mut self, res: usize) {
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__rt__result_record_output({}, i8* null)",
-            Result(res),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn write_tuple_recording(&mut self, size: usize) -> std::fmt::Result {
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__rt__tuple_record_output(i64 {size}, i8* null)"
-        )
-    }
-
-    fn write_array_recording(&mut self, size: usize) -> std::fmt::Result {
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__rt__array_record_output(i64 {size}, i8* null)"
-        )
-    }
-
-    fn write_arg(&mut self, arg: &Value) -> std::result::Result<(), String> {
-        match arg {
-            Value::Qubit(q) => {
-                let q = self.map(q.0);
-                write!(self.instrs, "{}", Qubit(q))
-            }
-            Value::Double(d) => write!(self.instrs, "{}", Double(*d)),
-            Value::Bool(b) => write!(self.instrs, "{}", Bool(*b)),
-            Value::Int(i) => write!(self.instrs, "{}", Int(*i)),
-            _ => return Err(format!("unsupported argument type: {}", arg.type_name())),
-        }
-        .expect("writing to string should succeed");
-        Ok(())
-    }
-
-    fn write_decl_type(&mut self, ty: &Value) -> std::result::Result<(), String> {
-        match ty {
-            Value::Qubit(_) => write!(self.decls, "%Qubit*"),
-            Value::Double(_) => write!(self.decls, "double"),
-            Value::Bool(_) => write!(self.decls, "i1"),
-            Value::Int(_) => write!(self.decls, "i64"),
-            _ => return Err(format!("unsupported argument type: {}", ty.type_name())),
-        }
-        .expect("writing to string should succeed");
-        Ok(())
-    }
-
-    fn write_decl(&mut self, name: &str, arg: &Value) -> std::result::Result<(), String> {
-        if self.decl_names.insert(name.to_string()) {
-            write!(self.decls, "declare void @{name}(").expect("writing to string should succeed");
-            if let Value::Tuple(args) = arg {
-                if let Some((first, rest)) = args.split_first() {
-                    self.write_decl_type(first)?;
-                    for arg in rest {
-                        write!(self.decls, ", ").expect("writing to string should succeed");
-                        self.write_decl_type(arg)?;
-                    }
-                }
-            } else {
-                self.write_decl_type(arg)?;
-            }
-            writeln!(self.decls, ")").expect("writing to string should succeed");
-        }
-
-        Ok(())
-    }
-}
-
-impl Backend for BaseProfSim {
-    type ResultType = usize;
-
-    fn ccx(&mut self, ctl0: usize, ctl1: usize, q: usize) {
-        let ctl0 = self.map(ctl0);
-        let ctl1 = self.map(ctl1);
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__ccx__body({}, {}, {})",
-            Qubit(ctl0),
-            Qubit(ctl1),
-            Qubit(q)
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn cx(&mut self, ctl: usize, q: usize) {
-        let ctl = self.map(ctl);
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__cx__body({}, {})",
-            Qubit(ctl),
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn cy(&mut self, ctl: usize, q: usize) {
-        let ctl = self.map(ctl);
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__cy__body({}, {})",
-            Qubit(ctl),
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn cz(&mut self, ctl: usize, q: usize) {
-        let ctl = self.map(ctl);
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__cz__body({}, {})",
-            Qubit(ctl),
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn h(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__h__body({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn m(&mut self, q: usize) -> Self::ResultType {
-        // Measurements are tracked separately from instructions, so that they can be
-        // deferred until the end of the program.
-        self.remapper.mreset(q)
-    }
-
-    fn mresetz(&mut self, q: usize) -> Self::ResultType {
-        self.remapper.mreset(q)
-    }
-
-    fn reset(&mut self, q: usize) {
-        // Reset is a no-op in Base Profile, but does force qubit remapping so that future
-        // operations on the given qubit id are performed on a fresh qubit. Clear the entry in the map
-        // so it is known to require remapping on next use.
-        self.remapper.reset(q);
-    }
-
-    fn rx(&mut self, theta: f64, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__rx__body({}, {})",
-            Double(theta),
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn rxx(&mut self, theta: f64, q0: usize, q1: usize) {
-        let q0 = self.map(q0);
-        let q1 = self.map(q1);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__rxx__body({}, {}, {})",
-            Double(theta),
-            Qubit(q0),
-            Qubit(q1),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn ry(&mut self, theta: f64, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__ry__body({}, {})",
-            Double(theta),
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn ryy(&mut self, theta: f64, q0: usize, q1: usize) {
-        let q0 = self.map(q0);
-        let q1 = self.map(q1);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__ryy__body({}, {}, {})",
-            Double(theta),
-            Qubit(q0),
-            Qubit(q1),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn rz(&mut self, theta: f64, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__rz__body({}, {})",
-            Double(theta),
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn rzz(&mut self, theta: f64, q0: usize, q1: usize) {
-        let q0 = self.map(q0);
-        let q1 = self.map(q1);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__rzz__body({}, {}, {})",
-            Double(theta),
-            Qubit(q0),
-            Qubit(q1),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn sadj(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__s__adj({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn s(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__s__body({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn swap(&mut self, q0: usize, q1: usize) {
-        let q0 = self.map(q0);
-        let q1 = self.map(q1);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__swap__body({}, {})",
-            Qubit(q0),
-            Qubit(q1),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn tadj(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__t__adj({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn t(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__t__body({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn x(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__x__body({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn y(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__y__body({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn z(&mut self, q: usize) {
-        let q = self.map(q);
-        writeln!(
-            self.instrs,
-            "  call void @__quantum__qis__z__body({})",
-            Qubit(q),
-        )
-        .expect("writing to string should succeed");
-    }
-
-    fn qubit_allocate(&mut self) -> usize {
-        self.remapper.qubit_allocate()
-    }
-
-    fn qubit_release(&mut self, q: usize) {
-        self.remapper.qubit_release(q);
-    }
-
-    fn capture_quantum_state(&mut self) -> (Vec<(BigUint, Complex<f64>)>, usize) {
-        (Vec::new(), 0)
-    }
-
-    fn qubit_is_zero(&mut self, _q: usize) -> bool {
-        // Because `qubit_is_zero` is called on every qubit release, this must return
-        // true to avoid a panic.
-        true
-    }
-
-    fn custom_intrinsic(
-        &mut self,
-        name: &str,
-        arg: Value,
-    ) -> Option<std::result::Result<Value, String>> {
-        // Global phase is a special case that is non-physical, so there is no need to generate
-        // a call here, just do a shortcut return.
-        if name == "GlobalPhase" {
-            return Some(Ok(Value::unit()));
-        }
-
-        match self.write_decl(name, &arg) {
-            Ok(()) => {}
-            Err(e) => return Some(Err(e)),
-        }
-        write!(self.instrs, "  call void @{name}(").expect("writing to string should succeed");
-
-        if let Value::Tuple(args) = arg {
-            if let Some((first, rest)) = args.split_first() {
-                match self.write_arg(first) {
-                    Ok(()) => {}
-                    Err(e) => return Some(Err(e)),
-                }
-                for arg in rest {
-                    write!(self.instrs, ", ").expect("writing to string should succeed");
-                    match self.write_arg(arg) {
-                        Ok(()) => {}
-                        Err(e) => return Some(Err(e)),
-                    }
-                }
-            }
-        } else {
-            match self.write_arg(&arg) {
-                Ok(()) => {}
-                Err(e) => return Some(Err(e)),
-            }
-        }
-
-        writeln!(self.instrs, ")").expect("writing to string should succeed");
-        Some(Ok(Value::unit()))
-    }
-}
-
-struct Qubit(HardwareId);
-
-impl Display for Qubit {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "%Qubit* inttoptr (i64 {} to %Qubit*)", self.0 .0)
-    }
-}
-
-struct Result(usize);
-
-impl Display for Result {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "%Result* inttoptr (i64 {} to %Result*)", self.0)
-    }
-}
-
-struct Double(f64);
-
-impl Display for Double {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let v = self.0;
-        if (v.floor() - v.ceil()).abs() < f64::EPSILON {
-            // The value is a whole number, which requires at least one decimal point
-            // to differentiate it from an integer value.
-            write!(f, "double {v:.1}")
-        } else {
-            write!(f, "double {v}")
-        }
-    }
-}
-
-struct Bool(bool);
-
-impl Display for Bool {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        if self.0 {
-            write!(f, "i1 true")
-        } else {
-            write!(f, "i1 false")
-        }
-    }
-}
-
-struct Int(i64);
-
-impl Display for Int {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "i64 {}", self.0)
-    }
-}
diff --git a/compiler/qsc_codegen/src/qir_base/postfix.ll b/compiler/qsc_codegen/src/qir_base/postfix.ll
deleted file mode 100644
index b21a1c42..00000000
--- a/compiler/qsc_codegen/src/qir_base/postfix.ll
+++ /dev/null
@@ -1,38 +0,0 @@
-  ret void
-}}
-
-declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-declare void @__quantum__qis__rx__body(double, %Qubit*)
-declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-declare void @__quantum__qis__ry__body(double, %Qubit*)
-declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-declare void @__quantum__qis__rz__body(double, %Qubit*)
-declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-declare void @__quantum__qis__h__body(%Qubit*)
-declare void @__quantum__qis__s__body(%Qubit*)
-declare void @__quantum__qis__s__adj(%Qubit*)
-declare void @__quantum__qis__t__body(%Qubit*)
-declare void @__quantum__qis__t__adj(%Qubit*)
-declare void @__quantum__qis__x__body(%Qubit*)
-declare void @__quantum__qis__y__body(%Qubit*)
-declare void @__quantum__qis__z__body(%Qubit*)
-declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-declare void @__quantum__rt__result_record_output(%Result*, i8*)
-declare void @__quantum__rt__array_record_output(i64, i8*)
-declare void @__quantum__rt__tuple_record_output(i64, i8*)
-{}
-attributes #0 = {{ "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="{}" "required_num_results"="{}" }}
-attributes #1 = {{ "irreversible" }}
-
-; module flags
-
-!llvm.module.flags = !{{!0, !1, !2, !3}}
-
-!0 = !{{i32 1, !"qir_major_version", i32 1}}
-!1 = !{{i32 7, !"qir_minor_version", i32 0}}
-!2 = !{{i32 1, !"dynamic_qubit_management", i1 false}}
-!3 = !{{i32 1, !"dynamic_result_management", i1 false}}
diff --git a/compiler/qsc_codegen/src/qir_base/prefix.ll b/compiler/qsc_codegen/src/qir_base/prefix.ll
deleted file mode 100644
index 41653179..00000000
--- a/compiler/qsc_codegen/src/qir_base/prefix.ll
+++ /dev/null
@@ -1,4 +0,0 @@
-%Result = type opaque
-%Qubit = type opaque
-
-define void @ENTRYPOINT__main() #0 {
diff --git a/compiler/qsc_data_structures/src/language_features.rs b/compiler/qsc_data_structures/src/language_features.rs
index e6a4094c..f3d5105c 100644
--- a/compiler/qsc_data_structures/src/language_features.rs
+++ b/compiler/qsc_data_structures/src/language_features.rs
@@ -10,7 +10,6 @@ pub struct LanguageFeatures(u8);
 bitflags! {
     impl LanguageFeatures: u8 {
         const V2PreviewSyntax = 0b1;
-        const PreviewQirGen = 0b10;
     }
 }
 
@@ -34,7 +33,6 @@ where
         iter.into_iter().fold(LanguageFeatures::empty(), |acc, x| {
             acc | match x.as_ref() {
                 "v2-preview-syntax" => LanguageFeatures::V2PreviewSyntax,
-                "preview-qir-gen" => LanguageFeatures::PreviewQirGen,
                 _ => LanguageFeatures::empty(),
             }
         })
diff --git a/compiler/qsc_eval/src/lib.rs b/compiler/qsc_eval/src/lib.rs
index 0e405214..8a4dae6f 100644
--- a/compiler/qsc_eval/src/lib.rs
+++ b/compiler/qsc_eval/src/lib.rs
@@ -25,10 +25,12 @@ pub mod output;
 pub mod state;
 pub mod val;
 
-use crate::val::Value;
+use crate::val::{
+    index_array, make_range, slice_array, update_index_range, update_index_single, Value,
+};
 use backend::Backend;
 use debug::{CallStack, Frame};
-use error::PackageSpan;
+pub use error::PackageSpan;
 use miette::Diagnostic;
 use num_bigint::BigInt;
 use output::Receiver;
@@ -288,7 +290,7 @@ pub struct VariableInfo {
     pub span: Span,
 }
 
-struct Range {
+pub struct Range {
     step: i64,
     end: i64,
     curr: i64,
@@ -1105,18 +1107,8 @@ impl State {
         update: Value,
         span: PackageSpan,
     ) -> Result<(), Error> {
-        if index < 0 {
-            return Err(Error::InvalidNegativeInt(index, span));
-        }
-        let i = index.as_index(span)?;
-        let mut values = values.to_vec();
-        match values.get_mut(i) {
-            Some(value) => {
-                *value = update;
-            }
-            None => return Err(Error::IndexOutOfRange(index, span)),
-        }
-        self.set_val_register(Value::Array(values.into()));
+        let updated_array = update_index_single(values, index, update, span)?;
+        self.set_val_register(updated_array);
         Ok(())
     }
 
@@ -1129,19 +1121,8 @@ impl State {
         update: Value,
         span: PackageSpan,
     ) -> Result<(), Error> {
-        let range = make_range(values, start, step, end, span)?;
-        let mut values = values.to_vec();
-        let update = update.unwrap_array();
-        for (idx, update) in range.into_iter().zip(update.iter()) {
-            let i = idx.as_index(span)?;
-            match values.get_mut(i) {
-                Some(value) => {
-                    *value = update.clone();
-                }
-                None => return Err(Error::IndexOutOfRange(idx, span)),
-            }
-        }
-        self.set_val_register(Value::Array(values.into()));
+        let updated_array = update_index_range(values, start, step, end, update, span)?;
+        self.set_val_register(updated_array);
         Ok(())
     }
 
@@ -1483,53 +1464,6 @@ fn lit_to_val(lit: &Lit) -> Value {
     }
 }
 
-fn index_array(arr: &[Value], index: i64, span: PackageSpan) -> Result<Value, Error> {
-    let i = index.as_index(span)?;
-    match arr.get(i) {
-        Some(v) => Ok(v.clone()),
-        None => Err(Error::IndexOutOfRange(index, span)),
-    }
-}
-
-fn slice_array(
-    arr: &[Value],
-    start: Option<i64>,
-    step: i64,
-    end: Option<i64>,
-    span: PackageSpan,
-) -> Result<Value, Error> {
-    let range = make_range(arr, start, step, end, span)?;
-    let mut slice = vec![];
-    for i in range {
-        slice.push(index_array(arr, i, span)?);
-    }
-
-    Ok(Value::Array(slice.into()))
-}
-
-fn make_range(
-    arr: &[Value],
-    start: Option<i64>,
-    step: i64,
-    end: Option<i64>,
-    span: PackageSpan,
-) -> Result<Range, Error> {
-    if step == 0 {
-        Err(Error::RangeStepZero(span))
-    } else {
-        let len: i64 = match arr.len().try_into() {
-            Ok(len) => Ok(len),
-            Err(_) => Err(Error::ArrayTooLarge(span)),
-        }?;
-        let (start, end) = if step > 0 {
-            (start.unwrap_or(0), end.unwrap_or(len - 1))
-        } else {
-            (start.unwrap_or(len - 1), end.unwrap_or(0))
-        };
-        Ok(Range::new(start, step, end))
-    }
-}
-
 fn eval_binop_eq(lhs_val: Value, rhs_val: Value, rhs_span: PackageSpan) -> Result<Value, Error> {
     match (lhs_val, rhs_val) {
         (Value::Result(val::Result::Id(_)), _) | (_, Value::Result(val::Result::Id(_))) => {
diff --git a/compiler/qsc_eval/src/val.rs b/compiler/qsc_eval/src/val.rs
index 6a055b82..8fd9735f 100644
--- a/compiler/qsc_eval/src/val.rs
+++ b/compiler/qsc_eval/src/val.rs
@@ -9,6 +9,8 @@ use std::{
     rc::Rc,
 };
 
+use crate::{error::PackageSpan, AsIndex, Error, Range as EvalRange};
+
 pub(super) const DEFAULT_RANGE_STEP: i64 = 1;
 
 #[derive(Clone, Debug, PartialEq)]
@@ -380,3 +382,97 @@ impl Value {
         }
     }
 }
+
+pub fn index_array(
+    arr: &[Value],
+    index: i64,
+    span: PackageSpan,
+) -> std::result::Result<Value, Error> {
+    let i = index.as_index(span)?;
+    match arr.get(i) {
+        Some(v) => Ok(v.clone()),
+        None => Err(Error::IndexOutOfRange(index, span)),
+    }
+}
+
+pub fn make_range(
+    arr: &[Value],
+    start: Option<i64>,
+    step: i64,
+    end: Option<i64>,
+    span: PackageSpan,
+) -> std::result::Result<EvalRange, Error> {
+    if step == 0 {
+        Err(Error::RangeStepZero(span))
+    } else {
+        let len: i64 = match arr.len().try_into() {
+            Ok(len) => Ok(len),
+            Err(_) => Err(Error::ArrayTooLarge(span)),
+        }?;
+        let (start, end) = if step > 0 {
+            (start.unwrap_or(0), end.unwrap_or(len - 1))
+        } else {
+            (start.unwrap_or(len - 1), end.unwrap_or(0))
+        };
+        Ok(EvalRange::new(start, step, end))
+    }
+}
+
+pub fn slice_array(
+    arr: &[Value],
+    start: Option<i64>,
+    step: i64,
+    end: Option<i64>,
+    span: PackageSpan,
+) -> std::result::Result<Value, Error> {
+    let range = make_range(arr, start, step, end, span)?;
+    let mut slice = vec![];
+    for i in range {
+        slice.push(index_array(arr, i, span)?);
+    }
+
+    Ok(Value::Array(slice.into()))
+}
+
+pub fn update_index_single(
+    values: &[Value],
+    index: i64,
+    update: Value,
+    span: PackageSpan,
+) -> std::result::Result<Value, Error> {
+    if index < 0 {
+        return Err(Error::InvalidNegativeInt(index, span));
+    }
+    let i = index.as_index(span)?;
+    let mut values = values.to_vec();
+    match values.get_mut(i) {
+        Some(value) => {
+            *value = update;
+        }
+        None => return Err(Error::IndexOutOfRange(index, span)),
+    }
+    Ok(Value::Array(values.into()))
+}
+
+pub fn update_index_range(
+    values: &[Value],
+    start: Option<i64>,
+    step: i64,
+    end: Option<i64>,
+    update: Value,
+    span: PackageSpan,
+) -> std::result::Result<Value, Error> {
+    let range = make_range(values, start, step, end, span)?;
+    let mut values = values.to_vec();
+    let update = update.unwrap_array();
+    for (idx, update) in range.into_iter().zip(update.iter()) {
+        let i = idx.as_index(span)?;
+        match values.get_mut(i) {
+            Some(value) => {
+                *value = update.clone();
+            }
+            None => return Err(Error::IndexOutOfRange(idx, span)),
+        }
+    }
+    Ok(Value::Array(values.into()))
+}
diff --git a/compiler/qsc_fir/src/fir.rs b/compiler/qsc_fir/src/fir.rs
index 7ac1dfcc..cf18ea7c 100644
--- a/compiler/qsc_fir/src/fir.rs
+++ b/compiler/qsc_fir/src/fir.rs
@@ -833,7 +833,7 @@ pub struct SpecImpl {
 impl Display for SpecImpl {
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
         let mut indent = set_indentation(indented(f), 0);
-        write!(indent, "SpecImpl:",)?;
+        write!(indent, "SpecImpl:")?;
         indent = set_indentation(indent, 1);
         write!(indent, "\nbody: {}", self.body)?;
         match &self.adj {
diff --git a/compiler/qsc_partial_eval/src/lib.rs b/compiler/qsc_partial_eval/src/lib.rs
index 4fe18f9b..fb968052 100644
--- a/compiler/qsc_partial_eval/src/lib.rs
+++ b/compiler/qsc_partial_eval/src/lib.rs
@@ -18,11 +18,12 @@ use miette::Diagnostic;
 use qsc_data_structures::span::Span;
 use qsc_data_structures::{functors::FunctorApp, target::TargetCapabilityFlags};
 use qsc_eval::resolve_closure;
+use qsc_eval::val::{index_array, slice_array, update_index_range, update_index_single};
 use qsc_eval::{
     self, exec_graph_section,
     output::GenericReceiver,
     val::{self, Value, Var, VarTy},
-    State, StepAction, StepResult, Variable,
+    PackageSpan, State, StepAction, StepResult, Variable,
 };
 use qsc_fir::{
     fir::{
@@ -33,6 +34,7 @@ use qsc_fir::{
     },
     ty::{Prim, Ty},
 };
+use qsc_lowerer::map_fir_package_to_hir;
 use qsc_rca::errors::{generate_errors_from_runtime_features, get_missing_runtime_features};
 use qsc_rca::{
     errors::Error as CapabilityError, ComputeKind, ComputePropertiesLookup,
@@ -264,6 +266,18 @@ impl<'a> PartialEvaluator<'a> {
         block_id
     }
 
+    fn entry_expr_output_span(&self) -> Span {
+        let expr = self.get_expr(self.entry.expr.expr);
+        match &expr.kind {
+            // Special handling for compiler generated entry expressions that come from the `@EntryPoint`
+            // attributed callable.
+            ExprKind::Call(callee, _) if expr.span == Span::default() => {
+                self.get_expr(*callee).span
+            }
+            _ => expr.span,
+        }
+    }
+
     fn eval(mut self) -> Result<Program, Error> {
         // Evaluate the entry-point expression.
         let ret_val = self.try_eval_expr(self.entry.expr.expr)?.into_value();
@@ -294,16 +308,54 @@ impl<'a> PartialEvaluator<'a> {
         Ok(self.program)
     }
 
-    fn entry_expr_output_span(&self) -> Span {
-        let expr = self.get_expr(self.entry.expr.expr);
-        match &expr.kind {
-            // Special handling for compiler generated entry expressions that come from the `@EntryPoint`
-            // attributed callable.
-            ExprKind::Call(callee, _) if expr.span == Span::default() => {
-                self.get_expr(*callee).span
+    fn eval_array_update_index(
+        &mut self,
+        array: &[Value],
+        index_expr_id: ExprId,
+        update_expr_id: ExprId,
+    ) -> Result<Value, Error> {
+        // Try to evaluate the index and update expressions to get their value, short-circuiting execution if any of the
+        // expressions is a return.
+        let index_expr = self.get_expr(index_expr_id);
+        let index_control_flow = self.try_eval_expr(index_expr_id)?;
+        let EvalControlFlow::Continue(index_value) = index_control_flow else {
+            return Err(Error::Unexpected(
+                "embedded return in index expression".to_string(),
+                index_expr.span,
+            ));
+        };
+        let update_control_flow = self.try_eval_expr(update_expr_id)?;
+        let EvalControlFlow::Continue(update_value) = update_control_flow else {
+            let update_expr = self.get_expr(update_expr_id);
+            return Err(Error::Unexpected(
+                "embedded return in update expression".to_string(),
+                update_expr.span,
+            ));
+        };
+
+        // Set the value at the specified index or range.
+        let hir_package_id = map_fir_package_to_hir(self.get_current_package_id());
+        let index_package_span = PackageSpan {
+            package: hir_package_id,
+            span: index_expr.span,
+        };
+        let update_result = match index_value {
+            Value::Int(index) => {
+                update_index_single(array, index, update_value, index_package_span)
             }
-            _ => expr.span,
-        }
+            Value::Range(range) => update_index_range(
+                array,
+                range.start,
+                range.step,
+                range.end,
+                update_value,
+                index_package_span,
+            ),
+            _ => panic!("invalid kind of value for index"),
+        };
+        let updated_array =
+            update_result.map_err(|e| Error::EvaluationFailed(e.to_string(), e.span().span))?;
+        Ok(updated_array)
     }
 
     fn eval_bin_op(
@@ -877,10 +929,9 @@ impl<'a> PartialEvaluator<'a> {
                 "Updated Field Expr".to_string(),
                 expr.span,
             )),
-            ExprKind::UpdateIndex(_, _, _) => Err(Error::Unimplemented(
-                "Update Index Expr".to_string(),
-                expr.span,
-            )),
+            ExprKind::UpdateIndex(array_expr_id, index_expr_id, update_expr_id) => {
+                self.eval_expr_update_index(*array_expr_id, *index_expr_id, *update_expr_id)
+            }
             ExprKind::Var(res, _) => Ok(EvalControlFlow::Continue(self.eval_expr_var(res))),
             ExprKind::While(condition_expr_id, body_block_id) => {
                 self.eval_expr_while(*condition_expr_id, *body_block_id)
@@ -941,46 +992,24 @@ impl<'a> PartialEvaluator<'a> {
         &mut self,
         array_expr_id: ExprId,
         index_expr_id: ExprId,
-        replace_expr_id: ExprId,
+        update_expr_id: ExprId,
     ) -> Result<EvalControlFlow, Error> {
-        // Get the value of the array expression to use it as the basis to perform a replacement on.
+        // Get the value of the array to use it as the basis to perform the update.
         let array_expr = self.get_expr(array_expr_id);
         let ExprKind::Var(Res::Local(array_loc_id), _) = &array_expr.kind else {
             panic!("array expression in assign index expression is expected to be a variable");
         };
-        let array_value = self
+        let array = self
             .eval_context
             .get_current_scope()
             .get_classical_local_value(*array_loc_id)
-            .clone();
+            .clone()
+            .unwrap_array();
 
-        // Try to evaluate the index and replace expressions to get their value, short-circuiting execution if any of
-        // the expressions is a return.
-        let index_control_flow = self.try_eval_expr(index_expr_id)?;
-        let EvalControlFlow::Continue(index_value) = index_control_flow else {
-            let index_expr = self.get_expr(index_expr_id);
-            return Err(Error::Unexpected(
-                "embedded return in assign index expression".to_string(),
-                index_expr.span,
-            ));
-        };
-        let replace_control_flow = self.try_eval_expr(replace_expr_id)?;
-        let EvalControlFlow::Continue(replace_value) = replace_control_flow else {
-            let replace_expr = self.get_expr(replace_expr_id);
-            return Err(Error::Unexpected(
-                "embedded return in assign index expression".to_string(),
-                replace_expr.span,
-            ));
-        };
-
-        // Replace the value at the corresponding index and update the array binding.
-        let index: usize = index_value
-            .unwrap_int()
-            .try_into()
-            .expect("could not convert array index into usize");
-        let mut array = array_value.unwrap_array().to_vec();
-        array[index] = replace_value;
-        self.update_bindings(array_expr_id, Value::Array(array.into()))?;
+        // Evaluate the updated array and update the corresponding bindings.
+        let new_array_value =
+            self.eval_array_update_index(&array, index_expr_id, update_expr_id)?;
+        self.update_bindings(array_expr_id, new_array_value)?;
         Ok(EvalControlFlow::Continue(Value::unit()))
     }
 
@@ -1486,14 +1515,26 @@ impl<'a> PartialEvaluator<'a> {
 
         // Get the value at the specified index.
         let array = array_value.unwrap_array();
-        let index: usize = index_value
-            .unwrap_int()
-            .try_into()
-            .expect("could not convert index to usize");
-        let value_at_index = array
-            .get(index)
-            .unwrap_or_else(|| panic!("could not get value at index {index}"));
-        Ok(EvalControlFlow::Continue(value_at_index.clone()))
+        let index_expr = self.get_expr(index_expr_id);
+        let hir_package_id = map_fir_package_to_hir(self.get_current_package_id());
+        let index_package_span = PackageSpan {
+            package: hir_package_id,
+            span: index_expr.span,
+        };
+        let value_result = match index_value {
+            Value::Int(index) => index_array(&array, index, index_package_span),
+            Value::Range(range) => slice_array(
+                &array,
+                range.start,
+                range.step,
+                range.end,
+                index_package_span,
+            ),
+            _ => panic!("invalid kind of value for index"),
+        };
+        let value =
+            value_result.map_err(|e| Error::EvaluationFailed(e.to_string(), e.span().span))?;
+        Ok(EvalControlFlow::Continue(value))
     }
 
     fn eval_expr_return(&mut self, expr_id: ExprId) -> Result<EvalControlFlow, Error> {
@@ -1605,6 +1646,26 @@ impl<'a> PartialEvaluator<'a> {
         Ok(EvalControlFlow::Continue(Value::Var(eval_variable)))
     }
 
+    fn eval_expr_update_index(
+        &mut self,
+        array_expr_id: ExprId,
+        index_expr_id: ExprId,
+        update_expr_id: ExprId,
+    ) -> Result<EvalControlFlow, Error> {
+        // Get the value of the array expression to use it as the basis to perform a replacement on.
+        let array_control_flow = self.try_eval_expr(array_expr_id)?;
+        let EvalControlFlow::Continue(array_value) = array_control_flow else {
+            let array_expr = self.get_expr(array_expr_id);
+            return Err(Error::Unexpected(
+                "embedded return in index expression".to_string(),
+                array_expr.span,
+            ));
+        };
+        let array = array_value.unwrap_array();
+        let updated_array = self.eval_array_update_index(&array, index_expr_id, update_expr_id)?;
+        Ok(EvalControlFlow::Continue(updated_array))
+    }
+
     fn eval_expr_var(&mut self, res: &Res) -> Value {
         match res {
             Res::Err => panic!("resolution error"),
diff --git a/compiler/qsc_passes/src/baseprofck.rs b/compiler/qsc_passes/src/baseprofck.rs
deleted file mode 100644
index 73650d33..00000000
--- a/compiler/qsc_passes/src/baseprofck.rs
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-#[cfg(test)]
-mod tests;
-
-use miette::Diagnostic;
-use qsc_data_structures::span::Span;
-use qsc_hir::{
-    hir::{BinOp, CallableKind, Expr, ExprKind, Item, ItemKind, Lit, Package, SpecBody, SpecGen},
-    ty::{Prim, Ty},
-    visit::{walk_expr, walk_item, Visitor},
-};
-use thiserror::Error;
-
-#[derive(Clone, Debug, Diagnostic, Error)]
-pub enum Error {
-    #[error("cannot compare measurement results")]
-    #[diagnostic(help(
-        "comparing measurement results is not supported when performing base profile QIR generation"
-    ))]
-    #[diagnostic(code("Qsc.BaseProfCk.ResultComparison"))]
-    ResultComparison(#[label] Span),
-
-    #[error("result literals are not supported")]
-    #[diagnostic(help(
-        "result literals `One` and `Zero` are not supported when performing base profile QIR generation"
-    ))]
-    #[diagnostic(code("Qsc.BaseProfCk.ResultLiteral"))]
-    ResultLiteral(#[label] Span),
-
-    #[error("non-Result return type in entry expression")]
-    #[diagnostic(help(
-        "returning types other than Result from the entry expression is not supported when performing base profile QIR generation"
-    ))]
-    #[diagnostic(code("Qsc.BaseProfCk.ReturnNonResult"))]
-    ReturnNonResult(#[label] Span),
-
-    #[error("intrinsic operations that return types other than Result or Unit are not supported")]
-    #[diagnostic(help(
-        "intrinsic operations that return types other than Result or Unit are not supported when performing base profile QIR generation"
-    ))]
-    #[diagnostic(code("Qsc.BaseProfCk.UnsupportedIntrinsic"))]
-    UnsupportedIntrinsic(#[label] Span),
-}
-
-#[must_use]
-pub fn check_base_profile_compliance(package: &Package) -> Vec<Error> {
-    let mut checker = Checker { errors: Vec::new() };
-    if let Some(entry) = &package.entry {
-        if any_non_result_ty(&entry.ty) {
-            checker.errors.push(Error::ReturnNonResult(entry.span));
-        }
-    }
-    checker.visit_package(package);
-
-    checker.errors
-}
-
-struct Checker {
-    errors: Vec<Error>,
-}
-
-impl<'a> Visitor<'a> for Checker {
-    fn visit_item(&mut self, item: &'a Item) {
-        match &item.kind {
-            ItemKind::Callable(callable)
-                if callable.kind == CallableKind::Operation
-                    && callable.body.body == SpecBody::Gen(SpecGen::Intrinsic)
-                    && callable.output != Ty::Prim(Prim::Result)
-                    && callable.output != Ty::Prim(Prim::Qubit)
-                    && callable.output != Ty::UNIT =>
-            {
-                self.errors
-                    .push(Error::UnsupportedIntrinsic(callable.name.span));
-            }
-            _ => {}
-        }
-
-        walk_item(self, item);
-    }
-
-    fn visit_expr(&mut self, expr: &'a Expr) {
-        match &expr.kind {
-            ExprKind::BinOp(BinOp::Eq | BinOp::Neq, lhs, _) if any_result_ty(&lhs.ty) => {
-                self.errors.push(Error::ResultComparison(expr.span));
-            }
-            ExprKind::Lit(Lit::Result(_)) => {
-                self.errors.push(Error::ResultLiteral(expr.span));
-            }
-            _ => {}
-        }
-        walk_expr(self, expr);
-    }
-}
-
-fn any_result_ty(ty: &Ty) -> bool {
-    match ty {
-        Ty::Array(ty) => any_result_ty(ty),
-        Ty::Prim(Prim::Result) => true,
-        Ty::Tuple(tys) => tys.iter().any(any_result_ty),
-        _ => false,
-    }
-}
-
-fn any_non_result_ty(ty: &Ty) -> bool {
-    match ty {
-        Ty::Array(ty) => any_non_result_ty(ty),
-        Ty::Prim(Prim::Result) => false,
-        Ty::Tuple(tys) if tys.is_empty() => true,
-        Ty::Tuple(tys) => tys.iter().any(any_non_result_ty),
-        _ => true,
-    }
-}
diff --git a/compiler/qsc_passes/src/lib.rs b/compiler/qsc_passes/src/lib.rs
index 948b6f49..f142605c 100644
--- a/compiler/qsc_passes/src/lib.rs
+++ b/compiler/qsc_passes/src/lib.rs
@@ -1,7 +1,6 @@
 // Copyright (c) Microsoft Corporation.
 // Licensed under the MIT License.
 
-mod baseprofck;
 mod borrowck;
 mod callable_limits;
 mod capabilitiesck;
@@ -43,7 +42,6 @@ pub(crate) static QIR_RUNTIME_NAMESPACE: &[&str] = &["QIR", "Runtime"];
 #[diagnostic(transparent)]
 #[error(transparent)]
 pub enum Error {
-    BaseProfCk(baseprofck::Error),
     BorrowCk(borrowck::Error),
     CallableLimits(callable_limits::Error),
     CapabilitiesCk(qsc_rca::errors::Error),
@@ -69,15 +67,19 @@ pub fn lower_hir_to_fir(
 }
 
 pub struct PassContext {
-    capabilities: TargetCapabilityFlags,
     borrow_check: borrowck::Checker,
 }
 
+impl Default for PassContext {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
 impl PassContext {
     #[must_use]
-    pub fn new(capabilities: TargetCapabilityFlags) -> Self {
+    pub fn new() -> Self {
         Self {
-            capabilities,
             borrow_check: borrowck::Checker::default(),
         }
     }
@@ -117,12 +119,6 @@ impl PassContext {
         ReplaceQubitAllocation::new(core, assigner).visit_package(package);
         Validator::default().visit_package(package);
 
-        let base_prof_errors = if self.capabilities == TargetCapabilityFlags::empty() {
-            baseprofck::check_base_profile_compliance(package)
-        } else {
-            Vec::new()
-        };
-
         callable_errors
             .into_iter()
             .map(Error::CallableLimits)
@@ -130,7 +126,6 @@ impl PassContext {
             .chain(spec_errors.into_iter().map(Error::SpecGen))
             .chain(conjugate_errors.into_iter().map(Error::ConjInvert))
             .chain(entry_point_errors)
-            .chain(base_prof_errors.into_iter().map(Error::BaseProfCk))
             .collect()
     }
 
@@ -148,14 +143,8 @@ pub fn run_default_passes(
     core: &Table,
     unit: &mut CompileUnit,
     package_type: PackageType,
-    capabilities: TargetCapabilityFlags,
 ) -> Vec<Error> {
-    PassContext::new(capabilities).run_default_passes(
-        &mut unit.package,
-        &mut unit.assigner,
-        core,
-        package_type,
-    )
+    PassContext::new().run_default_passes(&mut unit.package, &mut unit.assigner, core, package_type)
 }
 
 pub fn run_core_passes(core: &mut CompileUnit) -> Vec<Error> {
@@ -174,13 +163,7 @@ pub fn run_core_passes(core: &mut CompileUnit) -> Vec<Error> {
     ReplaceQubitAllocation::new(&table, &mut core.assigner).visit_package(&mut core.package);
     Validator::default().visit_package(&core.package);
 
-    let base_prof_errors = baseprofck::check_base_profile_compliance(&core.package);
-
-    borrow_errors
-        .into_iter()
-        .map(Error::BorrowCk)
-        .chain(base_prof_errors.into_iter().map(Error::BaseProfCk))
-        .collect()
+    borrow_errors.into_iter().map(Error::BorrowCk).collect()
 }
 
 pub fn run_fir_passes(
diff --git a/language_service/src/compilation.rs b/language_service/src/compilation.rs
index 35f919fa..a3a61602 100644
--- a/language_service/src/compilation.rs
+++ b/language_service/src/compilation.rs
@@ -257,11 +257,6 @@ fn run_fir_passes(
         return;
     }
 
-    if target_profile == Profile::Base {
-        // baseprofchk will handle the case where the target profile is Base
-        return;
-    }
-
     if target_profile == Profile::Unrestricted {
         // no point in running passes on unrestricted profile
         return;
diff --git a/language_service/src/protocol.rs b/language_service/src/protocol.rs
index 2ec8c979..de37d4e3 100644
--- a/language_service/src/protocol.rs
+++ b/language_service/src/protocol.rs
@@ -10,6 +10,7 @@ use qsc_project::Manifest;
 pub struct WorkspaceConfigurationUpdate {
     pub target_profile: Option<Profile>,
     pub package_type: Option<PackageType>,
+    pub language_features: Option<LanguageFeatures>,
 }
 
 #[derive(Debug)]
diff --git a/language_service/src/state.rs b/language_service/src/state.rs
index fa40339f..0706bfd9 100644
--- a/language_service/src/state.rs
+++ b/language_service/src/state.rs
@@ -91,9 +91,9 @@ struct PartialConfiguration {
 }
 
 impl PartialConfiguration {
-    pub fn from_language_features(features: LanguageFeatures) -> Self {
+    pub fn from_language_features(features: Option<LanguageFeatures>) -> Self {
         Self {
-            language_features: Some(features),
+            language_features: features,
             ..Default::default()
         }
     }
@@ -128,7 +128,7 @@ pub(super) struct CompilationStateUpdater<'a> {
 struct LoadManifestResult {
     compilation_uri: Arc<str>,
     sources: Vec<(Arc<str>, Arc<str>)>,
-    language_features: LanguageFeatures,
+    language_features: Option<LanguageFeatures>,
     lints: Vec<LintConfig>,
 }
 
@@ -180,7 +180,7 @@ impl<'a> CompilationStateUpdater<'a> {
             LoadManifestResult {
                 compilation_uri: doc_uri.clone(),
                 sources: vec![(doc_uri.clone(), text.clone())],
-                language_features: LanguageFeatures::default(),
+                language_features: None,
                 lints: Vec::default(),
             }
         });
@@ -228,11 +228,13 @@ impl<'a> CompilationStateUpdater<'a> {
                 Ok(o) => Some(LoadManifestResult {
                     compilation_uri: manifest.compilation_uri(),
                     sources: o.sources,
-                    language_features: manifest
-                        .manifest
-                        .language_features
-                        .iter()
-                        .collect::<LanguageFeatures>(),
+                    language_features: Some(
+                        manifest
+                            .manifest
+                            .language_features
+                            .iter()
+                            .collect::<LanguageFeatures>(),
+                    ),
                     lints: manifest.manifest.lints.clone(),
                 }),
                 Err(e) => {
@@ -254,7 +256,7 @@ impl<'a> CompilationStateUpdater<'a> {
         &mut self,
         mut sources: Vec<(Arc<str>, Arc<str>)>,
         compilation_uri: &Arc<str>,
-        language_features: LanguageFeatures,
+        language_features: Option<LanguageFeatures>,
         lints_config: &[LintConfig],
     ) {
         self.with_state_mut(|state| {
@@ -268,20 +270,22 @@ impl<'a> CompilationStateUpdater<'a> {
                 }
             }
 
+            let compilation_overrides =
+                PartialConfiguration::from_language_features(language_features);
+
+            let configuration = merge_configurations(&compilation_overrides, &self.configuration);
+
             let compilation = Compilation::new(
                 &sources,
-                self.configuration.package_type,
-                self.configuration.target_profile,
-                language_features,
+                configuration.package_type,
+                configuration.target_profile,
+                configuration.language_features,
                 lints_config,
             );
 
             state.compilations.insert(
                 compilation_uri.clone(),
-                (
-                    compilation,
-                    PartialConfiguration::from_language_features(language_features),
-                ),
+                (compilation, compilation_overrides),
             );
         });
     }
@@ -478,6 +482,11 @@ impl<'a> CompilationStateUpdater<'a> {
             self.configuration.target_profile = target_profile;
         }
 
+        if let Some(language_features) = configuration.language_features {
+            need_recompile |= self.configuration.language_features != language_features;
+            self.configuration.language_features = language_features;
+        }
+
         // Possible optimization: some projects will have overrides for these configurations,
         // so workspace updates won't impact them. We could exclude those projects
         // from recompilation, but we don't right now.
@@ -493,9 +502,6 @@ impl<'a> CompilationStateUpdater<'a> {
             for (compilation, package_specific_configuration) in state.compilations.values_mut() {
                 let configuration =
                     merge_configurations(package_specific_configuration, &self.configuration);
-                let language_features = package_specific_configuration
-                    .language_features
-                    .unwrap_or_default();
                 let lints_config = package_specific_configuration
                     .lints_config
                     .clone()
@@ -503,7 +509,7 @@ impl<'a> CompilationStateUpdater<'a> {
                 compilation.recompile(
                     configuration.package_type,
                     configuration.target_profile,
-                    language_features,
+                    configuration.language_features,
                     &lints_config,
                 );
             }
diff --git a/playground/src/editor.tsx b/playground/src/editor.tsx
index 903a61e7..95a6945b 100644
--- a/playground/src/editor.tsx
+++ b/playground/src/editor.tsx
@@ -130,7 +130,7 @@ export function Editor(props: {
 
     const config = {
       sources: [["code", code]],
-      languageFeatures: ["preview-qir-gen"],
+      languageFeatures: [],
       profile: profile,
     } as ProgramConfig;
 
@@ -183,7 +183,7 @@ export function Editor(props: {
     props.evtTarget.clearResults();
     const config = {
       sources: [["code", code]],
-      languageFeatures: ["preview-qir-gen"],
+      languageFeatures: [],
       profile: profile,
     } as ProgramConfig;
 
diff --git a/samples/language/Array.qs b/samples/language/Array.qs
index b46aed19..30f0d1d0 100644
--- a/samples/language/Array.qs
+++ b/samples/language/Array.qs
@@ -23,7 +23,7 @@ namespace MyQuantumApp {
 
         // A basic Int Array literal
         let intArray : Int[] = [1, 2, 3, 4];
-        Message($"Integer Array : {intArray} of length {Length(intArray)}");
+        Message($"Integer Array: {intArray} of length {Length(intArray)}");
 
         // A basic String Array literal
         let stringArray = ["a", "string", "array"];
diff --git a/samples/language/BigInt.qs b/samples/language/BigInt.qs
index 09d8e704..ec753951 100644
--- a/samples/language/BigInt.qs
+++ b/samples/language/BigInt.qs
@@ -11,16 +11,24 @@ namespace MyQuantumApp {
     operation Main() : BigInt {
         // Numbers can be declared in hex, octal, decimal, or binary.
         let foo = 0x42L;
+        Message($"Hexadecimal BigInt: {foo}");
         let foo = 0o42L;
+        Message($"Octal BigInt: {foo}");
         let foo = 42L;
+        Message($"Decimal BigInt: {foo}");
         let foo = 0b101010L;
+        Message($"Binary BigInt: {foo}");
 
         // Numbers can be operated upon in the usual ways, with addition (+), subtraction (-),
         // multiplication (*), division (/), modulo (%), and exponentiation (^).
         let foo = foo + 1L;
+        Message($"Addition result: {foo}");
         let foo = foo % 2L;
+        Message($"Modulo result: {foo}");
         // `BigInt`s being raised to an exponent take an `Int` as the exponent.
         let foo = foo^2;
+        Message($"Exponentiation result: {foo}");
+
         return foo;
     }
 }
diff --git a/samples/language/BitwiseOperators.qs b/samples/language/BitwiseOperators.qs
index 0ee48901..289eb6f3 100644
--- a/samples/language/BitwiseOperators.qs
+++ b/samples/language/BitwiseOperators.qs
@@ -14,33 +14,41 @@ namespace MyQuantumApp {
 
         // The integer value -6.
         let integer = ~~~5;
+        Message($"Bitwise NOT: {integer}");
 
         // The integer value 4.
         let integer = ~~~-5;
+        Message($"Bitwise NOT: {integer}");
 
-        // `&&&` performs a bitwise AND on the bits of two integer.
+        // `&&&` performs a bitwise AND on the bits of two integers.
 
         // The integer value 4.
         let integer = 5 &&& 6;
+        Message($"Bitwise AND: {integer}");
 
         // The integer value 2.
         let integer = -5 &&& 6;
+        Message($"Bitwise AND: {integer}");
 
-        // `|||` performs a bitwise OR on the bits of two integer.
+        // `|||` performs a bitwise OR on the bits of two integers.
 
         // The integer value 7.
         let integer = 5 ||| 6;
+        Message($"Bitwise OR: {integer}");
 
         // The integer value -1.
         let integer = -5 ||| 6;
+        Message($"Bitwise OR: {integer}");
 
-        // `^^^` performs a bitwise XOR on the bits of two integer.
+        // `^^^` performs a bitwise XOR on the bits of two integers.
 
         // The integer value 3.
         let integer = 5 ^^^ 6;
+        Message($"Bitwise XOR: {integer}");
 
         // The integer value -3.
         let integer = -5 ^^^ 6;
+        Message($"Bitwise XOR: {integer}");
 
         // `>>>` performs a signed right bit-shift of a magnitude specified by the
         // right-hand integer on the bits of the left-hand integer.
@@ -48,12 +56,15 @@ namespace MyQuantumApp {
 
         // The integer value 1.
         let integer = 5 >>> 2;
+        Message($"Right Bit-shift: {integer}");
 
         // The integer value -2.
         let integer = -5 >>> 2;
+        Message($"Right Bit-shift: {integer}");
 
         // The integer value 20.
         let integer = 5 >>> -2;
+        Message($"Right Bit-shift: {integer}");
 
         // `<<<` performs a signed left bit-shift of a magnitude specified by the
         // right-hand integer on the bits of the left-hand integer.
@@ -61,11 +72,14 @@ namespace MyQuantumApp {
 
         // The integer value 20.
         let integer = 5 <<< 2;
+        Message($"Left Bit-shift: {integer}");
 
         // The integer value -20.
         let integer = -5 <<< 2;
+        Message($"Left Bit-shift: {integer}");
 
         // The integer value 1.
         let integer = 5 <<< -2;
+        Message($"Left Bit-shift: {integer}");
     }
 }
diff --git a/samples/language/Bool.qs b/samples/language/Bool.qs
index 29ebb270..7c9d8f59 100644
--- a/samples/language/Bool.qs
+++ b/samples/language/Bool.qs
@@ -10,18 +10,24 @@ namespace MyQuantumApp {
     operation Main() : Bool {
         // `Bool`s can be operated upon with boolean operators:
         let andOp = true and true;
+        Message($"AND operation: {andOp}");
+
         let orOp = false or true;
+        Message($"OR operation: {orOp}");
 
         // Comparisons return booleans:
         let eqComparison = 1 == 2;
+        Message($"Equality comparison: {eqComparison}");
 
         // `if` expressions use boolean expressions as their conditions:
         if (2 == 2) {
+            Message("2 equals 2");
             // do something
         } else {
+            Message("2 does not equal 2");
             // do something else
         }
 
         return true;
     }
-}
\ No newline at end of file
+}
diff --git a/samples/language/ComparisonOperators.qs b/samples/language/ComparisonOperators.qs
index befdbcb3..c068ba10 100644
--- a/samples/language/ComparisonOperators.qs
+++ b/samples/language/ComparisonOperators.qs
@@ -14,63 +14,79 @@ namespace MyQuantumApp {
 
         // The Boolean value `true`.
         let boolean = 4 == 4;
+        Message($"Equality comparison: {boolean}");
 
         // The Boolean value `false`.
         let boolean = 4 == 6;
+        Message($"Equality comparison: {boolean}");
 
         // `!=` tests if the first value is not equivalent to the second value.
         // It is the opposite of `==`.
 
         // The Boolean value `false`.
         let boolean = 4 != 4;
+        Message($"Inequality comparison: {boolean}");
 
         // The Boolean value `true`.
         let boolean = 4 != 6;
+        Message($"Inequality comparison: {boolean}");
 
         // `<` tests if the first value is strictly less than the second value.
 
         // The Boolean value `false`.
         let boolean = 4 < 4;
+        Message($"Less than comparison: {boolean}");
 
         // The Boolean value `true`.
         let boolean = 4 < 6;
+        Message($"Less than comparison: {boolean}");
 
         // The Boolean value `false`.
         let boolean = 6 < 4;
+        Message($"Less than comparison: {boolean}");
 
         // `<=` tests if the first value is less than or equivalent to
         // the second value.
 
         // The Boolean value `true`.
         let boolean = 4 <= 4;
+        Message($"Less than or equal comparison: {boolean}");
 
         // The Boolean value `true`.
         let boolean = 4 <= 6;
+        Message($"Less than or equal comparison: {boolean}");
 
         // The Boolean value `false`.
         let boolean = 6 <= 4;
+        Message($"Less than or equal comparison: {boolean}");
 
         // `>` tests if the first value is strictly greater than the second value.
 
         // The Boolean value `false`.
         let boolean = 4 > 4;
+        Message($"Greater than comparison: {boolean}");
 
         // The Boolean value `false`.
         let boolean = 4 > 6;
+        Message($"Greater than comparison: {boolean}");
 
         // The Boolean value `true`.
         let boolean = 6 > 4;
+        Message($"Greater than comparison: {boolean}");
 
         // `>=` tests if the first value is greater than or equivalent to
         // the second value.
 
         // The Boolean value `true`.
         let boolean = 4 >= 4;
+        Message($"Greater than or equal comparison: {boolean}");
 
         // The Boolean value `false`.
         let boolean = 4 >= 6;
+        Message($"Greater than or equal comparison: {boolean}");
 
         // The Boolean value `true`.
         let boolean = 6 >= 4;
+        Message($"Greater than or equal comparison: {boolean}");
     }
 }
diff --git a/samples/language/ConditionalBranching.qs b/samples/language/ConditionalBranching.qs
index 876a3d99..c3a1263d 100644
--- a/samples/language/ConditionalBranching.qs
+++ b/samples/language/ConditionalBranching.qs
@@ -32,10 +32,9 @@ namespace MyQuantumApp {
         } else {
             Message("It is way too hot");
         }
-
-        let fahrenheit = 40;
-
+        let fahrenheit = -40;
         // `if` can also be used as an expression, to conditionally return a value.
         let absoluteValue = if fahrenheit > 0 { fahrenheit } else { fahrenheit * -1 };
+        Message($"Absolute value of {fahrenheit} is {absoluteValue}");
     }
 }
diff --git a/samples/language/CopyAndUpdateOperator.qs b/samples/language/CopyAndUpdateOperator.qs
index 33ea3e0b..94e053aa 100644
--- a/samples/language/CopyAndUpdateOperator.qs
+++ b/samples/language/CopyAndUpdateOperator.qs
@@ -19,15 +19,18 @@ namespace MyQuantumApp {
         // `new_array` is an array with values `[10, 11, 100, 13]`.
         // `array` is unchanged.
         let new_array = array w/ 2 <- 100;
+        Message($"Updated array: {new_array}");
 
         // `new_array` is an array with values `[10, 100, 12, 200]`.
         // `array` is unchanged.
         let new_array = array
             w/ 1 <- 100
             w/ 3 <- 200;
+        Message($"Updated array: {new_array}");
 
         // `new_struct` is a Pair with value `Pair(20, 100)`.
         // `struct` is unchanged.
         let new_struct = struct w/ second <- 100;
+        Message($"Updated struct: (first:{new_struct::first}, second:{new_struct::second})");
     }
 }
diff --git a/samples/language/DataTypes.qs b/samples/language/DataTypes.qs
index 3276b461..57e618da 100644
--- a/samples/language/DataTypes.qs
+++ b/samples/language/DataTypes.qs
@@ -9,7 +9,7 @@
 /// and operation types.
 namespace MyQuantumApp {
 
-    /// In the below code, all varibles have type annotations to showcase their type.
+    /// In the below code, all variables have type annotations to showcase their type.
     @EntryPoint()
     operation MeasureOneQubit() : Unit {
         // Notably, Qubits are allocated with the `use` keyword instead of declared with the `let`
@@ -27,9 +27,16 @@ namespace MyQuantumApp {
         // BigInt literals are always suffixed with an L, and can be declared in
         // binary, octal, decimal, or hexadecimal.
         let binaryBigInt : BigInt = 0b101010L;
+        Message($"Binary BigInt: {binaryBigInt}");
+
         let octalBigInt = 0o52L;
+        Message($"Octal BigInt: {octalBigInt}");
+
         let decimalBigInt = 42L;
+        Message($"Decimal BigInt: {decimalBigInt}");
+
         let hexadecimalBigInt = 0x2aL;
+        Message($"Hexadecimal BigInt: {hexadecimalBigInt}");
 
         // A double-precision 64-bit floating-point number.
         let double = 42.0;
@@ -63,11 +70,12 @@ namespace MyQuantumApp {
         newtype ComplexBool = (Real : Double, Imaginary : Double, Bool);
         // Instantiation of the above UDT.
         let complex = ComplexBool(42.0, 0.0, false);
+        let (real, imaginary, anonymous) = complex!;
+        Message($"Complex Bool: (real: {real}, imaginary: {imaginary}, anonymous: {anonymous})");
 
         // A function that takes an integer and returns a boolean. This variable declaration
         // uses a Lambda function as its right hand side.
         // The function signature is provided as an annotation here, for clarity.
         let functionType : Int => Bool = (int) => int == 0;
     }
-
 }
diff --git a/samples/language/Int.qs b/samples/language/Int.qs
index 481838d7..b8c4b614 100644
--- a/samples/language/Int.qs
+++ b/samples/language/Int.qs
@@ -10,15 +10,28 @@ namespace MyQuantumApp {
     operation Main() : Int {
         // Numbers can be declared in hex, octal, decimal, or binary.
         let foo = 0x42;
+        Message($"Hexadecimal: {foo}");
+
         let foo = 0o42;
+        Message($"Octal: {foo}");
+
         let foo = 42;
+        Message($"Decimal: {foo}");
+
         let foo = 0b101010;
+        Message($"Binary: {foo}");
 
         // Numbers can be operated upon in the usual ways, with addition (+), subtraction (-),
         // multiplication (*), division (/), modulo (%), and exponentiation (^).
         let foo = foo + 1;
+        Message($"After addition: {foo}");
+
         let foo = foo % 2;
+        Message($"After modulo: {foo}");
+
         let foo = foo^2;
+        Message($"After exponentiation: {foo}");
+
         return foo;
     }
 }
\ No newline at end of file
diff --git a/samples/language/LambdaExpression.qs b/samples/language/LambdaExpression.qs
index 26e9c646..822475b3 100644
--- a/samples/language/LambdaExpression.qs
+++ b/samples/language/LambdaExpression.qs
@@ -3,7 +3,7 @@
 ///
 /// # Description
 /// A lambda expression creates an anonymous function or operation, typically
-/// used for local encapsulated functionality. Lambdas offer low sytactic
+/// used for local encapsulated functionality. Lambdas offer low syntactic
 /// overhead, foregoing a fully namespaced function declaration, making them
 /// useful for single-use or utility functions.
 namespace MyQuantumApp {
@@ -13,6 +13,7 @@ namespace MyQuantumApp {
         // A lambda function is defined with an arrow `->`.
         // The below function takes two inputs and adds them.
         let add = (x, y) -> x + y;
+        Message($"Lambda add function result: {add(2, 3)}");
 
         // A lambda operation is defined with a fat arrow `=>`.
         // The below operation closes over `qubit` and applies
@@ -26,10 +27,11 @@ namespace MyQuantumApp {
         // that combines two elements into one.
         let intArray = [1, 2, 3, 4, 5];
         let sum = Fold(add, 0, intArray);
+        Message($"Sum of array using Fold: {sum}");
 
         // `Map` takes a callable and applies it to all elements in
         // an array
         let incremented = Mapped(x -> x + 1, intArray);
-
+        Message($"Array after incrementing each element using Map: {incremented}");
     }
 }
\ No newline at end of file
diff --git a/samples/language/Operations.qs b/samples/language/Operations.qs
index 3a8b423e..928a1ec3 100644
--- a/samples/language/Operations.qs
+++ b/samples/language/Operations.qs
@@ -16,6 +16,7 @@ namespace MyQuantumApp {
         H(q);
         // Now we measure the qubit in Z-basis using the `M` operation.
         let result = M(q);
+        Message($"Measurement result: {result}");
         // We reset the qubit before releasing it using the `Reset` operation.
         Reset(q);
         // Finally, we return the result of the measurement.
diff --git a/samples/language/PartialApplication.qs b/samples/language/PartialApplication.qs
index 9c393600..9413fb19 100644
--- a/samples/language/PartialApplication.qs
+++ b/samples/language/PartialApplication.qs
@@ -19,6 +19,7 @@ namespace MyQuantumApp {
 
         // we can add `1` to any number using our partially applied function
         let five = incrementByOne(4);
+        Message($"five = incrementByOne(4) => {five}");
 
         // More than one underscore can be used to define a function that takes
         // multiple arguments.
@@ -30,6 +31,7 @@ namespace MyQuantumApp {
         let intArray = [1, 2, 3, 4, 5];
         // The below expression increments all values in an array by 1
         let incremented = Mapped(Add(_, 1), intArray);
+        Message($"Incremented array: {incremented}");
     }
 
     function Add(x : Int, y : Int) : Int {
diff --git a/samples/language/Pauli.qs b/samples/language/Pauli.qs
index a7ee59fe..ca59ae42 100644
--- a/samples/language/Pauli.qs
+++ b/samples/language/Pauli.qs
@@ -11,9 +11,11 @@ namespace MyQuantumApp {
 
         // A `Pauli` can be declared as a literal.
         let pauliDimension = PauliX;
+        Message($"Pauli dimension: {pauliDimension}");
 
         // Measuring along a dimension returns a `Result`:
         let result = Measure([pauliDimension], [q]);
+        Message($"Measurement result: {result}");
 
         return result;
     }
diff --git a/vscode/package.json b/vscode/package.json
index 8974520f..fbfce4a0 100644
--- a/vscode/package.json
+++ b/vscode/package.json
@@ -110,16 +110,6 @@
             "The Adaptive_RI target profile includes all of the required Adaptive Profile capabilities, as well as the optional integer computation and qubit reset capabilities, as defined by the QIR specification."
           ],
           "markdownDescription": "Setting the target profile allows the Q# extension to generate programs that are compatible with a specific target. The target is the hardware or simulator which will be used to run the Q# program. [Learn more](https://aka.ms/qdk.qir)"
-        },
-        "Q#.qir.experimentalCodeGeneration": {
-          "type": "boolean",
-          "default": false,
-          "markdownDescription": "Enable the experimental QIR code generation functionality. (Required to generate code targeting the Adaptive Profile). [Learn more](https://aka.ms/qdk.qir)"
-        },
-        "Q#.qir.enableAdaptiveProfile": {
-          "type": "boolean",
-          "default": false,
-          "markdownDescription": "Enable Adaptive Profile as a target. [Learn more](https://aka.ms/qdk.qir)"
         }
       }
     },
diff --git a/vscode/src/config.ts b/vscode/src/config.ts
index 1b0b7d59..bd045d4a 100644
--- a/vscode/src/config.ts
+++ b/vscode/src/config.ts
@@ -41,17 +41,3 @@ export function getTargetFriendlyName(targetProfile?: string) {
       return "Q#: invalid";
   }
 }
-
-export function getEnablePreviewQirGen(): boolean {
-  return vscode.workspace.getConfiguration("Q#").get<boolean>(
-    "qir.experimentalCodeGeneration",
-    false, // The default value should be set in `package.json` as well.
-  );
-}
-
-export function getEnableAdaptiveProfile(): boolean {
-  return vscode.workspace.getConfiguration("Q#").get<boolean>(
-    "qir.enableAdaptiveProfile",
-    false, // The default value should be set in `package.json` as well.
-  );
-}
diff --git a/vscode/src/qirGeneration.ts b/vscode/src/qirGeneration.ts
index 1ae5f7f7..1630bd31 100644
--- a/vscode/src/qirGeneration.ts
+++ b/vscode/src/qirGeneration.ts
@@ -6,7 +6,7 @@ import { getCompilerWorker, log, ProgramConfig } from "qsharp-lang";
 import { isQsharpDocument } from "./common";
 import { EventType, sendTelemetryEvent } from "./telemetry";
 import { getRandomGuid } from "./utils";
-import { getTarget, getEnablePreviewQirGen, setTarget } from "./config";
+import { getTarget, setTarget } from "./config";
 import { loadProject } from "./projectSystem";
 
 const generateQirTimeoutMs = 30000;
@@ -30,26 +30,25 @@ export async function getQirForActiveWindow(): Promise<string> {
     );
   }
 
-  // Check that the current target is base profile, and current doc has no errors.
+  // Check that the current target is base or adaptive_ri profile, and current doc has no errors.
   const targetProfile = getTarget();
-  const enablePreviewQirGen = getEnablePreviewQirGen();
-  if (targetProfile !== "base") {
-    const allowed = targetProfile === "adaptive_ri" && enablePreviewQirGen;
-    if (!allowed) {
-      const result = await vscode.window.showWarningMessage(
-        "Submitting to Azure is only supported when targeting the QIR base profile.",
-        { modal: true },
-        { title: "Change the QIR target profile and continue", action: "set" },
-        { title: "Cancel", action: "cancel", isCloseAffordance: true },
+  if (targetProfile === "unrestricted") {
+    const result = await vscode.window.showWarningMessage(
+      "Submitting to Azure is only supported when targeting the QIR base or adaptive_ri profile.",
+      { modal: true },
+      {
+        title: "Set the QIR target profile to Base and continue",
+        action: "set",
+      },
+      { title: "Cancel", action: "cancel", isCloseAffordance: true },
+    );
+    if (result?.action !== "set") {
+      throw new QirGenerationError(
+        "Submitting to Azure is not supported when using the unrestricted profile. " +
+          "Please update the QIR target via the status bar selector or extension settings.",
       );
-      if (result?.action !== "set") {
-        throw new QirGenerationError(
-          "Submitting to Azure is only supported when targeting the QIR base profile. " +
-            "Please update the QIR target via the status bar selector or extension settings.",
-        );
-      } else {
-        setTarget("base");
-      }
+    } else {
+      setTarget("base");
     }
   }
   let sources: [string, string][] = [];
@@ -81,9 +80,7 @@ export async function getQirForActiveWindow(): Promise<string> {
     const associationId = getRandomGuid();
     const start = performance.now();
     sendTelemetryEvent(EventType.GenerateQirStart, { associationId }, {});
-    if (enablePreviewQirGen) {
-      languageFeatures.push("preview-qir-gen");
-    }
+
     const config = {
       sources,
       languageFeatures,
@@ -100,8 +97,8 @@ export async function getQirForActiveWindow(): Promise<string> {
   } catch (e: any) {
     log.error("Codegen error. ", e.toString());
     throw new QirGenerationError(
-      `Code generation failed due to error: "${e.toString()}". Please ensure the code is compatible with the QIR base profile ` +
-        "by setting the target QIR profile to 'base' and fixing any errors.",
+      `Code generation failed due to error: "${e.toString()}". Please ensure the code is compatible with a QIR profile ` +
+        "by setting the target QIR profile to 'base' or 'adaptive_ri' and fixing any errors.",
     );
   } finally {
     worker.terminate();
diff --git a/vscode/src/statusbar.ts b/vscode/src/statusbar.ts
index 132517ce..e24af6ec 100644
--- a/vscode/src/statusbar.ts
+++ b/vscode/src/statusbar.ts
@@ -4,12 +4,7 @@
 import { log, TargetProfile } from "qsharp-lang";
 import * as vscode from "vscode";
 import { isQsharpDocument } from "./common";
-import {
-  getEnableAdaptiveProfile,
-  getTarget,
-  getTargetFriendlyName,
-  setTarget,
-} from "./config";
+import { getTarget, getTargetFriendlyName, setTarget } from "./config";
 
 export function activateTargetProfileStatusBarItem(): vscode.Disposable[] {
   const disposables = [];
@@ -86,7 +81,7 @@ function registerTargetProfileCommand() {
     "qsharp-vscode.setTargetProfile",
     async () => {
       const target = await vscode.window.showQuickPick(
-        getTargetProfiles().map((profile) => ({
+        targetProfiles.map((profile) => ({
           label: profile.uiText,
         })),
         { placeHolder: "Select the QIR target profile" },
@@ -105,20 +100,6 @@ const targetProfiles = [
   { configName: "unrestricted", uiText: "Q#: unrestricted" },
 ];
 
-function getTargetProfiles(): {
-  configName: string;
-  uiText: string;
-}[] {
-  const allow_adaptive_ri = getEnableAdaptiveProfile();
-  if (allow_adaptive_ri) {
-    return targetProfiles;
-  } else {
-    return targetProfiles.filter(
-      (profile) => profile.configName !== "adaptive_ri",
-    );
-  }
-}
-
 function getTargetProfileSetting(uiText: string): TargetProfile {
   switch (uiText) {
     case "Q#: QIR base":
diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml
index 5a437d35..2027eea0 100644
--- a/wasm/Cargo.toml
+++ b/wasm/Cargo.toml
@@ -19,7 +19,7 @@ futures-util = { workspace = true }
 js-sys = { workspace = true }
 katas = { path = "../katas"}
 log = { workspace = true }
-miette = { workspace = true}
+miette = { workspace = true }
 num-bigint = { workspace = true }
 num-complex = { workspace = true }
 qsls = { path = "../language_service" }
diff --git a/wasm/src/language_service.rs b/wasm/src/language_service.rs
index 304c2ab9..e3abf60c 100644
--- a/wasm/src/language_service.rs
+++ b/wasm/src/language_service.rs
@@ -100,6 +100,9 @@ impl LanguageService {
                     "exe" => PackageType::Exe,
                     _ => panic!("invalid package type"),
                 }),
+                language_features: config
+                    .languageFeatures
+                    .map(|features| features.iter().collect::<LanguageFeatures>()),
             });
     }
 
@@ -331,10 +334,12 @@ serializable_type! {
     {
         pub targetProfile: Option<String>,
         pub packageType: Option<String>,
+        pub languageFeatures: Option<Vec<String>>,
     },
     r#"export interface IWorkspaceConfiguration {
         targetProfile?: TargetProfile;
         packageType?: "exe" | "lib";
+        languageFeatures?: LanguageFeatures[];
     }"#,
     IWorkspaceConfiguration
 }
diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs
index ac1fe003..12099c98 100644
--- a/wasm/src/lib.rs
+++ b/wasm/src/lib.rs
@@ -7,6 +7,7 @@
 use diagnostic::{interpret_errors_into_vs_diagnostics, VSDiagnostic};
 use katas::check_solution;
 use language_service::IOperationInfo;
+use miette::JSONReportHandler;
 use num_bigint::BigUint;
 use num_complex::Complex64;
 use project_system::into_async_rust_fn_with;
@@ -22,7 +23,6 @@ use qsc::{
     LanguageFeatures, PackageStore, PackageType, SourceContents, SourceMap, SourceName, SparseSim,
     TargetCapabilityFlags,
 };
-use qsc_codegen::qir_base::generate_qir;
 use resource_estimator::{self as re, estimate_entry};
 use serde::{Deserialize, Serialize};
 use serde_json::json;
@@ -86,39 +86,30 @@ pub fn get_qir(
     if profile == Profile::Unrestricted {
         return Err("Invalid target profile for QIR generation".to_string());
     }
-    if language_features.contains(LanguageFeatures::PreviewQirGen) {
-        qsc::codegen::get_qir(sources, language_features, profile.into())
-    } else {
-        _get_qir(sources, language_features)
-    }
-}
-
-// allows testing without wasm bindings.
-fn _get_qir(sources: SourceMap, language_features: LanguageFeatures) -> Result<String, String> {
-    let core = compile::core();
-    let mut store = PackageStore::new(core);
-    let std = compile::std(&store, Profile::Base.into());
-    let std = store.insert(std);
 
-    let (unit, errors) = qsc::compile::compile(
-        &store,
-        &[std],
-        sources,
-        PackageType::Exe,
-        Profile::Base.into(),
-        language_features,
-    );
-
-    // Ensure it compiles before trying to add it to the store.
-    if !errors.is_empty() {
-        // This should never happen, as the program should be checked for errors before trying to
-        // generate code for it. But just in case, simply report the failure.
-        return Err("Failed to generate QIR".to_string());
-    }
+    _get_qir(sources, language_features, profile.into())
+}
 
-    let package = store.insert(unit);
+pub(crate) fn _get_qir(
+    sources: SourceMap,
+    language_features: LanguageFeatures,
+    capabilities: TargetCapabilityFlags,
+) -> Result<String, String> {
+    qsc::codegen::get_qir(sources, language_features, capabilities).map_err(|errors| {
+        let mut msg = String::new();
+        msg.push('[');
+        for error in errors {
+            if msg.len() > 1 {
+                msg.push(',');
+            }
+            JSONReportHandler::new()
+                .render_report(&mut msg, &error)
+                .expect("rendering should succeed");
+        }
 
-    generate_qir(&store, package).map_err(|e| e.0.to_string())
+        msg.push(']');
+        msg
+    })
 }
 
 #[wasm_bindgen]
@@ -494,5 +485,10 @@ pub fn generate_docs(
 
 #[wasm_bindgen(typescript_custom_section)]
 const TARGET_PROFILE: &'static str = r#"
-export type TargetProfile = "base" | "adaptive_ri" |"unrestricted";
+export type TargetProfile = "base" | "adaptive_ri" | "unrestricted";
+"#;
+
+#[wasm_bindgen(typescript_custom_section)]
+const LANGUAGE_FEATURES: &'static str = r#"
+export type LanguageFeatures = "v2-preview-syntax";
 "#;


Test patch:
diff --git a/compiler/qsc/src/codegen/tests.rs b/compiler/qsc/src/codegen/tests.rs
index 40160e82..29505a6c 100644
--- a/compiler/qsc/src/codegen/tests.rs
+++ b/compiler/qsc/src/codegen/tests.rs
@@ -22,7 +22,37 @@ fn code_with_errors_returns_errors() {
 
     expect![[r#"
         Err(
-            "Failed to generate QIR. Could not compile sources.:\nsyntax error\n",
+            [
+                Compile(
+                    WithSource {
+                        sources: [
+                            Source {
+                                name: "test.qs",
+                                contents: "namespace Test {\n            @EntryPoint()\n            operation Main() : Unit {\n                use q = Qubit()\n                let pi_over_two = 4.0 / 2.0;\n            }\n        }",
+                                offset: 0,
+                            },
+                        ],
+                        error: Frontend(
+                            Error(
+                                Parse(
+                                    Error(
+                                        Token(
+                                            Semi,
+                                            Keyword(
+                                                Let,
+                                            ),
+                                            Span {
+                                                lo: 129,
+                                                hi: 132,
+                                            },
+                                        ),
+                                    ),
+                                ),
+                            ),
+                        ),
+                    },
+                ),
+            ],
         )
     "#]]
     .assert_debug_eq(&get_qir(sources, language_features, capabilities));
diff --git a/compiler/qsc/src/interpret/tests.rs b/compiler/qsc/src/interpret/tests.rs
index 3ecba807..cb30c785 100644
--- a/compiler/qsc/src/interpret/tests.rs
+++ b/compiler/qsc/src/interpret/tests.rs
@@ -654,7 +654,7 @@ mod given_interpreter {
         }
 
         #[test]
-        fn normal_qirgen() {
+        fn base_qirgen() {
             let mut interpreter = Interpreter::new(
                 true,
                 SourceMap::default(),
@@ -674,37 +674,22 @@ mod given_interpreter {
                 %Qubit = type opaque
 
                 define void @ENTRYPOINT__main() #0 {
+                block_0:
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
                   call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
+                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
                   call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
                   ret void
                 }
 
-                declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__rx__body(double, %Qubit*)
-                declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__ry__body(double, %Qubit*)
-                declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__rz__body(double, %Qubit*)
-                declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
                 declare void @__quantum__qis__h__body(%Qubit*)
-                declare void @__quantum__qis__s__body(%Qubit*)
-                declare void @__quantum__qis__s__adj(%Qubit*)
-                declare void @__quantum__qis__t__body(%Qubit*)
-                declare void @__quantum__qis__t__adj(%Qubit*)
-                declare void @__quantum__qis__x__body(%Qubit*)
-                declare void @__quantum__qis__y__body(%Qubit*)
-                declare void @__quantum__qis__z__body(%Qubit*)
-                declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
+
+                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
+
                 declare void @__quantum__rt__result_record_output(%Result*, i8*)
-                declare void @__quantum__rt__array_record_output(i64, i8*)
-                declare void @__quantum__rt__tuple_record_output(i64, i8*)
+
+                declare void @__quantum__qis__mz__body(%Qubit*, %Result*) #1
 
                 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
                 attributes #1 = { "irreversible" }
@@ -924,37 +909,22 @@ mod given_interpreter {
                 %Qubit = type opaque
 
                 define void @ENTRYPOINT__main() #0 {
+                block_0:
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
                   call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
+                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
                   call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
                   ret void
                 }
 
-                declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__rx__body(double, %Qubit*)
-                declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__ry__body(double, %Qubit*)
-                declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__rz__body(double, %Qubit*)
-                declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
                 declare void @__quantum__qis__h__body(%Qubit*)
-                declare void @__quantum__qis__s__body(%Qubit*)
-                declare void @__quantum__qis__s__adj(%Qubit*)
-                declare void @__quantum__qis__t__body(%Qubit*)
-                declare void @__quantum__qis__t__adj(%Qubit*)
-                declare void @__quantum__qis__x__body(%Qubit*)
-                declare void @__quantum__qis__y__body(%Qubit*)
-                declare void @__quantum__qis__z__body(%Qubit*)
-                declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
+
+                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
+
                 declare void @__quantum__rt__result_record_output(%Result*, i8*)
-                declare void @__quantum__rt__array_record_output(i64, i8*)
-                declare void @__quantum__rt__tuple_record_output(i64, i8*)
+
+                declare void @__quantum__qis__mz__body(%Qubit*, %Result*) #1
 
                 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
                 attributes #1 = { "irreversible" }
@@ -993,37 +963,22 @@ mod given_interpreter {
                 %Qubit = type opaque
 
                 define void @ENTRYPOINT__main() #0 {
+                block_0:
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
                   call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
+                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
                   call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
                   ret void
                 }
 
-                declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__rx__body(double, %Qubit*)
-                declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__ry__body(double, %Qubit*)
-                declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__rz__body(double, %Qubit*)
-                declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
                 declare void @__quantum__qis__h__body(%Qubit*)
-                declare void @__quantum__qis__s__body(%Qubit*)
-                declare void @__quantum__qis__s__adj(%Qubit*)
-                declare void @__quantum__qis__t__body(%Qubit*)
-                declare void @__quantum__qis__t__adj(%Qubit*)
-                declare void @__quantum__qis__x__body(%Qubit*)
-                declare void @__quantum__qis__y__body(%Qubit*)
-                declare void @__quantum__qis__z__body(%Qubit*)
-                declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
+
+                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
+
                 declare void @__quantum__rt__result_record_output(%Result*, i8*)
-                declare void @__quantum__rt__array_record_output(i64, i8*)
-                declare void @__quantum__rt__tuple_record_output(i64, i8*)
+
+                declare void @__quantum__qis__mz__body(%Qubit*, %Result*) #1
 
                 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
                 attributes #1 = { "irreversible" }
@@ -1102,37 +1057,22 @@ mod given_interpreter {
                 %Qubit = type opaque
 
                 define void @ENTRYPOINT__main() #0 {
+                block_0:
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
                   call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
+                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
                   call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
                   ret void
                 }
 
-                declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__rx__body(double, %Qubit*)
-                declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__ry__body(double, %Qubit*)
-                declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__rz__body(double, %Qubit*)
-                declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
                 declare void @__quantum__qis__h__body(%Qubit*)
-                declare void @__quantum__qis__s__body(%Qubit*)
-                declare void @__quantum__qis__s__adj(%Qubit*)
-                declare void @__quantum__qis__t__body(%Qubit*)
-                declare void @__quantum__qis__t__adj(%Qubit*)
-                declare void @__quantum__qis__x__body(%Qubit*)
-                declare void @__quantum__qis__y__body(%Qubit*)
-                declare void @__quantum__qis__z__body(%Qubit*)
-                declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
+
+                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
+
                 declare void @__quantum__rt__result_record_output(%Result*, i8*)
-                declare void @__quantum__rt__array_record_output(i64, i8*)
-                declare void @__quantum__rt__tuple_record_output(i64, i8*)
+
+                declare void @__quantum__qis__mz__body(%Qubit*, %Result*) #1
 
                 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
                 attributes #1 = { "irreversible" }
@@ -1184,37 +1124,22 @@ mod given_interpreter {
                 %Qubit = type opaque
 
                 define void @ENTRYPOINT__main() #0 {
+                block_0:
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
                   call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
                   call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
+                  call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
                   call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
                   ret void
                 }
 
-                declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__rx__body(double, %Qubit*)
-                declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__ry__body(double, %Qubit*)
-                declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-                declare void @__quantum__qis__rz__body(double, %Qubit*)
-                declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
                 declare void @__quantum__qis__h__body(%Qubit*)
-                declare void @__quantum__qis__s__body(%Qubit*)
-                declare void @__quantum__qis__s__adj(%Qubit*)
-                declare void @__quantum__qis__t__body(%Qubit*)
-                declare void @__quantum__qis__t__adj(%Qubit*)
-                declare void @__quantum__qis__x__body(%Qubit*)
-                declare void @__quantum__qis__y__body(%Qubit*)
-                declare void @__quantum__qis__z__body(%Qubit*)
-                declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-                declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
+
+                declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
+
                 declare void @__quantum__rt__result_record_output(%Result*, i8*)
-                declare void @__quantum__rt__array_record_output(i64, i8*)
-                declare void @__quantum__rt__tuple_record_output(i64, i8*)
+
+                declare void @__quantum__qis__mz__body(%Qubit*, %Result*) #1
 
                 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
                 attributes #1 = { "irreversible" }
@@ -1246,9 +1171,9 @@ mod given_interpreter {
             is_error(
                 &res,
                 &expect![[r#"
-                non-Result return type in entry expression
-                   [<entry>] [1]
-            "#]],
+                    cannot use an integer value as an output
+                       [<entry>] [1]
+                "#]],
             );
         }
 
diff --git a/compiler/qsc_codegen/src/qir_base/tests.rs b/compiler/qsc_codegen/src/qir_base/tests.rs
deleted file mode 100644
index 8cf1af5f..00000000
--- a/compiler/qsc_codegen/src/qir_base/tests.rs
+++ /dev/null
@@ -1,1657 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-#![allow(clippy::too_many_lines)]
-#![allow(clippy::needless_raw_string_hashes)]
-
-use std::sync::Arc;
-
-use expect_test::{expect, Expect};
-use indoc::indoc;
-use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
-use qsc_frontend::compile::{self, compile, PackageStore, SourceMap};
-use qsc_passes::{run_core_passes, run_default_passes, PackageType};
-
-use crate::qir_base::generate_qir;
-
-fn check(program: &str, expr: Option<&str>, expect: &Expect) {
-    let mut core = compile::core();
-    assert!(run_core_passes(&mut core).is_empty());
-    let mut store = PackageStore::new(core);
-    let mut std = compile::std(&store, TargetCapabilityFlags::empty());
-    assert!(run_default_passes(
-        store.core(),
-        &mut std,
-        PackageType::Lib,
-        TargetCapabilityFlags::empty()
-    )
-    .is_empty());
-    let std = store.insert(std);
-
-    let expr_as_arc: Option<Arc<str>> = expr.map(|s| Arc::from(s.to_string()));
-    let sources = SourceMap::new([("test".into(), program.into())], expr_as_arc);
-
-    let mut unit = compile(
-        &store,
-        &[std],
-        sources,
-        TargetCapabilityFlags::empty(),
-        LanguageFeatures::default(),
-    );
-    assert!(unit.errors.is_empty(), "{:?}", unit.errors);
-    assert!(run_default_passes(
-        store.core(),
-        &mut unit,
-        PackageType::Exe,
-        TargetCapabilityFlags::empty()
-    )
-    .is_empty());
-    let package = store.insert(unit);
-
-    let qir = generate_qir(&store, package);
-    match qir {
-        Ok(qir) => expect.assert_eq(&qir),
-        Err((err, _)) => expect.assert_debug_eq(&err),
-    }
-}
-
-#[test]
-fn simple_entry_program_is_valid() {
-    check(
-        indoc! {r#"
-    namespace Sample {
-        @EntryPoint()
-        operation Entry() : Result
-        {
-            use q = Qubit();
-            H(q);
-            M(q)
-        }
-    }
-        "#},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn simple_program_is_valid() {
-    check(
-        "",
-        Some(indoc! {r#"
-        {
-            use q = Qubit();
-            H(q);
-            M(q)
-        }
-        "#}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn output_recording_array() {
-    check(
-        "",
-        Some(indoc! {"{use q = Qubit(); [M(q), M(q)]}"}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__rt__array_record_output(i64 2, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="3" "required_num_results"="2" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn output_recording_tuple() {
-    check(
-        "",
-        Some(indoc! {"{use q = Qubit(); (M(q), M(q))}"}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="3" "required_num_results"="2" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn reset_allocates_new_qubit_id() {
-    check(
-        "",
-        Some(indoc! {"{use q = Qubit(); H(q); Reset(q); H(q); M(q)}"}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="3" "required_num_results"="1" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn reuse_after_measurement_uses_fresh_aux_qubit_id() {
-    check(
-        "",
-        Some(indoc! {"{use q = Qubit(); H(q); M(q); H(q); M(q)}"}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="3" "required_num_results"="2" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn qubit_allocation_allows_reuse_of_unmeasured_qubits() {
-    check(
-        "",
-        Some(indoc! {"{
-            { use (c, q) = (Qubit(), Qubit()); CNOT(c, q); MResetZ(q); }
-            { use (c, q) = (Qubit(), Qubit()); CNOT(c, q); MResetZ(q) }
-        }"}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="3" "required_num_results"="2" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn verify_all_intrinsics() {
-    check(
-        "",
-        Some(indoc! {"{
-            use (q1, q2, q3) = (Qubit(), Qubit(), Qubit());
-            CCNOT(q1, q2, q3);
-            CX(q1, q2);
-            CY(q1, q2);
-            CZ(q1, q2);
-            Rx(0.0, q1);
-            Rxx(0.0, q1, q2);
-            Ry(0.0, q1);
-            Ryy(0.0, q1, q2);
-            Rz(0.0, q1);
-            Rzz(0.0, q1, q2);
-            H(q1);
-            S(q1);
-            Adjoint S(q1);
-            T(q1);
-            Adjoint T(q1);
-            X(q1);
-            Y(q1);
-            Z(q1);
-            SWAP(q1, q2);
-            Reset(q1);
-            (M(q1),
-            Microsoft.Quantum.Measurement.MResetZ(q1))
-        }"}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__ccx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cy__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__rx__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__rxx__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__ry__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__ryy__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__rzz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__s__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__s__adj(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__y__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__z__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__swap__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 4 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="5" "required_num_results"="2" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn complex_program_is_valid() {
-    check(
-        "",
-        Some(indoc! {"{
-            open Microsoft.Quantum.Math;
-
-            operation SWAPfromExp(q1 : Qubit, q2 : Qubit) : Unit is Ctl + Adj {
-                let theta  = PI() / 4.0;
-                Exp([PauliX, PauliX], theta, [q1, q2]);
-                Exp([PauliY, PauliY], theta, [q1, q2]);
-                Exp([PauliZ, PauliZ], theta, [q1, q2]);
-            }
-
-            use (aux, ctls, qs) = (Qubit(), Qubit[3], Qubit[2]);
-            within {
-                H(aux);
-                ApplyToEachA(CNOT(aux, _), ctls + qs);
-            }
-            apply {
-                Controlled SWAPfromExp(ctls, (qs[0], qs[1]));
-
-                Controlled Adjoint SWAP(ctls, (qs[0], qs[1]));
-            }
-
-            MResetEachZ([aux] + ctls + qs)
-        }"}),
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 5 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__rz__body(double -0.7853981633974483, %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__rz__body(double 0.7853981633974483, %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 5 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 5 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__s__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__rz__body(double -0.7853981633974483, %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__rz__body(double 0.7853981633974483, %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__s__adj(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 5 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 5 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__rz__body(double -0.7853981633974483, %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__rz__body(double 0.7853981633974483, %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 5 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 4 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__ccx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__t__body(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 4 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 2 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Result* inttoptr (i64 3 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 4 to %Qubit*), %Result* inttoptr (i64 4 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 5 to %Qubit*), %Result* inttoptr (i64 5 to %Result*)) #1
-              call void @__quantum__rt__array_record_output(i64 6, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 2 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 3 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 4 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 5 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="8" "required_num_results"="6" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn qubit_ids_properly_reused() {
-    check(
-        indoc! {"
-        namespace Test {
-
-            open Microsoft.Quantum.Intrinsic;
-
-            // Verifies the use of the CNOT quantum gate from Q#'s Microsoft.Quantum.Intrinsic namespace.
-            // Expected simulation output: ([0, 0], [1, 1]).
-            @EntryPoint()
-            operation IntrinsicCNOT() : (Result[], Result[]) {
-                use registerA = Qubit[2];           // |00⟩
-                CNOT(registerA[0], registerA[1]);   // |00⟩
-                let resultsA = MeasureEachZ(registerA);
-                ResetAll(registerA);
-
-                use registerB = Qubit[2];           // |00⟩
-                X(registerB[0]);                    // |10⟩
-                CNOT(registerB[0], registerB[1]);   // |11⟩
-                let resultsB = MeasureEachZ(registerB);
-                ResetAll(registerB);
-
-                return (resultsA, resultsB);
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*))
-              call void @__quantum__qis__x__body(%Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 4 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Qubit* inttoptr (i64 4 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 6 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Qubit* inttoptr (i64 5 to %Qubit*))
-              call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 7 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 6 to %Qubit*), %Result* inttoptr (i64 2 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 7 to %Qubit*), %Result* inttoptr (i64 3 to %Result*)) #1
-              call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
-              call void @__quantum__rt__array_record_output(i64 2, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              call void @__quantum__rt__array_record_output(i64 2, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 2 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 3 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="8" "required_num_results"="4" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_on_single_qubit() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : (Result, Result) {
-                use (q1, q2) = (Qubit(), Qubit());
-                MyCustomGate(q1);
-                MyCustomGate(q2);
-                return (MResetZ(q1), MResetZ(q2));
-            }
-
-            operation MyCustomGate(q : Qubit) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @MyCustomGate(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @MyCustomGate(%Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-            declare void @MyCustomGate(%Qubit*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn multiple_custom_intrinsic_calls() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : (Result, Result) {
-                use (q0, q1) = (Qubit(), Qubit());
-                MySecondCustomGate(q0, q1);
-                MyCustomGate(q0);
-                MyCustomFunc(42);
-                return (MResetZ(q0), MResetZ(q1));
-            }
-
-            operation MyCustomGate(q : Qubit) : Unit {
-                body intrinsic;
-            }
-
-            operation MySecondCustomGate(q0 : Qubit, q1 : Qubit) : Unit {
-                body intrinsic;
-            }
-
-            function MyCustomFunc(n : Int) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @MySecondCustomGate(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
-              call void @MyCustomGate(%Qubit* inttoptr (i64 0 to %Qubit*))
-              call void @MyCustomFunc(i64 42)
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
-              call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-            declare void @MySecondCustomGate(%Qubit*, %Qubit*)
-            declare void @MyCustomGate(%Qubit*)
-            declare void @MyCustomFunc(i64)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_on_qubit_and_double() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let d = 3.14;
-                MyCustomGate(q, d);
-                return MResetZ(q);
-            }
-
-            operation MyCustomGate(q : Qubit, d : Double) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @MyCustomGate(%Qubit* inttoptr (i64 0 to %Qubit*), double 3.14)
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-            declare void @MyCustomGate(%Qubit*, double)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_on_qubit_and_bool() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let b = true;
-                MyCustomGate(q, b);
-                return MResetZ(q);
-            }
-
-            operation MyCustomGate(q : Qubit, b : Bool) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @MyCustomGate(%Qubit* inttoptr (i64 0 to %Qubit*), i1 true)
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-            declare void @MyCustomGate(%Qubit*, i1)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_on_qubit_and_int() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let i = 42;
-                MyCustomGate(q, i);
-                return MResetZ(q);
-            }
-
-            operation MyCustomGate(q : Qubit, i : Int) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @MyCustomGate(%Qubit* inttoptr (i64 0 to %Qubit*), i64 42)
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-            declare void @MyCustomGate(%Qubit*, i64)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_fail_on_result_arg() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let r = MResetZ(q);
-                MyCustomGate(q, r);
-                return r;
-            }
-
-            operation MyCustomGate(q : Qubit, r : Result) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            IntrinsicFail(
-                "MyCustomGate",
-                "unsupported argument type: Result",
-                PackageSpan {
-                    package: PackageId(
-                        2,
-                    ),
-                    span: Span {
-                        lo: 177,
-                        hi: 261,
-                    },
-                },
-            )
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_fail_on_bigint_arg() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let i = 42L;
-                MyCustomGate(q, i);
-                return MResetZ(q);
-            }
-
-            operation MyCustomGate(q : Qubit, i : BigInt) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            IntrinsicFail(
-                "MyCustomGate",
-                "unsupported argument type: BigInt",
-                PackageSpan {
-                    package: PackageId(
-                        2,
-                    ),
-                    span: Span {
-                        lo: 179,
-                        hi: 263,
-                    },
-                },
-            )
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_fail_on_string_arg() {
-    check(
-        indoc! {r#"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let s = "hello, world";
-                MyCustomGate(q, s);
-                return MResetZ(q);
-            }
-
-            operation MyCustomGate(q : Qubit, s : String) : Unit {
-                body intrinsic;
-            }
-        }
-        "#},
-        None,
-        &expect![[r#"
-            IntrinsicFail(
-                "MyCustomGate",
-                "unsupported argument type: String",
-                PackageSpan {
-                    package: PackageId(
-                        2,
-                    ),
-                    span: Span {
-                        lo: 190,
-                        hi: 274,
-                    },
-                },
-            )
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_fail_on_array_arg() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let a = [1, 2, 3];
-                MyCustomGate(q, a);
-                return MResetZ(q);
-            }
-
-            operation MyCustomGate(q : Qubit, a : Int[]) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            IntrinsicFail(
-                "MyCustomGate",
-                "unsupported argument type: Array",
-                PackageSpan {
-                    package: PackageId(
-                        2,
-                    ),
-                    span: Span {
-                        lo: 185,
-                        hi: 268,
-                    },
-                },
-            )
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_fail_on_tuple_arg() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                let t = (1, 2, 3);
-                MyCustomGate(q, t);
-                return MResetZ(q);
-            }
-
-            operation MyCustomGate(q : Qubit, t : (Int, Int, Int)) : Unit {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            IntrinsicFail(
-                "MyCustomGate",
-                "unsupported argument type: Tuple",
-                PackageSpan {
-                    package: PackageId(
-                        2,
-                    ),
-                    span: Span {
-                        lo: 185,
-                        hi: 278,
-                    },
-                },
-            )
-        "#]],
-    );
-}
-
-#[test]
-fn custom_intrinsic_fail_on_non_unit_return() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                MyCustomGate(q);
-                return MResetZ(q);
-            }
-
-            function MyCustomGate(q : Qubit) : Int {
-                body intrinsic;
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            UnsupportedIntrinsicType(
-                "MyCustomGate",
-                PackageSpan {
-                    package: PackageId(
-                        2,
-                    ),
-                    span: Span {
-                        lo: 155,
-                        hi: 225,
-                    },
-                },
-            )
-        "#]],
-    );
-}
-
-#[test]
-fn pauli_i_rotation_for_global_phase_is_noop() {
-    check(
-        indoc! {"
-        namespace Test {
-            @EntryPoint()
-            operation Test() : Result {
-                use q = Qubit();
-                R(PauliI, 1.0, q);
-                return MResetZ(q);
-            }
-        }
-        "},
-        None,
-        &expect![[r#"
-            %Result = type opaque
-            %Qubit = type opaque
-
-            define void @ENTRYPOINT__main() #0 {
-              call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
-              call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
-              ret void
-            }
-
-            declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__rx__body(double, %Qubit*)
-            declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__ry__body(double, %Qubit*)
-            declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__rz__body(double, %Qubit*)
-            declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-            declare void @__quantum__qis__h__body(%Qubit*)
-            declare void @__quantum__qis__s__body(%Qubit*)
-            declare void @__quantum__qis__s__adj(%Qubit*)
-            declare void @__quantum__qis__t__body(%Qubit*)
-            declare void @__quantum__qis__t__adj(%Qubit*)
-            declare void @__quantum__qis__x__body(%Qubit*)
-            declare void @__quantum__qis__y__body(%Qubit*)
-            declare void @__quantum__qis__z__body(%Qubit*)
-            declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-            declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
-            declare void @__quantum__rt__result_record_output(%Result*, i8*)
-            declare void @__quantum__rt__array_record_output(i64, i8*)
-            declare void @__quantum__rt__tuple_record_output(i64, i8*)
-
-            attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }
-            attributes #1 = { "irreversible" }
-
-            ; module flags
-
-            !llvm.module.flags = !{!0, !1, !2, !3}
-
-            !0 = !{i32 1, !"qir_major_version", i32 1}
-            !1 = !{i32 7, !"qir_minor_version", i32 0}
-            !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
-            !3 = !{i32 1, !"dynamic_result_management", i1 false}
-        "#]],
-    );
-}
diff --git a/compiler/qsc_codegen/src/qsharp/test_utils.rs b/compiler/qsc_codegen/src/qsharp/test_utils.rs
index e13d728e..3fb9acec 100644
--- a/compiler/qsc_codegen/src/qsharp/test_utils.rs
+++ b/compiler/qsc_codegen/src/qsharp/test_utils.rs
@@ -34,13 +34,7 @@ pub(crate) fn get_compilation(sources: Option<SourceMap>) -> (PackageId, Package
     assert!(run_core_passes(&mut core).is_empty());
     let mut store = PackageStore::new(core);
     let mut std = compile::std(&store, TargetCapabilityFlags::empty());
-    assert!(run_default_passes(
-        store.core(),
-        &mut std,
-        PackageType::Lib,
-        TargetCapabilityFlags::empty()
-    )
-    .is_empty());
+    assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty());
     let std = store.insert(std);
 
     let mut unit = compile(
@@ -51,13 +45,7 @@ pub(crate) fn get_compilation(sources: Option<SourceMap>) -> (PackageId, Package
         LanguageFeatures::empty(),
     );
     assert!(unit.errors.is_empty(), "{:?}", unit.errors);
-    assert!(run_default_passes(
-        store.core(),
-        &mut unit,
-        PackageType::Lib,
-        TargetCapabilityFlags::all()
-    )
-    .is_empty());
+    assert!(run_default_passes(store.core(), &mut unit, PackageType::Lib,).is_empty());
     let package_id = store.insert(unit);
     (package_id, store)
 }
diff --git a/compiler/qsc_eval/src/intrinsic/tests.rs b/compiler/qsc_eval/src/intrinsic/tests.rs
index 9aa50bc0..cca7842d 100644
--- a/compiler/qsc_eval/src/intrinsic/tests.rs
+++ b/compiler/qsc_eval/src/intrinsic/tests.rs
@@ -154,13 +154,7 @@ fn check_intrinsic(file: &str, expr: &str, out: &mut impl Receiver) -> Result<Va
 
     let mut std = compile::std(&store, TargetCapabilityFlags::all());
     assert!(std.errors.is_empty());
-    assert!(run_default_passes(
-        store.core(),
-        &mut std,
-        PackageType::Lib,
-        TargetCapabilityFlags::all()
-    )
-    .is_empty());
+    assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty());
     let std_fir = qsc_lowerer::Lowerer::new().lower_package(&std.package);
     let std_id = store.insert(std);
 
@@ -173,13 +167,7 @@ fn check_intrinsic(file: &str, expr: &str, out: &mut impl Receiver) -> Result<Va
         LanguageFeatures::default(),
     );
     assert!(unit.errors.is_empty());
-    assert!(run_default_passes(
-        store.core(),
-        &mut unit,
-        PackageType::Lib,
-        TargetCapabilityFlags::all()
-    )
-    .is_empty());
+    assert!(run_default_passes(store.core(), &mut unit, PackageType::Lib).is_empty());
     let unit_fir = qsc_lowerer::Lowerer::new().lower_package(&unit.package);
     let entry = unit_fir.entry_exec_graph.clone();
 
diff --git a/compiler/qsc_eval/src/tests.rs b/compiler/qsc_eval/src/tests.rs
index d4ac5c13..6f019792 100644
--- a/compiler/qsc_eval/src/tests.rs
+++ b/compiler/qsc_eval/src/tests.rs
@@ -51,13 +51,7 @@ fn check_expr(file: &str, expr: &str, expect: &Expect) {
 
     let mut std = compile::std(&store, TargetCapabilityFlags::all());
     assert!(std.errors.is_empty());
-    assert!(run_default_passes(
-        store.core(),
-        &mut std,
-        PackageType::Lib,
-        TargetCapabilityFlags::all()
-    )
-    .is_empty());
+    assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty());
     let std_fir = fir_lowerer.lower_package(&std.package);
     let std_id = store.insert(std);
 
@@ -70,12 +64,7 @@ fn check_expr(file: &str, expr: &str, expect: &Expect) {
         LanguageFeatures::default(),
     );
     assert!(unit.errors.is_empty(), "{:?}", unit.errors);
-    let pass_errors = run_default_passes(
-        store.core(),
-        &mut unit,
-        PackageType::Lib,
-        TargetCapabilityFlags::all(),
-    );
+    let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib);
     assert!(pass_errors.is_empty(), "{pass_errors:?}");
     let unit_fir = fir_lowerer.lower_package(&unit.package);
     let entry = unit_fir.entry_exec_graph.clone();
@@ -117,13 +106,7 @@ fn check_partial_eval_stmt(
 
     let mut std = compile::std(&store, TargetCapabilityFlags::all());
     assert!(std.errors.is_empty());
-    assert!(run_default_passes(
-        store.core(),
-        &mut std,
-        PackageType::Lib,
-        TargetCapabilityFlags::all()
-    )
-    .is_empty());
+    assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty());
     let std_fir = qsc_lowerer::Lowerer::new().lower_package(&std.package);
     let std_id = store.insert(std);
 
@@ -136,12 +119,7 @@ fn check_partial_eval_stmt(
         LanguageFeatures::default(),
     );
     assert!(unit.errors.is_empty(), "{:?}", unit.errors);
-    let pass_errors = run_default_passes(
-        store.core(),
-        &mut unit,
-        PackageType::Lib,
-        TargetCapabilityFlags::all(),
-    );
+    let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib);
     assert!(pass_errors.is_empty(), "{pass_errors:?}");
     let unit_fir = qsc_lowerer::Lowerer::new().lower_package(&unit.package);
     fir_expect.assert_eq(&unit_fir.to_string());
diff --git a/compiler/qsc_partial_eval/tests/arrays.rs b/compiler/qsc_partial_eval/tests/arrays.rs
index 17ce85f8..cf7c0d01 100644
--- a/compiler/qsc_partial_eval/tests/arrays.rs
+++ b/compiler/qsc_partial_eval/tests/arrays.rs
@@ -12,7 +12,10 @@ pub mod test_utils;
 use expect_test::expect;
 use indoc::indoc;
 use qsc_rir::rir::{BlockId, CallableId};
-use test_utils::{assert_block_instructions, assert_callable, get_rir_program};
+use test_utils::{
+    assert_block_instructions, assert_callable, assert_error, get_partial_evaluation_error,
+    get_rir_program,
+};
 
 #[test]
 fn array_with_dynamic_content() {
@@ -216,7 +219,7 @@ fn array_repeat_with_dynamic_content() {
 }
 
 #[test]
-fn result_at_index_in_array() {
+fn result_array_value_at_index() {
     let program = get_rir_program(indoc! {r#"
         namespace Test {
             @EntryPoint()
@@ -266,3 +269,762 @@ fn result_at_index_in_array() {
                 Return"#]],
     );
 }
+
+#[test]
+fn result_array_value_at_negative_index_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result {
+                use (q0, q1) = (Qubit(), Qubit());
+                let results = [MResetZ(q0), MResetZ(q1)];
+                results[-1]
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[
+            r#"EvaluationFailed("value cannot be used as an index: -1", Span { lo: 177, hi: 179 })"#
+        ]],
+    );
+}
+
+#[test]
+fn result_array_value_at_index_out_of_bounds_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result {
+                use (q0, q1) = (Qubit(), Qubit());
+                let results = [MResetZ(q0), MResetZ(q1)];
+                results[2]
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[r#"EvaluationFailed("index out of range: 2", Span { lo: 177, hi: 178 })"#]],
+    );
+}
+
+#[test]
+fn result_array_slice_with_explicit_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2), MResetZ(q3), MResetZ(q4)];
+                a[0..2..4]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(2), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_slice_with_open_start_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2) = (Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a[...1]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(2), args( Integer(2), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_slice_with_open_ended_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2) = (Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a[1...]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(2), args( Integer(2), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Call id(3), args( Result(2), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_slice_with_open_two_step_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2), MResetZ(q3), MResetZ(q4)];
+                a[...2...]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(2), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_slice_with_out_of_bounds_range_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3) = (Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a[1..3]
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[r#"EvaluationFailed("index out of range: 3", Span { lo: 206, hi: 210 })"#]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_single_index() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3) = (Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a w/ 1 <- MResetZ(q3)
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(2), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_single_negative_index_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3) = (Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a w/ -1 <- MResetZ(q3)
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[
+            r#"EvaluationFailed("negative integers cannot be used here: -1", Span { lo: 209, hi: 211 })"#
+        ]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_single_out_of_bounds_index_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3) = (Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a w/ 3 <- MResetZ(q3)
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[r#"EvaluationFailed("index out of range: 3", Span { lo: 209, hi: 210 })"#]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_explicit_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                use (aux0, aux1, aux2) = (Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2), MResetZ(q3), MResetZ(q4)];
+                a w/ 0..2..4 <- [MResetZ(aux0), MResetZ(aux1), MResetZ(aux2)]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(1), args( Qubit(5), Result(5), )
+                Call id(1), args( Qubit(6), Result(6), )
+                Call id(1), args( Qubit(7), Result(7), )
+                Call id(2), args( Integer(5), Pointer, )
+                Call id(3), args( Result(5), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Call id(3), args( Result(6), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(7), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_open_start_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a w/ ...2 <- [MResetZ(q3), MResetZ(q4)]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Call id(3), args( Result(2), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_open_ended_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a w/ 1... <- [MResetZ(q3), MResetZ(q4)]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_open_two_step_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a w/ ...2... <- [MResetZ(q3), MResetZ(q4)]
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn result_array_copy_and_update_with_out_of_bounds_range_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3) = (Qubit(), Qubit(), Qubit(), Qubit());
+                let a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a w/ 1..3 <- [MResetZ(q0), MResetZ(q1), MResetZ(q2)]
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[r#"EvaluationFailed("index out of range: 3", Span { lo: 209, hi: 213 })"#]],
+    );
+}
diff --git a/compiler/qsc_partial_eval/tests/assigns.rs b/compiler/qsc_partial_eval/tests/assigns.rs
index a253f9da..5512913d 100644
--- a/compiler/qsc_partial_eval/tests/assigns.rs
+++ b/compiler/qsc_partial_eval/tests/assigns.rs
@@ -493,7 +493,7 @@ fn assigning_result_literal_within_dynamic_if_expression_produces_error() {
 }
 
 #[test]
-fn array_of_results_replace_element_at_index_with_dynamic_content() {
+fn array_of_results_update_element_at_index_with_dynamic_content() {
     let program = get_rir_program(indoc! {r#"
         namespace Test {
             @EntryPoint()
@@ -562,7 +562,7 @@ fn array_of_results_replace_element_at_index_with_dynamic_content() {
 }
 
 #[test]
-fn array_of_bools_replace_element_at_index_with_dynamic_content() {
+fn array_of_bools_update_element_at_index_with_dynamic_content() {
     let program = get_rir_program(indoc! {r#"
         namespace Test {
             @EntryPoint()
@@ -647,6 +647,363 @@ fn array_of_bools_replace_element_at_index_with_dynamic_content() {
     );
 }
 
+#[test]
+fn array_of_results_update_element_at_negative_index_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1) = (Qubit(), Qubit());
+                mutable arr = [MResetZ(q0), Zero];
+                set arr w/= -1 <- MResetZ(q1);
+                arr
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[
+            r#"EvaluationFailed("negative integers cannot be used here: -1", Span { lo: 176, hi: 178 })"#
+        ]],
+    );
+}
+
+#[test]
+fn array_of_results_update_element_at_out_of_bounds_index_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1) = (Qubit(), Qubit());
+                mutable arr = [MResetZ(q0), Zero];
+                set arr w/= 2 <- MResetZ(q1);
+                arr
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[r#"EvaluationFailed("index out of range: 2", Span { lo: 176, hi: 177 })"#]],
+    );
+}
+
+#[test]
+fn array_of_results_update_slice_with_explicit_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                use (aux0, aux1, aux2) = (Qubit(), Qubit(), Qubit());
+                mutable a = [MResetZ(q0), MResetZ(q1), MResetZ(q2), MResetZ(q3), MResetZ(q4)];
+                set a w/= 0..2..4 <- [MResetZ(aux0), MResetZ(aux1), MResetZ(aux2)];
+                a
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(1), args( Qubit(5), Result(5), )
+                Call id(1), args( Qubit(6), Result(6), )
+                Call id(1), args( Qubit(7), Result(7), )
+                Call id(2), args( Integer(5), Pointer, )
+                Call id(3), args( Result(5), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Call id(3), args( Result(6), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(7), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn array_of_results_update_slice_with_open_start_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                mutable a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                set a w/= ...2 <- [MResetZ(q3), MResetZ(q4)];
+                a
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Call id(3), args( Result(2), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn array_of_results_update_slice_with_open_ended_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                mutable a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                set a w/= 1... <- [MResetZ(q3), MResetZ(q4)];
+                a
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn array_of_results_update_slice_with_open_two_step_range() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3, q4) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit());
+                mutable a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                set a w/= ...2... <- [MResetZ(q3), MResetZ(q4)];
+                a
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(1), args( Qubit(2), Result(2), )
+                Call id(1), args( Qubit(3), Result(3), )
+                Call id(1), args( Qubit(4), Result(4), )
+                Call id(2), args( Integer(3), Pointer, )
+                Call id(3), args( Result(3), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Call id(3), args( Result(4), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn array_of_results_update_slice_with_out_of_bounds_range_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1, q2, q3) = (Qubit(), Qubit(), Qubit(), Qubit());
+                mutable a = [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                set a w/= 1..3 <- [MResetZ(q0), MResetZ(q1), MResetZ(q2)];
+                a
+            }
+        }
+    "#});
+    assert_error(
+        &error,
+        &expect![[r#"EvaluationFailed("index out of range: 3", Span { lo: 218, hi: 222 })"#]],
+    );
+}
+
 #[test]
 fn empty_array_of_results_in_place_concatenation() {
     let program = get_rir_program(indoc! {r#"
diff --git a/compiler/qsc_partial_eval/tests/returns.rs b/compiler/qsc_partial_eval/tests/returns.rs
index 7a66ee92..82d2c553 100644
--- a/compiler/qsc_partial_eval/tests/returns.rs
+++ b/compiler/qsc_partial_eval/tests/returns.rs
@@ -910,10 +910,11 @@ fn explicit_return_embedded_in_assign_index_expr_yields_error() {
         }
     }
     "#});
-    // The type of error will change once this kind of hybrid expression is supported.
     assert_error(
         &error,
-        &expect![[r#"Unimplemented("Update Index Expr", Span { lo: 170, hi: 193 })"#]],
+        &expect![[
+            r#"Unexpected("embedded return in update expression", Span { lo: 181, hi: 193 })"#
+        ]],
     );
 }
 
@@ -1090,7 +1091,7 @@ fn explicit_return_embedded_in_hybrid_update_index_expr_yields_error() {
     assert_error(
         &error,
         &expect![[
-            r#"Unexpected("embedded return in assign index expression", Span { lo: 142, hi: 154 })"#
+            r#"Unexpected("embedded return in update expression", Span { lo: 142, hi: 154 })"#
         ]],
     );
 }
diff --git a/language_service/src/state/tests.rs b/language_service/src/state/tests.rs
index ecc93fd4..a215d8d5 100644
--- a/language_service/src/state/tests.rs
+++ b/language_service/src/state/tests.rs
@@ -314,6 +314,7 @@ async fn rca_errors_are_reported_when_compilation_succeeds() {
     updater.update_configuration(WorkspaceConfigurationUpdate {
         target_profile: Some(Profile::AdaptiveRI),
         package_type: Some(PackageType::Lib),
+        language_features: None,
     });
 
     updater
@@ -358,6 +359,69 @@ async fn rca_errors_are_reported_when_compilation_succeeds() {
     );
 }
 
+#[tokio::test]
+async fn base_profile_rca_errors_are_reported_when_compilation_succeeds() {
+    let errors = RefCell::new(Vec::new());
+    let mut updater = new_updater(&errors);
+
+    updater.update_configuration(WorkspaceConfigurationUpdate {
+        target_profile: Some(Profile::Base),
+        package_type: Some(PackageType::Lib),
+        language_features: None,
+    });
+
+    updater
+        .update_document("single/foo.qs", 1, "namespace Test { operation RcaCheck() : Double { use q = Qubit(); mutable x = 1.0; if MResetZ(q) == One { set x = 2.0; } x } }")
+        .await;
+
+    // we expect two errors, one for `set x = 2.0` and one for `x`
+    expect_errors(
+        &errors,
+        &expect![[r#"
+            [
+                (
+                    "single/foo.qs",
+                    Some(
+                        1,
+                    ),
+                    [
+                        Pass(
+                            CapabilitiesCk(
+                                UseOfDynamicBool(
+                                    Span {
+                                        lo: 86,
+                                        hi: 103,
+                                    },
+                                ),
+                            ),
+                        ),
+                        Pass(
+                            CapabilitiesCk(
+                                UseOfDynamicDouble(
+                                    Span {
+                                        lo: 106,
+                                        hi: 117,
+                                    },
+                                ),
+                            ),
+                        ),
+                        Pass(
+                            CapabilitiesCk(
+                                UseOfDynamicDouble(
+                                    Span {
+                                        lo: 121,
+                                        hi: 122,
+                                    },
+                                ),
+                            ),
+                        ),
+                    ],
+                ),
+            ]
+        "#]],
+    );
+}
+
 #[tokio::test]
 async fn package_type_update_causes_error() {
     let errors = RefCell::new(Vec::new());
@@ -366,6 +430,7 @@ async fn package_type_update_causes_error() {
     updater.update_configuration(WorkspaceConfigurationUpdate {
         target_profile: None,
         package_type: Some(PackageType::Lib),
+        language_features: None,
     });
 
     updater
@@ -386,6 +451,7 @@ async fn package_type_update_causes_error() {
     updater.update_configuration(WorkspaceConfigurationUpdate {
         target_profile: None,
         package_type: Some(PackageType::Exe),
+        language_features: None,
     });
 
     expect_errors(
@@ -418,13 +484,14 @@ async fn target_profile_update_fixes_error() {
     updater.update_configuration(WorkspaceConfigurationUpdate {
         target_profile: Some(Profile::Base),
         package_type: Some(PackageType::Lib),
+        language_features: None,
     });
 
     updater
         .update_document(
             "single/foo.qs",
             1,
-            r#"namespace Foo { operation Main() : Unit { if Zero == Zero { Message("hi") } } }"#,
+            r#"namespace Foo { operation Main() : Unit { use q = Qubit(); if M(q) == Zero { Message("hi") } } }"#,
         )
         .await;
 
@@ -439,31 +506,11 @@ async fn target_profile_update_fixes_error() {
                     ),
                     [
                         Pass(
-                            BaseProfCk(
-                                ResultComparison(
-                                    Span {
-                                        lo: 45,
-                                        hi: 57,
-                                    },
-                                ),
-                            ),
-                        ),
-                        Pass(
-                            BaseProfCk(
-                                ResultLiteral(
-                                    Span {
-                                        lo: 45,
-                                        hi: 49,
-                                    },
-                                ),
-                            ),
-                        ),
-                        Pass(
-                            BaseProfCk(
-                                ResultLiteral(
+                            CapabilitiesCk(
+                                UseOfDynamicBool(
                                     Span {
-                                        lo: 53,
-                                        hi: 57,
+                                        lo: 62,
+                                        hi: 74,
                                     },
                                 ),
                             ),
@@ -477,6 +524,7 @@ async fn target_profile_update_fixes_error() {
     updater.update_configuration(WorkspaceConfigurationUpdate {
         target_profile: Some(Profile::Unrestricted),
         package_type: None,
+        language_features: None,
     });
 
     expect_errors(
@@ -516,6 +564,7 @@ async fn target_profile_update_causes_error_in_stdlib() {
     updater.update_configuration(WorkspaceConfigurationUpdate {
         target_profile: Some(Profile::Base),
         package_type: None,
+        language_features: None,
     });
 
     expect_errors(
diff --git a/pip/tests-qir/test_qir.py b/pip/tests-qir/test_qir.py
index 56fc6fb5..95e1dcde 100644
--- a/pip/tests-qir/test_qir.py
+++ b/pip/tests-qir/test_qir.py
@@ -21,7 +21,7 @@ def test_compile_qir_input_data() -> None:
     qir = operation._repr_qir_()
     assert isinstance(qir, bytes)
     module = Module.from_ir(Context(), qir.decode(), "module")
-    assert len(module.functions) == 24
+    assert len(module.functions) == 5
     assert module.functions[0].name == "ENTRYPOINT__main"
     func = module.functions[0]
     assert len(func.basic_blocks) == 1
@@ -71,7 +71,7 @@ def test_compile_qir_all_gates() -> None:
     qir = operation._repr_qir_()
     assert isinstance(qir, bytes)
     module = Module.from_ir(Context(), qir.decode(), "module")
-    assert len(module.functions) == 24
+    assert len(module.functions) == 23
     assert module.functions[0].name == "ENTRYPOINT__main"
     func = module.functions[0]
     assert len(func.basic_blocks) == 1
diff --git a/pip/tests/test_interpreter.py b/pip/tests/test_interpreter.py
index d1a7cfcf..a90171e9 100644
--- a/pip/tests/test_interpreter.py
+++ b/pip/tests/test_interpreter.py
@@ -181,7 +181,9 @@ def test_value_array() -> None:
 def test_target_error() -> None:
     e = Interpreter(TargetProfile.Base)
     with pytest.raises(QSharpError) as excinfo:
-        e.interpret("operation Program() : Result { return Zero }")
+        e.interpret(
+            "operation Program() : Result { use q = Qubit(); if M(q) == Zero { return Zero } else { return One } }"
+        )
     assert str(excinfo.value).startswith("Qsc.BaseProfCk.ResultLiteral") != -1
 
 
@@ -406,37 +408,20 @@ def test_base_qir_can_be_generated() -> None:
         %Qubit = type opaque
 
         define void @ENTRYPOINT__main() #0 {
+        block_0:
           call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
           call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
           call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
-          call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
+          call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
           call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
           ret void
         }
 
-        declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
-        declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
-        declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
-        declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
-        declare void @__quantum__qis__rx__body(double, %Qubit*)
-        declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
-        declare void @__quantum__qis__ry__body(double, %Qubit*)
-        declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
         declare void @__quantum__qis__rz__body(double, %Qubit*)
-        declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
-        declare void @__quantum__qis__h__body(%Qubit*)
-        declare void @__quantum__qis__s__body(%Qubit*)
-        declare void @__quantum__qis__s__adj(%Qubit*)
-        declare void @__quantum__qis__t__body(%Qubit*)
-        declare void @__quantum__qis__t__adj(%Qubit*)
-        declare void @__quantum__qis__x__body(%Qubit*)
-        declare void @__quantum__qis__y__body(%Qubit*)
-        declare void @__quantum__qis__z__body(%Qubit*)
-        declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
-        declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
+
         declare void @__quantum__rt__result_record_output(%Result*, i8*)
-        declare void @__quantum__rt__array_record_output(i64, i8*)
-        declare void @__quantum__rt__tuple_record_output(i64, i8*)
+
+        declare void @__quantum__qis__mz__body(%Qubit*, %Result*) #1
 
         attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }
         attributes #1 = { "irreversible" }
diff --git a/resource_estimator/src/system/optimization/code_distance_iterators/tests.rs b/resource_estimator/src/system/optimization/code_distance_iterators/tests.rs
index 1842d03f..0352ad3f 100644
--- a/resource_estimator/src/system/optimization/code_distance_iterators/tests.rs
+++ b/resource_estimator/src/system/optimization/code_distance_iterators/tests.rs
@@ -16,7 +16,7 @@ fn test_switch_to_non_comparable_code_distance_indexes_basic() {
         &left,
         &right,
         3
-    ),);
+    ));
     assert_eq!(current, [1, 4, 4]);
 }
 
@@ -31,7 +31,7 @@ fn test_switch_to_non_comparable_code_distance_indexes_overflow() {
         &left,
         &right,
         3
-    ),);
+    ));
     assert_eq!(current, [2, 2, 3]);
 }
 
@@ -45,7 +45,7 @@ fn test_switch_to_non_comparable_code_distance_indexes_finding_left() {
         &left,
         &right,
         5
-    ),);
+    ));
     assert_eq!(current, [2, 2, 3, 3, 3]);
 }
 
@@ -59,7 +59,7 @@ fn test_switch_to_non_comparable_code_distance_indexes_all_max() {
         &left,
         &right,
         3
-    ),);
+    ));
 }
 
 #[test]
diff --git a/wasm/src/tests.rs b/wasm/src/tests.rs
index c5335ab7..515e72c6 100644
--- a/wasm/src/tests.rs
+++ b/wasm/src/tests.rs
@@ -3,7 +3,9 @@
 
 use expect_test::expect;
 use indoc::indoc;
-use qsc::{interpret, LanguageFeatures, SourceMap};
+use qsc::{interpret, LanguageFeatures, SourceMap, TargetCapabilityFlags};
+
+use crate::_get_qir;
 
 use super::run_internal_with_features;
 
@@ -39,9 +41,10 @@ fn test_compile() {
     M(q)
     }}";
 
-    let result = crate::_get_qir(
+    let result = qsc::codegen::get_qir(
         SourceMap::new([("test.qs".into(), code.into())], None),
         LanguageFeatures::default(),
+        TargetCapabilityFlags::empty(),
     );
     assert!(result.is_ok());
 }
@@ -463,3 +466,24 @@ fn test_doc_gen() {
         }
     }
 }
+
+#[test]
+fn code_with_errors_returns_errors() {
+    let source = "namespace Test {
+            @EntryPoint()
+            operation Main() : Unit {
+                use q = Qubit()
+                let pi_over_two = 4.0 / 2.0;
+            }
+        }";
+    let sources = SourceMap::new([("test.qs".into(), source.into())], None);
+    let language_features = LanguageFeatures::default();
+    let capabilities = TargetCapabilityFlags::empty();
+
+    expect![[r#"
+        Err(
+            "[{\"message\": \"syntax error\",\"code\": \"Qsc.Parse.Token\",\"severity\": \"error\",\"causes\": [\"expected `;`, found keyword `let`\"],\"filename\": \"test.qs\",\"labels\": [{\"span\": {\"offset\": 129,\"length\": 3}}],\"related\": []}]",
+        )
+    "#]]
+    .assert_debug_eq(&_get_qir(sources, language_features, capabilities));
+}