-
-
Notifications
You must be signed in to change notification settings - Fork 72
🧪 Establish a typed OpenQASM 3 frontend #1910
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
burgholzer
wants to merge
30
commits into
main
Choose a base branch
from
agent/oq3-foundation
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
64fe189
Vendor the pinned OpenQASM 3.1 grammar
burgholzer 4832ba2
Add an experimental typed OQ3 dialect
burgholzer e2daad9
Build a staged OpenQASM 3.1 frontend
burgholzer 666d894
Document the OQ3 foundation ExecPlan
burgholzer 3e2b0aa
Treat OpenQASM 3.0 as current OpenQASM 3
burgholzer a7e53a8
Replace the ANTLR frontend with a handwritten-parser plan
burgholzer 885a556
Update the OQ3 foundation progress
burgholzer 737db8a
Replace the direct OpenQASM MLIR translator
burgholzer 5f2f309
Simplify modifiers and complete scalar expressions
burgholzer 734948c
Stabilize OQ3 frontend invariants
burgholzer 0bc6d2c
Fix OQ3 dialect documentation generation
burgholzer 4766f7d
Fix OQ3 documentation and MLIR linting
burgholzer c8e93be
🎨 pre-commit fixes
pre-commit-ci[bot] 105e3f5
Fix OpenQASM frontend lint diagnostics
burgholzer 310fcc2
Expand OpenQASM frontend coverage
burgholzer 4c02537
Cover OpenQASM language builtins
burgholzer ccde1ba
Fix OpenQASM docs build dependencies
burgholzer ebd70f8
Cover canonical OQ3 gate lowering
burgholzer 9d3316b
Complete staged OpenQASM frontend
burgholzer bcca207
Remove intermediate OpenQASM dialect
burgholzer 79e7a8a
Tighten OpenQASM pipeline contracts
burgholzer 99ad652
Close OpenQASM pipeline acceptance gaps
burgholzer d0a197a
Clean up OpenQASM frontend residue
burgholzer 21bb4bd
Format OpenQASM support tables after rebase
burgholzer 67d697b
Fix OpenQASM Windows and lint CI
burgholzer 4cfef76
Clean up OpenQASM frontend internals
burgholzer 5e610fc
Broaden OpenQASM QC acceptance
burgholzer 508c4cd
Lower control-flow assertions to QIR
burgholzer 727c244
Separate standard and jeff compiler contracts
burgholzer 0ccdb32
Document OpenQASM pipeline contracts
burgholzer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -79,7 +79,7 @@ docs/api/ | |
|
|
||
| # PyBuilder | ||
| .pybuilder/ | ||
| target/ | ||
| /target/ | ||
|
|
||
| # Jupyter Notebook | ||
| .ipynb_checkpoints | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # OpenQASM input | ||
|
|
||
| The compiler reads OpenQASM 3 through a staged lexer, parser, and semantic | ||
| analyzer, then emits the QC dialect directly. OpenQASM is an input language, not | ||
| an intermediate dialect: a successful translation contains QC and standard MLIR | ||
| operations only. Translation fails before returning a module when the QC target | ||
| cannot represent an accepted source feature. | ||
|
|
||
| ## Parser and semantic support | ||
|
|
||
| | Feature | Status | Restriction | Representative test | | ||
| | -------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | | ||
| | OpenQASM 3.0 and 3.1 | Supported | Later 3.x versions are rejected | `PreservesExactAndOptionalVersionSemantics` | | ||
| | `stdgates.inc` and nested includes | Supported | Includes are expanded textually with bounded depth and source locations | `ExpandsNestedIncludesAtTheirSourceLocations` | | ||
| | Qubits, bits, and `bool`, `int`, `uint`, `float` scalars | Supported | Width-qualified integer and floating types are not yet supported | `RejectsUnsupportedIntegerDeclarations` | | ||
| | Lexical scope, assignment, and constants | Supported | Mutable global values cannot be captured by gate definitions | `TracksLexicalScopeAndEnclosingAssignments` | | ||
| | `if`, inclusive `for`, and `while` | Supported | Gate bodies contain gate calls and loops over gate calls only | `EmitsStructuredLoopsWithCarriedMutableState` | | ||
| | Expressions and scalar math functions | Supported | Operations are checked against the implemented scalar type rules | `AcceptsAllScalarOperatorsAndComparisonPredicates` | | ||
| | Dynamic qubit and bit indexing | Supported | Target restrictions and the combined emission budget are listed below | `DispatchesDynamicQubitGatesWithStructuredControlFlow` | | ||
| | Primitive, broadcast, and custom gates | Supported | Recursive definitions and mismatched broadcast widths are rejected | `BroadcastsRegistersAlongsideScalarQubits` | | ||
| | `inv`, `ctrl`, `negctrl`, and `pow` modifiers | Parsed and semantically checked | Target support differs below | `RejectsInvalidGateControlAndBroadcastShapes` | | ||
| | `input` declarations, subroutines, and `extern` | Recognized and rejected by the parser | `input`, `def`, `return`, and `extern` are reserved but are not in the implemented grammar | `DiagnosesUnsupportedReservedFeatureSyntax` | | ||
| | Calibration, timing, `duration`, and `stretch` | Recognized and rejected by the parser | `defcalgrammar`, `cal`, `defcal`, `delay`, `durationof`, `duration`, and `stretch` are not implemented | `DiagnosesUnsupportedReservedFeatureSyntax` | | ||
| | `array`, `complex`, `angle`, and aliases | Recognized and rejected by the parser | Aggregate, complex, angle, and `let` alias declarations have no typed representation yet | `RejectsUnsupportedReservedWordsAsIdentifiers` | | ||
| | `switch`, `break`, and `continue` | Recognized and rejected by the parser | These control-flow forms are reserved but are not in the implemented grammar | `RejectsUnsupportedReservedWordsAsIdentifiers` | | ||
| | Bitwise and shift operators | Parsed and rejected semantically | Explicitly sized `uint`, `bit`, or `angle` operands are required by the language and are not implemented | `RejectsInvalidProgramsAcrossSemanticFamilies` | | ||
|
|
||
| ## Translation and compiler support | ||
|
|
||
| The standard compiler path is OpenQASM to QC, optimized QCO, reconstructed QC, | ||
| and QIR. This is the primary acceptance contract. Serialization through `jeff` | ||
| is optional: a smaller positive corpus exercises it, while known incompatible | ||
| programs are accepted by the standard path and fail explicitly when QCO is | ||
| converted to `jeff`. Base refers to direct production of the QIR Base Profile. | ||
|
|
||
| | Feature | Parse | Semantics | QC | Standard Adaptive QIR | `jeff` | Base | Restriction or rejection reason | Representative test | | ||
| | ----------------------------------------------- | --------- | --------- | -------------------------------------------- | --------------------- | ------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | | ||
| | Primitive and custom gates | Supported | Supported | Supported | Supported | Supported in the positive corpus | Supported | Custom gates are expanded during QC emission | `broadcast_custom_gate` | | ||
| | Gate arithmetic and math parameters | Supported | Supported | Supported | Supported | Supported in the positive corpus | Supported | Scalar `pow()` is distinct from the gate modifier | `math_parameters` | | ||
| | Broadcast gates | Supported | Supported | Supported | Supported | Supported in the positive corpus | Supported | Operands must have compatible widths | `broadcast_custom_gate` | | ||
| | `inv`, `ctrl`, and `negctrl` | Supported | Supported | Supported | Supported | Supported in the positive corpus | Not in the tested Base subset | Modifiers on custom gates that require structured control flow are rejected | `RejectsModifiersOnTransitivelyStructuredCustomGatesAtQCTarget` | | ||
| | `pow @` | Supported | Supported | Rejected | Rejected | Rejected before `jeff` | Rejected | The QC dialect has no power modifier yet; translation reports the source location | `RejectsPowerAtTheQCTargetBoundary` | | ||
| | `if` and nested `if`/`for` | Supported | Supported | Supported | Supported | Supported in the positive corpus | Adaptive only | The Base corpus is intentionally straight-line | `nested_static_control_flow` | | ||
| | Measurement-controlled `while` | Supported | Supported | Supported | Supported | Supported in the positive corpus | Adaptive only | Requires runtime classical control | `measurement_controlled_while` | | ||
| | Loop-carried mutable bit and floating state | Supported | Supported | Supported | Supported | Supported in the positive corpus | Adaptive only | Carried state remains SSA values through QC, QCO, and reconstructed QC | `mutable_loop_state`, `scalar_loop_state` | | ||
| | Checked signed and wrapping unsigned arithmetic | Supported | Supported | Supported with runtime assertions | Supported | Rejected at QCO-to-`jeff` when live | Not in the tested Base subset | Signed overflow and invalid division are asserted; unsigned arithmetic wraps at 64 bits | `checked_integer_state` | | ||
| | Constant inclusive ranges | Supported | Supported | Supported with constant `scf.for` bounds | Supported | Supported when the body is compatible | Adaptive only | Positive, negative, empty, singleton, non-divisible, and boundary ranges avoid runtime trip-count math | `UsesConstantBoundsForStaticInclusiveRanges` | | ||
| | Dynamic inclusive ranges | Supported | Supported | Supported with comparison-driven `scf.while` | Supported | Rejected at QCO-to-`jeff` | Adaptive only | A dynamic zero step is asserted; iteration uses no division-based trip count | `dynamic_range` | | ||
| | Dynamic indexing resolved by optimization | Supported | Supported | Supported with bounds assertions | Supported | Supported when assertions fold away | Not in the tested Base subset | Straight-line constants and equal-constant branch joins can be simplified before `jeff` | `resolved_dynamic_index`, `equal_constant_index_join` | | ||
| | General runtime and induction-variable indexing | Supported | Supported | Supported with bounds assertions | Supported | Rejected at QCO-to-`jeff` | Not in the tested Base subset | The standard QIR path lowers the assertions; `jeff` cannot currently represent them | `runtime_dynamic_index`, `induction_variable_index` | | ||
| | Measurement, reset, and barrier | Supported | Supported | Supported | Supported | Supported in the positive corpus | Measurement and barrier supported | Reset is Adaptive-only | `reset`, `barrier` | | ||
| | Projected QC emission budget | Supported | Supported | Rejected above 100000 primitive applications | Rejected | Rejected before `jeff` | Rejected | One overflow-safe projection composes custom-gate expansion with dynamic-dispatch multiplicity | `ComposesDispatchAndCustomGateExpansionBudgets` | | ||
|
|
||
| The integration suites use public compiler APIs. The broad corpus must complete | ||
| the standard pipeline and the smaller `jeff` corpus must round-trip. The | ||
| incompatible corpus records failures at `intoJeff()` so those limitations do not | ||
| reduce the set of programs accepted by QC or QIR. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,63 @@ | ||
| InheritParentConfig: true | ||
| Checks: | | ||
| llvm-namespace-comment, | ||
| llvm-prefer-isa-or-dyn-cast-in-conditionals, | ||
| llvm-prefer-register-over-unsigned, | ||
| llvm-prefer-static-over-anonymous-namespace, | ||
| llvm-twine-local, | ||
| -bugprone-throwing-static-initialization, | ||
| -cppcoreguidelines-avoid-non-const-global-variables, | ||
| -cppcoreguidelines-pro-bounds-avoid-unchecked-container-access, | ||
| -misc-use-anonymous-namespace, | ||
| -modernize-type-traits, | ||
| -*-const-correctness, | ||
| InheritParentConfig: false | ||
|
|
||
| Checks: > | ||
| -*, | ||
| bugprone-argument-comment, | ||
| bugprone-assert-side-effect, | ||
| bugprone-branch-clone, | ||
| bugprone-copy-constructor-init, | ||
| bugprone-dangling-handle, | ||
| bugprone-dynamic-static-initializers, | ||
| bugprone-macro-parentheses, | ||
| bugprone-macro-repeated-side-effects, | ||
| bugprone-misplaced-widening-cast, | ||
| bugprone-move-forwarding-reference, | ||
| bugprone-multiple-statement-macro, | ||
| bugprone-suspicious-semicolon, | ||
| bugprone-swapped-arguments, | ||
| bugprone-terminating-continue, | ||
| bugprone-unused-raii, | ||
| bugprone-unused-return-value, | ||
| misc-redundant-expression, | ||
| misc-static-assert, | ||
| misc-unused-using-decls, | ||
| modernize-use-bool-literals, | ||
| modernize-loop-convert, | ||
| modernize-make-unique, | ||
| modernize-raw-string-literal, | ||
| modernize-use-equals-default, | ||
| modernize-use-default-member-init, | ||
| modernize-use-emplace, | ||
| modernize-use-nullptr, | ||
| modernize-use-override, | ||
| modernize-use-using, | ||
| performance-for-range-copy, | ||
| performance-implicit-conversion-in-loop, | ||
| performance-inefficient-algorithm, | ||
| performance-inefficient-vector-operation, | ||
| performance-move-const-arg, | ||
| performance-no-automatic-move, | ||
| performance-trivially-destructible, | ||
| performance-unnecessary-copy-initialization, | ||
| performance-unnecessary-value-param, | ||
| readability-avoid-const-params-in-decls, | ||
| readability-const-return-type, | ||
| readability-container-size-empty, | ||
| readability-inconsistent-declaration-parameter-name, | ||
| readability-misleading-indentation, | ||
| readability-redundant-control-flow, | ||
| readability-redundant-smartptr-get, | ||
| readability-simplify-boolean-expr, | ||
| readability-simplify-subscript-expr, | ||
| readability-use-anyofallof | ||
|
|
||
| CheckOptions: | ||
| - key: readability-identifier-naming.MemberCase | ||
| value: camelBack | ||
| - key: readability-identifier-naming.ParameterCase | ||
| value: camelBack | ||
| - key: readability-identifier-naming.VariableCase | ||
| value: camelBack | ||
| - key: modernize-use-using.IgnoreExternC | ||
| value: true | ||
| FormatStyle: file |
168 changes: 168 additions & 0 deletions
168
mlir/include/mlir/Target/OpenQASM/Detail/OpenQASMLexer.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| /* | ||
| * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM | ||
| * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH | ||
| * All rights reserved. | ||
| * | ||
| * SPDX-License-Identifier: MIT | ||
| * | ||
| * Licensed under the MIT License | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <llvm/ADT/StringRef.h> | ||
| #include <llvm/Support/SMLoc.h> | ||
| #include <mlir/Support/LLVM.h> | ||
|
|
||
| #include <cstdint> | ||
|
|
||
| namespace mlir::oq3::frontend::detail { | ||
|
|
||
| /// The kind of a lexical token. | ||
| enum class TokenKind : uint8_t { | ||
| Eof, | ||
| Error, | ||
| UnterminatedComment, | ||
| UnsupportedKeyword, | ||
|
|
||
| // Keywords | ||
| OpenQASM, | ||
| Include, | ||
| Const, | ||
| Qubit, | ||
| Qreg, | ||
| Bit, | ||
| CReg, | ||
| Gate, | ||
| Opaque, | ||
| Output, | ||
| Barrier, | ||
| Reset, | ||
| Measure, | ||
| If, | ||
| Else, | ||
| For, | ||
| While, | ||
| In, | ||
| Gphase, | ||
| Inv, | ||
| Pow, | ||
| Ctrl, | ||
| NegCtrl, | ||
|
|
||
| // Types | ||
| Int, | ||
| Uint, | ||
| Bool, | ||
| Float, | ||
| Angle, | ||
| Duration, | ||
| True, | ||
| False, | ||
|
|
||
| // Identifiers and literals | ||
| Identifier, | ||
| HardwareQubit, | ||
| StringLiteral, | ||
| IntegerLiteral, | ||
| FloatLiteral, | ||
|
|
||
| // Punctuation | ||
| LParen, | ||
| RParen, | ||
| LBracket, | ||
| RBracket, | ||
| LBrace, | ||
| RBrace, | ||
| Comma, | ||
| Semicolon, | ||
| Colon, | ||
| Arrow, | ||
| At, | ||
|
|
||
| // Operators | ||
| Equals, | ||
| Plus, | ||
| Minus, | ||
| Asterisk, | ||
| DoubleAsterisk, | ||
| Slash, | ||
| Percent, | ||
| Tilde, | ||
| Amp, | ||
| Pipe, | ||
| Caret, | ||
| ShiftLeft, | ||
| ShiftRight, | ||
| ExclamationPoint, | ||
| AmpAmp, // `&&` | ||
| PipePipe, // `||` | ||
| CompoundAssign, // `+=`, `-=`, ... | ||
|
|
||
| // Comparisons | ||
| EqualsEquals, | ||
| NotEquals, | ||
| Less, | ||
| LessEquals, | ||
| Greater, | ||
| GreaterEquals, | ||
| }; | ||
|
|
||
| /// A human-readable name for @p kind, used in diagnostics. | ||
| [[nodiscard]] StringRef describe(TokenKind kind); | ||
|
|
||
| /** | ||
| * @brief A single lexical token. | ||
| * | ||
| * @details | ||
| * Spellings are zero-copy views into the source buffer. Literals are | ||
| * pre-parsed. | ||
| */ | ||
| struct Token { | ||
| TokenKind kind = TokenKind::Eof; | ||
| SMLoc loc; | ||
| StringRef identifier; ///< For `Identifier` tokens. | ||
| StringRef stringValue; ///< For `StringLiteral` tokens. | ||
| StringRef spelling; ///< Zero-copy source spelling. | ||
| uint64_t intValue = 0; | ||
| double floatValue = 0.0; | ||
| }; | ||
|
|
||
| /** | ||
| * @brief A zero-copy lexer over an OpenQASM 3 source buffer. | ||
| * | ||
| * @details | ||
| * The lexer holds pointers into the buffer and produces tokens on demand | ||
| * without allocating. Token locations are `SMLoc`s into the buffer, so they can | ||
| * be resolved to line/column via the owning `llvm::SourceMgr`. | ||
| */ | ||
| class Lexer { | ||
| public: | ||
| explicit Lexer(StringRef buffer) : cur(buffer.begin()), end(buffer.end()) {} | ||
|
|
||
| /// Produce the next token, or an `Eof`/`Error` token at the end/on failure. | ||
| [[nodiscard]] Token next(); | ||
|
|
||
| private: | ||
| [[nodiscard]] bool atEnd() const { return cur == end; } | ||
|
|
||
| /// The character after the cursor, or `'\0'` at the end of the buffer. | ||
| [[nodiscard]] char peek() const { return (cur + 1) != end ? cur[1] : '\0'; } | ||
|
|
||
| /** | ||
| * @brief Skip whitespace and comments. | ||
| * @return The start of an unterminated block comment, or `nullptr` if the | ||
| * trivia is well-formed. | ||
| */ | ||
| [[nodiscard]] const char* skipTrivia(); | ||
|
|
||
| [[nodiscard]] Token lexIdentifierOrKeyword(const char* start); | ||
| [[nodiscard]] Token lexNumber(const char* start); | ||
| [[nodiscard]] Token lexString(const char* start, char quote); | ||
| [[nodiscard]] Token lexHardwareQubit(const char* start); | ||
|
|
||
| const char* cur; | ||
| const char* end; | ||
| }; | ||
|
|
||
| } // namespace mlir::oq3::frontend::detail |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move all header files from this directory to
mlir/include/mlir/Target/OpenQASM?