Skip to content

Commit 575b919

Browse files
committed
Opaque Pointer spec updates
This change updates the specification to use opaque pointers throughout, making it compatible with newer versions of LLVM (everything after 15).
1 parent a67da3a commit 575b919

11 files changed

Lines changed: 1154 additions & 131 deletions

File tree

specification/under_development/profiles/Adaptive_Profile.md

Lines changed: 88 additions & 95 deletions
Large diffs are not rendered by default.

specification/under_development/profiles/Base_Profile.md

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,6 @@ The code below illustrates how a simple program looks within a Base Profile
113113
representation:
114114

115115
```llvm
116-
; type definitions
117-
118-
%Result = type opaque
119-
%Qubit = type opaque
120-
121116
; global constants (labels for output recording)
122117
123118
@0 = internal constant [3 x i8] c"r1\00"
@@ -129,45 +124,45 @@ representation:
129124
define i64 @Entry_Point_Name() #0 {
130125
entry:
131126
; calls to initialize the execution environment
132-
call void @__quantum__rt__initialize(i8* null)
127+
call void @__quantum__rt__initialize(ptr null)
133128
br label %body
134129
135130
body: ; preds = %entry
136131
; calls to QIS functions that are not irreversible
137-
call void @__quantum__qis__h__body(%Qubit* null)
138-
call void @__quantum__qis__cnot__body(%Qubit* null, %Qubit* inttoptr (i64 1 to %Qubit*))
132+
call void @__quantum__qis__h__body(ptr null)
133+
call void @__quantum__qis__cnot__body(ptr null, ptr inttoptr (i64 1 to ptr))
139134
br label %measurements
140135
141136
measurements: ; preds = %body
142137
; calls to QIS functions that are irreversible
143-
call void @__quantum__qis__mz__body(%Qubit* null, %Result* writeonly null)
144-
call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* writeonly inttoptr (i64 1 to %Result*))
138+
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
139+
call void @__quantum__qis__mz__body(ptr inttoptr (i64 1 to ptr), ptr writeonly inttoptr (i64 1 to ptr))
145140
br label %output
146141
147142
output: ; preds = %measurements
148143
; calls to record the program output
149-
call void @__quantum__rt__tuple_record_output(i64 2, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @2, i32 0, i32 0))
150-
call void @__quantum__rt__result_record_output(%Result* null, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @0, i32 0, i32 0))
151-
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @1, i32 0, i32 0))
144+
call void @__quantum__rt__tuple_record_output(i64 2, getelementptr inbounds ([3 x i8], ptr @2, i32 0, i32 0))
145+
call void @__quantum__rt__result_record_output(ptr null, getelementptr inbounds ([3 x i8], ptr @0, i32 0, i32 0))
146+
call void @__quantum__rt__result_record_output(ptr inttoptr (i64 1 to ptr), getelementptr inbounds ([3 x i8], ptr @1, i32 0, i32 0))
152147
153148
ret i64 0
154149
}
155150
156151
; declarations of QIS functions
157152
158-
declare void @__quantum__qis__h__body(%Qubit*)
153+
declare void @__quantum__qis__h__body(ptr)
159154
160-
declare void @__quantum__qis__cnot__body(%Qubit*, %Qubit*)
155+
declare void @__quantum__qis__cnot__body(ptr, ptr)
161156
162-
declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
157+
declare void @__quantum__qis__mz__body(ptr, ptr writeonly) #1
163158
164159
; declarations of runtime functions for initialization and output recording
165160
166-
declare void @__quantum__rt__initialize(i8*)
161+
declare void @__quantum__rt__initialize(ptr)
167162
168-
declare void @__quantum__rt__tuple_record_output(i64, i8*)
163+
declare void @__quantum__rt__tuple_record_output(i64, ptr)
169164
170-
declare void @__quantum__rt__result_record_output(%Result*, i8*)
165+
declare void @__quantum__rt__result_record_output(ptr, ptr)
171166
172167
; attributes
173168
@@ -179,7 +174,7 @@ attributes #1 = { "irreversible" }
179174
180175
!llvm.module.flags = !{!0, !1, !2, !3}
181176
182-
!0 = !{i32 1, !"qir_major_version", i32 1}
177+
!0 = !{i32 1, !"qir_major_version", i32 2}
183178
!1 = !{i32 7, !"qir_minor_version", i32 0}
184179
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
185180
!3 = !{i32 1, !"dynamic_result_management", i1 false}
@@ -235,7 +230,7 @@ one to the other. Both blocks consist (only) of calls to [QIS
235230
functions](#quantum-instruction-set). Any number of such calls may be performed.
236231
To be compatible with the Base Profile the called functions must return void.
237232
Any arguments to invoke them must be inlined into the call itself; they must be
238-
constants or pointers of type `%Qubit*` or `%Result*`.
233+
constants or pointers of type `ptr`.
239234

240235
The only difference between these two blocks is that the first one contains only
241236
calls to functions that are *not* marked as irreversible by an attribute on the
@@ -268,8 +263,8 @@ must satisfy the following three requirements:
268263
with an custom function attribute named `irreversible`. The use of
269264
[attributes](#attributes) in general is outlined in the corresponding section.
270265

271-
- Parameters of type `%Result*` must be `writeonly` parameters; only the runtime
272-
function `__quantum__rt__result_record_output` used for [output
266+
- Parameters of type `ptr` identifying results must be `writeonly` parameters;
267+
only the runtime function `__quantum__rt__result_record_output` used for [output
273268
recording](#output-recording) may read a measurement result.
274269

275270
For more information about the relation between a profile specification and the
@@ -289,8 +284,8 @@ within a Base Profile compliant program:
289284
| `call` | Used within a basic block to invoke any one of the declared QIS functions and runtime functions. | May optionally be preceded by a [`tail` marker](https://llvm.org/docs/LangRef.html#call-instruction). |
290285
| `br` | Used to branch from one basic block to another. | The branching must be unconditional and occurs as the final instruction of a block to jump to the next one. |
291286
| `ret` | Used to return the exit code of the program. | Must occur (only) as the last instruction of the final block in an entry point. |
292-
| `inttoptr` | Used to cast an `i64` integer value to either a `%Qubit*` or a `%Result*`. | May be used as part of a function call only. |
293-
| `getelementptr inbounds` | Used to create an `i8*` to pass a constant string for the purpose of labeling an output value. | May be used as part of a call to an output recording function only. |
287+
| `inttoptr` | Used to cast an `i64` integer value to a `ptr`. | May be used as part of a function call only. |
288+
| `getelementptr inbounds` | Used to create a `ptr` to pass a constant string for the purpose of labeling an output value. | May be used as part of a call to an output recording function only. |
294289

295290
See also the section on [data types and values](#data-types-and-values) for more
296291
information about the creation and usage of LLVM values.
@@ -303,10 +298,10 @@ program:
303298

304299
| Function | Signature | Description |
305300
| :---------------------------------- | :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
306-
| __quantum__rt__initialize | `void(i8*)` | Initializes the execution environment. Sets all qubits to a zero-state if they are not dynamically managed. |
307-
| __quantum__rt__tuple_record_output | `void(i64, i8*)` | Inserts a marker in the generated output that indicates the start of a tuple and how many tuple elements it has. The second parameter defines a string label for the tuple. Depending on the output schema, the label is included in the output or omitted. |
308-
| __quantum__rt__array_record_output | `void(i64, i8*)` | Inserts a marker in the generated output that indicates the start of an array and how many array elements it has. The second parameter defines a string label for the array. Depending on the output schema, the label is included in the output or omitted. |
309-
| __quantum__rt__result_record_output | `void(%Result*, i8*)` | Adds a measurement result to the generated output. The second parameter defines a string label for the result value. Depending on the output schema, the label is included in the output or omitted. |
301+
| __quantum__rt__initialize | `void(ptr)` | Initializes the execution environment. Sets all qubits to a zero-state if they are not dynamically managed. |
302+
| __quantum__rt__tuple_record_output | `void(i64, ptr)` | Inserts a marker in the generated output that indicates the start of a tuple and how many tuple elements it has. The second parameter defines a string label for the tuple. Depending on the output schema, the label is included in the output or omitted. |
303+
| __quantum__rt__array_record_output | `void(i64, ptr)` | Inserts a marker in the generated output that indicates the start of an array and how many array elements it has. The second parameter defines a string label for the array. Depending on the output schema, the label is included in the output or omitted. |
304+
| __quantum__rt__result_record_output | `void(ptr, ptr)` | Adds a measurement result to the generated output. The second parameter defines a string label for the result value. Depending on the output schema, the label is included in the output or omitted. |
310305

311306
### Initialization
312307

@@ -324,7 +319,7 @@ to the runtime functions ending in `record_output` listed in the table
324319
contained within the final block of an entry point function, i.e. the block that
325320
terminates in a return instruction.
326321

327-
For all output recording functions, the `i8*` argument must be a non-null
322+
For all output recording functions, the `ptr` argument must be a non-null
328323
pointer to a global constant that contains a null-terminated string. A unique
329324
string must be used for each call to an output recording function within the
330325
same entry point. A backend may ignore that argument depending on the [output
@@ -357,15 +352,15 @@ of type `i64` in particular may be used as part of calls to output recording
357352
functions; see the section on [output recording](#output-recording) for more
358353
details.
359354

360-
The `%Qubit*` and `%Result*` data types must be supported by all backends.
355+
The `ptr` data types must be supported by all backends.
361356
Qubits and results can occur only as arguments in function calls and are
362-
represented as a pointer of type `%Qubit*` and `%Result*` respectively, where
357+
represented as a pointer type, where
363358
the pointer itself identifies the qubit or result value rather than a memory
364359
location where the value is stored: a 64-bit integer constant is cast to the
365360
appropriate pointer type. A more detailed elaboration on the purpose of this
366361
representation is given in the next subsection. The integer constant that is
367-
cast must be in the interval `[0, numQubits)` for `%Qubit*` and `[0,
368-
numResults)` for `%Result*`, where `numQubits` and `numResults` are the required
362+
cast must be in the interval `[0, numQubits)` for qubits and `[0,
363+
numResults)` for results, where `numQubits` and `numResults` are the required
369364
number of qubits and results defined by the corresponding [entry point
370365
attributes](#attributes). Since backends may look at the values of the
371366
`required_num_qubits` and `required_num_results` attributes to determine whether
@@ -505,8 +500,8 @@ major and minor version of the specification that the QIR bitcode adheres to.
505500

506501
### Memory Management
507502

508-
Each bitcode file contains the information whether pointers of type `%Qubit*`
509-
and `%Result*` point to a valid memory location, or whether a pointer merely
503+
Each bitcode file contains the information whether instances of `ptr` used for
504+
qubits and results point to a valid memory location, or whether a pointer merely
510505
encodes an integer constant that identifies which qubit or result the value
511506
refers to. This information is represented in the form of the two module flags
512507
named `"dynamic_qubit_management"` and `"dynamic_result_management"`. Within the

0 commit comments

Comments
 (0)