Skip to content

Commit c6d74f6

Browse files
authored
Add playground RIR tab with raw and ssa processed RIR (#2096)
1 parent 1255ac0 commit c6d74f6

File tree

9 files changed

+174
-30
lines changed

9 files changed

+174
-30
lines changed

compiler/qsc/src/codegen.rs

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub mod qsharp {
1010
}
1111

1212
pub mod qir {
13-
use qsc_codegen::qir::fir_to_qir;
13+
use qsc_codegen::qir::{fir_to_qir, fir_to_rir};
1414

1515
use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
1616
use qsc_frontend::{
@@ -87,33 +87,100 @@ pub mod qir {
8787
))]
8888
})
8989
}
90+
91+
pub fn get_rir(
92+
sources: SourceMap,
93+
language_features: LanguageFeatures,
94+
capabilities: TargetCapabilityFlags,
95+
mut package_store: PackageStore,
96+
dependencies: &Dependencies,
97+
) -> Result<Vec<String>, Vec<Error>> {
98+
let (package_id, fir_store, entry, compute_properties) = compile_to_fir(
99+
sources,
100+
language_features,
101+
capabilities,
102+
&mut package_store,
103+
dependencies,
104+
)?;
105+
106+
let (raw, ssa) = fir_to_rir(&fir_store, capabilities, Some(compute_properties), &entry)
107+
.map_err(|e| {
108+
let source_package_id = match e.span() {
109+
Some(span) => span.package,
110+
None => package_id,
111+
};
112+
let source_package = package_store
113+
.get(source_package_id)
114+
.expect("package should be in store");
115+
vec![Error::PartialEvaluation(WithSource::from_map(
116+
&source_package.sources,
117+
e,
118+
))]
119+
})?;
120+
Ok(vec![raw.to_string(), ssa.to_string()])
121+
}
122+
90123
pub fn get_qir(
91124
sources: SourceMap,
92125
language_features: LanguageFeatures,
93126
capabilities: TargetCapabilityFlags,
94127
mut package_store: PackageStore,
95128
dependencies: &Dependencies,
96129
) -> Result<String, Vec<Error>> {
130+
let (package_id, fir_store, entry, compute_properties) = compile_to_fir(
131+
sources,
132+
language_features,
133+
capabilities,
134+
&mut package_store,
135+
dependencies,
136+
)?;
137+
138+
fir_to_qir(&fir_store, capabilities, Some(compute_properties), &entry).map_err(|e| {
139+
let source_package_id = match e.span() {
140+
Some(span) => span.package,
141+
None => package_id,
142+
};
143+
let source_package = package_store
144+
.get(source_package_id)
145+
.expect("package should be in store");
146+
vec![Error::PartialEvaluation(WithSource::from_map(
147+
&source_package.sources,
148+
e,
149+
))]
150+
})
151+
}
152+
153+
fn compile_to_fir(
154+
sources: SourceMap,
155+
language_features: LanguageFeatures,
156+
capabilities: TargetCapabilityFlags,
157+
package_store: &mut PackageStore,
158+
dependencies: &[(qsc_hir::hir::PackageId, Option<std::sync::Arc<str>>)],
159+
) -> Result<
160+
(
161+
qsc_hir::hir::PackageId,
162+
qsc_fir::fir::PackageStore,
163+
ProgramEntry,
164+
qsc_rca::PackageStoreComputeProperties,
165+
),
166+
Vec<Error>,
167+
> {
97168
if capabilities == TargetCapabilityFlags::all() {
98169
return Err(vec![Error::UnsupportedRuntimeCapabilities]);
99170
}
100-
101171
let (unit, errors) = crate::compile::compile(
102-
&package_store,
172+
package_store,
103173
dependencies,
104174
sources,
105175
PackageType::Exe,
106176
capabilities,
107177
language_features,
108178
);
109-
110-
// Ensure it compiles before trying to add it to the store.
111179
if !errors.is_empty() {
112180
return Err(errors.iter().map(|e| Error::Compile(e.clone())).collect());
113181
}
114-
115182
let package_id = package_store.insert(unit);
116-
let (fir_store, fir_package_id) = qsc_passes::lower_hir_to_fir(&package_store, package_id);
183+
let (fir_store, fir_package_id) = qsc_passes::lower_hir_to_fir(package_store, package_id);
117184
let package = fir_store.get(fir_package_id);
118185
let entry = ProgramEntry {
119186
exec_graph: package.entry_exec_graph.clone(),
@@ -125,7 +192,6 @@ pub mod qir {
125192
)
126193
.into(),
127194
};
128-
129195
let compute_properties = PassContext::run_fir_passes_on_fir(
130196
&fir_store,
131197
fir_package_id,
@@ -140,19 +206,6 @@ pub mod qir {
140206
.map(|e| Error::Pass(WithSource::from_map(&source_package.sources, e.clone())))
141207
.collect::<Vec<_>>()
142208
})?;
143-
144-
fir_to_qir(&fir_store, capabilities, Some(compute_properties), &entry).map_err(|e| {
145-
let source_package_id = match e.span() {
146-
Some(span) => span.package,
147-
None => package_id,
148-
};
149-
let source_package = package_store
150-
.get(source_package_id)
151-
.expect("package should be in store");
152-
vec![Error::PartialEvaluation(WithSource::from_map(
153-
&source_package.sources,
154-
e,
155-
))]
156-
})
209+
Ok((package_id, fir_store, entry, compute_properties))
157210
}
158211
}

