@@ -6,7 +6,7 @@ mod rir_builder;
6
6
#[ cfg( test) ]
7
7
mod tests;
8
8
9
- use qsc_rir:: rir;
9
+ use qsc_rir:: { rir, utils :: get_all_block_successors } ;
10
10
11
11
/// A trait for converting a type into QIR of type `T`.
12
12
/// This can be used to generate QIR strings or other representations.
@@ -86,22 +86,41 @@ impl ToQir<String> for rir::Instruction {
86
86
fn to_qir ( & self , program : & rir:: Program ) -> String {
87
87
match self {
88
88
rir:: Instruction :: Store ( _, _) => unimplemented ! ( "store should be removed by pass" ) ,
89
- rir:: Instruction :: Call ( call_id, args) => {
89
+ rir:: Instruction :: Call ( call_id, args, output ) => {
90
90
let args = args
91
91
. iter ( )
92
92
. map ( |arg| ToQir :: < String > :: to_qir ( arg, program) )
93
93
. collect :: < Vec < _ > > ( )
94
94
. join ( ", " ) ;
95
95
let callable = program. get_callable ( * call_id) ;
96
+ if let Some ( output) = output {
97
+ format ! (
98
+ " {} = call {} @{}({})" ,
99
+ ToQir :: <String >:: to_qir( & output. variable_id, program) ,
100
+ ToQir :: <String >:: to_qir( & callable. output_type, program) ,
101
+ callable. name,
102
+ args
103
+ )
104
+ } else {
105
+ format ! (
106
+ " call {} @{}({})" ,
107
+ ToQir :: <String >:: to_qir( & callable. output_type, program) ,
108
+ callable. name,
109
+ args
110
+ )
111
+ }
112
+ }
113
+ rir:: Instruction :: Jump ( block_id) => {
114
+ format ! ( " br label %{}" , ToQir :: <String >:: to_qir( block_id, program) )
115
+ }
116
+ rir:: Instruction :: Branch ( cond, true_id, false_id) => {
96
117
format ! (
97
- " call {} @{}({}) " ,
98
- ToQir :: <String >:: to_qir( & callable . output_type , program) ,
99
- callable . name ,
100
- args
118
+ " br {}, label %{}, label %{} " ,
119
+ ToQir :: <String >:: to_qir( cond , program) ,
120
+ ToQir :: < String > :: to_qir ( true_id , program ) ,
121
+ ToQir :: < String > :: to_qir ( false_id , program )
101
122
)
102
123
}
103
- rir:: Instruction :: Jump ( _) => todo ! ( ) ,
104
- rir:: Instruction :: Branch ( _, _, _) => todo ! ( ) ,
105
124
rir:: Instruction :: Add ( _, _, _) => todo ! ( ) ,
106
125
rir:: Instruction :: Sub ( _, _, _) => todo ! ( ) ,
107
126
rir:: Instruction :: Mul ( _, _, _) => todo ! ( ) ,
@@ -118,6 +137,22 @@ impl ToQir<String> for rir::Instruction {
118
137
}
119
138
}
120
139
140
+ impl ToQir < String > for rir:: BlockId {
141
+ fn to_qir ( & self , _program : & rir:: Program ) -> String {
142
+ format ! ( "block_{}" , self . 0 )
143
+ }
144
+ }
145
+
146
+ impl ToQir < String > for rir:: Block {
147
+ fn to_qir ( & self , program : & rir:: Program ) -> String {
148
+ self . 0
149
+ . iter ( )
150
+ . map ( |instr| ToQir :: < String > :: to_qir ( instr, program) )
151
+ . collect :: < Vec < _ > > ( )
152
+ . join ( "\n " )
153
+ }
154
+ }
155
+
121
156
impl ToQir < String > for rir:: Callable {
122
157
fn to_qir ( & self , program : & rir:: Program ) -> String {
123
158
let input_type = self
@@ -127,30 +162,33 @@ impl ToQir<String> for rir::Callable {
127
162
. collect :: < Vec < _ > > ( )
128
163
. join ( ", " ) ;
129
164
let output_type = ToQir :: < String > :: to_qir ( & self . output_type , program) ;
130
- let signature = format ! ( "{} @{}({})" , output_type, self . name, input_type) ;
131
165
let Some ( entry_id) = self . body else {
132
166
return format ! (
133
- "declare {signature}{}" ,
134
- if self . name == "__quantum__qis__mz__body" {
135
- // The mz callable is a special case that needs the irreversable attribute.
167
+ "declare {output_type} @{}({input_type}){}" ,
168
+ self . name,
169
+ if self . is_measurement {
170
+ // Measurement callables are a special case that needs the irreversable attribute.
136
171
" #1"
137
172
} else {
138
173
""
139
174
}
140
175
) ;
141
176
} ;
142
- // For now, assume a single block.
143
- let block = program. get_block ( entry_id) ;
144
- let body = block
145
- . 0
146
- . iter ( )
147
- . map ( |instr| ToQir :: < String > :: to_qir ( instr, program) )
148
- . collect :: < Vec < _ > > ( )
149
- . join ( "\n " ) ;
150
- format ! (
151
- "define {signature} #0 {{\n block_{}:\n {body}\n }}" ,
152
- entry_id. 0
153
- )
177
+ let mut body = String :: new ( ) ;
178
+ let all_blocks = get_all_block_successors ( entry_id, program) ;
179
+ for block_id in all_blocks {
180
+ let block = program. get_block ( block_id) ;
181
+ body. push_str ( & format ! (
182
+ "{}:\n {}\n " ,
183
+ ToQir :: <String >:: to_qir( & block_id, program) ,
184
+ ToQir :: <String >:: to_qir( block, program)
185
+ ) ) ;
186
+ }
187
+ assert ! (
188
+ input_type. is_empty( ) ,
189
+ "entry point should not have an input"
190
+ ) ;
191
+ format ! ( "define {output_type} @ENTRYPOINT__main() #0 {{\n {body}}}" , )
154
192
}
155
193
}
156
194
0 commit comments