2323#include < mlir/Dialect/Func/IR/FuncOps.h>
2424#include < mlir/IR/Builders.h>
2525#include < mlir/IR/BuiltinOps.h>
26+ #include < mlir/IR/Location.h>
2627#include < mlir/IR/MLIRContext.h>
2728#include < mlir/IR/OwningOpRef.h>
2829#include < mlir/IR/Value.h>
3435namespace mlir ::qco {
3536
3637QCOProgramBuilder::QCOProgramBuilder (MLIRContext* context)
37- : OpBuilder(context), ctx(context), loc(getUnknownLoc()),
38- module (ModuleOp::create(loc)) {
38+ : ImplicitLocOpBuilder(
39+ FileLineColLoc::get (context, " <qco-program-builder>" , 1 , 1 ), context),
40+ ctx(context), module(ModuleOp::create(*this )) {
3941 ctx->loadDialect <QCODialect>();
4042}
4143
@@ -45,7 +47,7 @@ void QCOProgramBuilder::initialize() {
4547
4648 // Create main function as entry point
4749 auto funcType = getFunctionType ({}, {getI64Type ()});
48- auto mainFunc = func::FuncOp::create (*this , loc, " main" , funcType);
50+ auto mainFunc = func::FuncOp::create (*this , " main" , funcType);
4951
5052 // Add entry_point attribute to identify the main function
5153 auto entryPointAttr = getStringAttr (" entry_point" );
@@ -59,7 +61,7 @@ void QCOProgramBuilder::initialize() {
5961Value QCOProgramBuilder::allocQubit () {
6062 checkFinalized ();
6163
62- auto allocOp = AllocOp::create (*this , loc );
64+ auto allocOp = AllocOp::create (*this );
6365 const auto qubit = allocOp.getResult ();
6466
6567 // Track the allocated qubit as valid
@@ -76,7 +78,7 @@ Value QCOProgramBuilder::staticQubit(const int64_t index) {
7678 }
7779
7880 auto indexAttr = getI64IntegerAttr (index);
79- auto staticOp = StaticOp::create (*this , loc, indexAttr);
81+ auto staticOp = StaticOp::create (*this , indexAttr);
8082 const auto qubit = staticOp.getQubit ();
8183
8284 // Track the static qubit as valid
@@ -102,7 +104,7 @@ QCOProgramBuilder::allocQubitRegister(const int64_t size,
102104
103105 for (int64_t i = 0 ; i < size; ++i) {
104106 const auto indexAttr = getI64IntegerAttr (i);
105- auto allocOp = AllocOp::create (*this , loc, nameAttr, sizeAttr, indexAttr);
107+ auto allocOp = AllocOp::create (*this , nameAttr, sizeAttr, indexAttr);
106108 const auto & qubit = qubits.emplace_back (allocOp.getResult ());
107109 // Track the allocated qubit as valid
108110 validQubits.insert (qubit);
@@ -156,7 +158,7 @@ void QCOProgramBuilder::updateQubitTracking(Value inputQubit,
156158std::pair<Value, Value> QCOProgramBuilder::measure (Value qubit) {
157159 checkFinalized ();
158160
159- auto measureOp = MeasureOp::create (*this , loc, qubit);
161+ auto measureOp = MeasureOp::create (*this , qubit);
160162 auto qubitOut = measureOp.getQubitOut ();
161163 auto result = measureOp.getResult ();
162164
@@ -173,7 +175,7 @@ Value QCOProgramBuilder::measure(Value qubit, const Bit& bit) {
173175 auto sizeAttr = getI64IntegerAttr (bit.registerSize );
174176 auto indexAttr = getI64IntegerAttr (bit.registerIndex );
175177 auto measureOp =
176- MeasureOp::create (*this , loc, qubit, nameAttr, sizeAttr, indexAttr);
178+ MeasureOp::create (*this , qubit, nameAttr, sizeAttr, indexAttr);
177179 const auto qubitOut = measureOp.getQubitOut ();
178180
179181 // Update tracking
@@ -185,7 +187,7 @@ Value QCOProgramBuilder::measure(Value qubit, const Bit& bit) {
185187Value QCOProgramBuilder::reset (Value qubit) {
186188 checkFinalized ();
187189
188- auto resetOp = ResetOp::create (*this , loc, qubit);
190+ auto resetOp = ResetOp::create (*this , qubit);
189191 const auto qubitOut = resetOp.getQubitOut ();
190192
191193 // Update tracking
@@ -203,7 +205,7 @@ Value QCOProgramBuilder::reset(Value qubit) {
203205#define DEFINE_ZERO_TARGET_ONE_PARAMETER (OP_CLASS, OP_NAME, PARAM ) \
204206 void QCOProgramBuilder::OP_NAME (const std::variant<double , Value>&(PARAM)) { \
205207 checkFinalized (); \
206- OP_CLASS::create (*this , loc, PARAM); \
208+ OP_CLASS::create (*this , PARAM); \
207209 } \
208210 Value QCOProgramBuilder::c##OP_NAME( \
209211 const std::variant<double , Value>&(PARAM), Value control) { \
@@ -239,7 +241,7 @@ DEFINE_ZERO_TARGET_ONE_PARAMETER(GPhaseOp, gphase, theta)
239241#define DEFINE_ONE_TARGET_ZERO_PARAMETER (OP_CLASS, OP_NAME ) \
240242 Value QCOProgramBuilder::OP_NAME (Value qubit) { \
241243 checkFinalized (); \
242- auto op = OP_CLASS::create (*this , loc, qubit); \
244+ auto op = OP_CLASS::create (*this , qubit); \
243245 const auto & qubitOut = op.getQubitOut (); \
244246 updateQubitTracking (qubit, qubitOut); \
245247 return qubitOut; \
@@ -284,7 +286,7 @@ DEFINE_ONE_TARGET_ZERO_PARAMETER(SXdgOp, sxdg)
284286 Value QCOProgramBuilder::OP_NAME (const std::variant<double , Value>&(PARAM), \
285287 Value qubit) { \
286288 checkFinalized (); \
287- auto op = OP_CLASS::create (*this , loc, qubit, PARAM); \
289+ auto op = OP_CLASS::create (*this , qubit, PARAM); \
288290 const auto & qubitOut = op.getQubitOut (); \
289291 updateQubitTracking (qubit, qubitOut); \
290292 return qubitOut; \
@@ -325,7 +327,7 @@ DEFINE_ONE_TARGET_ONE_PARAMETER(POp, p, phi)
325327 const std::variant<double, Value>&(PARAM2), \
326328 Value qubit) { \
327329 checkFinalized (); \
328- auto op = OP_CLASS::create (*this , loc, qubit, PARAM1, PARAM2); \
330+ auto op = OP_CLASS::create (*this , qubit, PARAM1, PARAM2); \
329331 const auto & qubitOut = op.getQubitOut (); \
330332 updateQubitTracking (qubit, qubitOut); \
331333 return qubitOut; \
@@ -368,7 +370,7 @@ DEFINE_ONE_TARGET_TWO_PARAMETER(U2Op, u2, phi, lambda)
368370 const std::variant<double, Value>&(PARAM3), \
369371 Value qubit) { \
370372 checkFinalized (); \
371- auto op = OP_CLASS::create (*this , loc, qubit, PARAM1, PARAM2, PARAM3); \
373+ auto op = OP_CLASS::create (*this , qubit, PARAM1, PARAM2, PARAM3); \
372374 const auto & qubitOut = op.getQubitOut (); \
373375 updateQubitTracking (qubit, qubitOut); \
374376 return qubitOut; \
@@ -409,7 +411,7 @@ DEFINE_ONE_TARGET_THREE_PARAMETER(UOp, u, theta, phi, lambda)
409411 std::pair<Value, Value> QCOProgramBuilder::OP_NAME (Value qubit0, \
410412 Value qubit1) { \
411413 checkFinalized (); \
412- auto op = OP_CLASS::create (*this , loc, qubit0, qubit1); \
414+ auto op = OP_CLASS::create (*this , qubit0, qubit1); \
413415 const auto & qubit0Out = op.getQubit0Out (); \
414416 const auto & qubit1Out = op.getQubit1Out (); \
415417 updateQubitTracking (qubit0, qubit0Out); \
@@ -453,7 +455,7 @@ DEFINE_TWO_TARGET_ZERO_PARAMETER(ECROp, ecr)
453455 std::pair<Value, Value> QCOProgramBuilder::OP_NAME ( \
454456 const std::variant<double , Value>&(PARAM), Value qubit0, Value qubit1) { \
455457 checkFinalized (); \
456- auto op = OP_CLASS::create (*this , loc, qubit0, qubit1, PARAM); \
458+ auto op = OP_CLASS::create (*this , qubit0, qubit1, PARAM); \
457459 const auto & qubit0Out = op.getQubit0Out (); \
458460 const auto & qubit1Out = op.getQubit1Out (); \
459461 updateQubitTracking (qubit0, qubit0Out); \
@@ -501,7 +503,7 @@ DEFINE_TWO_TARGET_ONE_PARAMETER(RZZOp, rzz, theta)
501503 const std::variant<double, Value>&(PARAM2), Value qubit0, \
502504 Value qubit1) { \
503505 checkFinalized (); \
504- auto op = OP_CLASS::create (*this , loc, qubit0, qubit1, PARAM1, PARAM2); \
506+ auto op = OP_CLASS::create (*this , qubit0, qubit1, PARAM1, PARAM2); \
505507 const auto & qubit0Out = op.getQubit0Out (); \
506508 const auto & qubit1Out = op.getQubit1Out (); \
507509 updateQubitTracking (qubit0, qubit0Out); \
@@ -548,7 +550,7 @@ DEFINE_TWO_TARGET_TWO_PARAMETER(XXMinusYYOp, xx_minus_yy, theta, beta)
548550ValueRange QCOProgramBuilder::barrier (ValueRange qubits) {
549551 checkFinalized ();
550552
551- auto op = BarrierOp::create (*this , loc, qubits);
553+ auto op = BarrierOp::create (*this , qubits);
552554 const auto & qubitsOut = op.getQubitsOut ();
553555 for (const auto & [inputQubit, outputQubit] : llvm::zip (qubits, qubitsOut)) {
554556 updateQubitTracking (inputQubit, outputQubit);
@@ -565,17 +567,17 @@ std::pair<ValueRange, ValueRange> QCOProgramBuilder::ctrl(
565567 llvm::function_ref<llvm::SmallVector<Value>(ValueRange)> body) {
566568 checkFinalized ();
567569
568- auto ctrlOp = CtrlOp::create (*this , loc, controls, targets);
570+ auto ctrlOp = CtrlOp::create (*this , controls, targets);
569571 auto & block = ctrlOp.getBodyRegion ().emplaceBlock ();
570572 const auto qubitType = QubitType::get (getContext ());
571573 for (const auto target : targets) {
572- const auto arg = block.addArgument (qubitType, loc );
574+ const auto arg = block.addArgument (qubitType, getLoc () );
573575 updateQubitTracking (target, arg);
574576 }
575577 const InsertionGuard guard (*this );
576578 setInsertionPointToStart (&block);
577579 const auto innerTargetsOut = body (block.getArguments ());
578- YieldOp::create (*this , loc, innerTargetsOut);
580+ YieldOp::create (*this , innerTargetsOut);
579581
580582 if (innerTargetsOut.size () != targets.size ()) {
581583 llvm::reportFatalUsageError (
@@ -606,7 +608,7 @@ QCOProgramBuilder& QCOProgramBuilder::dealloc(Value qubit) {
606608 validateQubitValue (qubit);
607609 validQubits.erase (qubit);
608610
609- DeallocOp::create (*this , loc, qubit);
611+ DeallocOp::create (*this , qubit);
610612
611613 return *this ;
612614}
@@ -655,16 +657,16 @@ OwningOpRef<ModuleOp> QCOProgramBuilder::finalize() {
655657 return opA->isBeforeInBlock (opB);
656658 });
657659 for (auto qubit : sortedQubits) {
658- DeallocOp::create (*this , loc, qubit);
660+ DeallocOp::create (*this , qubit);
659661 }
660662
661663 validQubits.clear ();
662664
663665 // Create constant 0 for successful exit code
664- auto exitCode = arith::ConstantOp::create (*this , loc, getI64IntegerAttr (0 ));
666+ auto exitCode = arith::ConstantOp::create (*this , getI64IntegerAttr (0 ));
665667
666668 // Add return statement with exit code 0 to the main function
667- func::ReturnOp::create (*this , loc, ValueRange{exitCode});
669+ func::ReturnOp::create (*this , ValueRange{exitCode});
668670
669671 // Invalidate context to prevent use-after-finalize
670672 ctx = nullptr ;
0 commit comments