compiler/qsc_codegen/src/qir.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use qsc_partial_eval::{partially_evaluate, ProgramEntry};
1313
use qsc_rca::PackageStoreComputeProperties;
1414
use qsc_rir::{
1515
passes::check_and_transform,
16-
rir::{self, ConditionCode},
16+
rir::{self, ConditionCode, Program},
1717
utils::get_all_block_successors,
1818
};
1919

@@ -37,6 +37,18 @@ pub fn hir_to_qir(
3737
fir_to_qir(&fir_store, capabilities, compute_properties, entry)
3838
}
3939

40+
pub fn fir_to_rir(
41+
fir_store: &qsc_fir::fir::PackageStore,
42+
capabilities: TargetCapabilityFlags,
43+
compute_properties: Option<PackageStoreComputeProperties>,
44+
entry: &ProgramEntry,
45+
) -> Result<(Program, Program), qsc_partial_eval::Error> {
46+
let mut program = get_rir_from_compilation(fir_store, compute_properties, entry, capabilities)?;
47+
let orig = program.clone();
48+
check_and_transform(&mut program);
49+
Ok((orig, program))
50+
}
51+
4052
pub fn fir_to_qir(
4153
fir_store: &qsc_fir::fir::PackageStore,
4254
capabilities: TargetCapabilityFlags,

npm/qsharp/src/compiler/compiler.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export interface ICompiler {
4545
profile?: TargetProfile,
4646
): Promise<string>;
4747

48+
getRir(program: ProgramConfig): Promise<string[]>;
49+
4850
run(
4951
program: ProgramConfig,
5052
expr: string,
@@ -162,6 +164,14 @@ export class Compiler implements ICompiler {
162164
);
163165
}
164166

167+
async getRir(program: ProgramConfig): Promise<string[]> {
168+
const config = toWasmProgramConfig(
169+
program,
170+
program.profile || "adaptive_ri",
171+
);
172+
return this.wasm.get_rir(config);
173+
}
174+
165175
async run(
166176
program: ProgramConfig,
167177
expr: string,
@@ -319,6 +329,7 @@ export const compilerProtocol: ServiceProtocol<ICompiler, QscEventData> = {
319329
checkCode: "request",
320330
getAst: "request",
321331
getHir: "request",
332+
getRir: "request",
322333
getQir: "request",
323334
getEstimates: "request",
324335
getCircuit: "request",

npm/qsharp/ux/qsharp-ux.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,14 @@ html {
343343
white-space: pre;
344344
}
345345

346+
.rir-output {
347+
height: 40vh;
348+
min-height: 400px;
349+
width: 100%;
350+
resize: none;
351+
white-space: pre;
352+
}
353+
346354
.qir-output {
347355
height: 100%;
348356
width: 100%;

playground/src/editor.tsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export function Editor(props: {
9090
profile: TargetProfile;
9191
setAst: (ast: string) => void;
9292
setHir: (hir: string) => void;
93+
setRir: (rir: string[]) => void;
9394
setQir: (qir: string) => void;
9495
activeTab: ActiveTab;
9596
languageService: ILanguageServiceWorker;
@@ -159,7 +160,7 @@ export function Editor(props: {
159160
);
160161
}
161162
const codeGenTimeout = 1000; // ms
162-
if (props.activeTab === "qir-tab") {
163+
if (props.activeTab === "qir-tab" || props.activeTab === "rir-tab") {
163164
let timedOut = false;
164165
const compiler = props.compiler_worker_factory();
165166
const compilerTimeout = setTimeout(() => {
@@ -168,14 +169,28 @@ export function Editor(props: {
168169
compiler.terminate();
169170
}, codeGenTimeout);
170171
try {
171-
const qir = await compiler.getQir(config);
172-
clearTimeout(compilerTimeout);
173-
props.setQir(qir);
172+
if (props.activeTab === "rir-tab") {
173+
const ir = await compiler.getRir(config);
174+
clearTimeout(compilerTimeout);
175+
props.setRir(ir);
176+
} else {
177+
const ir = await compiler.getQir(config);
178+
clearTimeout(compilerTimeout);
179+
props.setQir(ir);
180+
}
174181
} catch (e: any) {
175182
if (timedOut) {
176-
props.setQir("timed out");
183+
if (props.activeTab === "rir-tab") {
184+
props.setRir(["timed out", "timed out"]);
185+
} else {
186+
props.setQir("timed out");
187+
}
177188
} else {
178-
props.setQir(e.toString());
189+
if (props.activeTab === "rir-tab") {
190+
props.setRir([e.toString(), e.toString()]);
191+
} else {
192+
props.setQir(e.toString());
193+
}
179194
}
180195
} finally {
181196
compiler.terminate();

playground/src/kata.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ function LessonElem(props: Props & { section: KataSection }) {
113113
profile={getProfile()}
114114
setAst={() => ({})}
115115
setHir={() => ({})}
116+
setRir={() => ({})}
116117
setQir={() => ({})}
117118
activeTab="results-tab"
118119
languageService={props.languageService}
@@ -124,6 +125,7 @@ function LessonElem(props: Props & { section: KataSection }) {
124125
onShotError={(diag?: VSDiagnostic) => setShotError(diag)}
125126
ast=""
126127
hir=""
128+
rir={["", ""]}
127129
qir=""
128130
activeTab="results-tab"
129131
setActiveTab={() => undefined}
@@ -176,6 +178,7 @@ function ExerciseElem(props: Props & { section: KataSection }) {
176178
profile={getProfile()}
177179
setAst={() => ({})}
178180
setHir={() => ({})}
181+
setRir={() => ({})}
179182
setQir={() => ({})}
180183
activeTab="results-tab"
181184
languageService={props.languageService}
@@ -187,6 +190,7 @@ function ExerciseElem(props: Props & { section: KataSection }) {
187190
onShotError={(diag?: VSDiagnostic) => setShotError(diag)}
188191
ast=""
189192
hir=""
193+
rir={["", ""]}
190194
qir=""
191195
activeTab="results-tab"
192196
setActiveTab={() => undefined}

playground/src/main.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ md.use((mk as any).default, {
5656
}); // Not sure why it's not using the default export automatically :-/
5757
setRenderer((input: string) => md.render(input));
5858

59-
export type ActiveTab = "results-tab" | "ast-tab" | "hir-tab" | "qir-tab";
59+
export type ActiveTab =
60+
| "results-tab"
61+
| "ast-tab"
62+
| "hir-tab"
63+
| "rir-tab"
64+
| "qir-tab";
6065

6166
const basePath = (window as any).qscBasePath || "";
6267
const monacoPath = basePath + "libs/monaco/vs";
@@ -104,6 +109,7 @@ function App(props: { katas: Kata[]; linkedCode?: string }) {
104109

105110
const [ast, setAst] = useState<string>("");
106111
const [hir, setHir] = useState<string>("");
112+
const [rir, setRir] = useState<string[]>(["", ""]);
107113
const [qir, setQir] = useState<string>("");
108114
const [activeTab, setActiveTab] = useState<ActiveTab>("results-tab");
109115

@@ -178,6 +184,7 @@ function App(props: { katas: Kata[]; linkedCode?: string }) {
178184
profile={getProfile()}
179185
setAst={setAst}
180186
setHir={setHir}
187+
setRir={setRir}
181188
setQir={setQir}
182189
activeTab={activeTab}
183190
languageService={languageService}
@@ -188,6 +195,7 @@ function App(props: { katas: Kata[]; linkedCode?: string }) {
188195
onShotError={(diag?: VSDiagnostic) => setShotError(diag)}
189196
ast={ast}
190197
hir={hir}
198+
rir={rir}
191199
qir={qir}
192200
activeTab={activeTab}
193201
setActiveTab={setActiveTab}

playground/src/tabs.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const tabArray: Array<[ActiveTab, string]> = [
99
["results-tab", "RESULTS"],
1010
["ast-tab", "AST"],
1111
["hir-tab", "HIR"],
12+
["rir-tab", "RIR"],
1213
["qir-tab", "QIR"],
1314
];
1415

@@ -28,6 +29,21 @@ function HirTab(props: { hir: string; activeTab: ActiveTab }) {
2829
) : null;
2930
}
3031

32+
function RirTab(props: { rir: string[]; activeTab: ActiveTab }) {
33+
const raw = props.rir[0];
34+
const ssa = props.rir[1];
35+
return props.activeTab === "rir-tab" ? (
36+
<div>
37+
<textarea readonly class="rir-output">
38+
{raw}
39+
</textarea>
40+
<textarea readonly class="rir-output">
41+
{ssa}
42+
</textarea>
43+
</div>
44+
) : null;
45+
}
46+
3147
function QirTab(props: { qir: string; activeTab: ActiveTab }) {
3248
return props.activeTab === "qir-tab" ? (
3349
<textarea readonly class="qir-output">
@@ -43,6 +59,7 @@ export function OutputTabs(props: {
4359
kataMode?: boolean;
4460
ast: string;
4561
hir: string;
62+
rir: string[];
4663
qir: string;
4764
activeTab: ActiveTab;
4865
setActiveTab: (tab: ActiveTab) => void;
@@ -65,6 +82,7 @@ export function OutputTabs(props: {
6582
<ResultsTab {...props} />
6683
<AstTab {...props} />
6784
<HirTab {...props} />
85+
<RirTab {...props} />
6886
<QirTab {...props} />
6987
</div>
7088
</>

0 commit comments

Comments
 (0)