@@ -1523,7 +1523,7 @@ nb::object PyOperation::create(std::string_view name,
1523
1523
llvm::ArrayRef<MlirValue> operands,
1524
1524
std::optional<nb::dict> attributes,
1525
1525
std::optional<std::vector<PyBlock *>> successors,
1526
- int regions, DefaultingPyLocation ___location,
1526
+ int regions, PyLocation ___location,
1527
1527
const nb::object &maybeIp, bool inferType) {
1528
1528
llvm::SmallVector<MlirType, 4 > mlirResults;
1529
1529
llvm::SmallVector<MlirBlock, 4 > mlirSuccessors;
@@ -1627,7 +1627,7 @@ nb::object PyOperation::create(std::string_view name,
1627
1627
if (!operation.ptr )
1628
1628
throw nb::value_error (" Operation creation failed" );
1629
1629
PyOperationRef created =
1630
- PyOperation::createDetached (___location-> getContext (), operation);
1630
+ PyOperation::createDetached (___location. getContext (), operation);
1631
1631
maybeInsertOperation (created, maybeIp);
1632
1632
1633
1633
return created.getObject ();
@@ -1937,9 +1937,9 @@ nb::object PyOpView::buildGeneric(
1937
1937
std::optional<nb::list> resultTypeList, nb::list operandList,
1938
1938
std::optional<nb::dict> attributes,
1939
1939
std::optional<std::vector<PyBlock *>> successors,
1940
- std::optional<int > regions, DefaultingPyLocation ___location,
1940
+ std::optional<int > regions, PyLocation ___location,
1941
1941
const nb::object &maybeIp) {
1942
- PyMlirContextRef context = ___location-> getContext ();
1942
+ PyMlirContextRef context = ___location. getContext ();
1943
1943
1944
1944
// Class level operation construction metadata.
1945
1945
// Operand and result segment specs are either none, which does no
@@ -2789,6 +2789,70 @@ class PyOpAttributeMap {
2789
2789
PyOperationRef operation;
2790
2790
};
2791
2791
2792
+ std::optional<MlirLocation> tracebackToLocation (MlirContext ctx) {
2793
+ // We use a thread_local here mostly to avoid requiring a large amount of
2794
+ // space.
2795
+ size_t frames_limit = 100 ;
2796
+ thread_local std::vector<MlirLocation> frames;
2797
+ frames.reserve (frames_limit);
2798
+ int count = 0 ;
2799
+
2800
+ assert (PyGILState_Check ());
2801
+
2802
+ if (!PyGlobals::get ().tracebacksEnabled ())
2803
+ return std::nullopt;
2804
+
2805
+ PyThreadState *thread_state = PyThreadState_GET ();
2806
+
2807
+ PyFrameObject *next;
2808
+ for (PyFrameObject *py_frame = PyThreadState_GetFrame (thread_state);
2809
+ py_frame != nullptr && count < frames_limit; py_frame = next) {
2810
+ PyCodeObject *code = PyFrame_GetCode (py_frame);
2811
+ int lasti = PyFrame_GetLasti (py_frame);
2812
+ MlirStringRef fileName = mlirStringRefCreateFromCString (
2813
+ nb::borrow<nb::str>(code->co_filename ).c_str ());
2814
+
2815
+ #if PY_VERSION_HEX < 0x030b00f0
2816
+ MlirStringRef funcName = mlirStringRefCreateFromCString (
2817
+ nb::borrow<nb::str>(frame.code ->co_name ).c_str ());
2818
+ auto line = PyCode_Addr2Line (frame.code , frame.lasti );
2819
+ auto loc = mlirLocationFileLineColGet (ctx, fileName, line, 0 );
2820
+ #else
2821
+ MlirStringRef funcName = mlirStringRefCreateFromCString (
2822
+ nb::borrow<nb::str>(code->co_qualname ).c_str ());
2823
+ int start_line, start_column, end_line, end_column;
2824
+ if (!PyCode_Addr2Location (code, lasti, &start_line, &start_column,
2825
+ &end_line, &end_column)) {
2826
+ throw nb::python_error ();
2827
+ }
2828
+ auto loc = mlirLocationFileLineColRangeGet (
2829
+ ctx, fileName, start_column, start_column, end_line, end_column);
2830
+ #endif
2831
+
2832
+ frames.push_back (mlirLocationNameGet (ctx, funcName, loc));
2833
+ ++count;
2834
+ next = PyFrame_GetBack (py_frame);
2835
+ Py_XDECREF (py_frame);
2836
+
2837
+ if (frames.size () > frames_limit)
2838
+ break ;
2839
+ }
2840
+
2841
+ if (frames.empty ())
2842
+ return mlirLocationUnknownGet (ctx);
2843
+ if (frames.size () == 1 )
2844
+ return frames.front ();
2845
+
2846
+ MlirLocation callee = frames.front ();
2847
+ frames.erase (frames.begin ());
2848
+ MlirLocation caller = frames.back ();
2849
+ for (const MlirLocation &frame :
2850
+ llvm::reverse (llvm::ArrayRef (frames).drop_back ()))
2851
+ caller = mlirLocationCallSiteGet (frame, caller);
2852
+
2853
+ return mlirLocationCallSiteGet (callee, caller);
2854
+ }
2855
+
2792
2856
} // namespace
2793
2857
2794
2858
// ------------------------------------------------------------------------------
@@ -3241,6 +3305,10 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3241
3305
.def_static (
3242
3306
" create" ,
3243
3307
[](DefaultingPyLocation loc) {
3308
+ PyMlirContextRef ctx = loc->getContext ();
3309
+ MlirLocation mlirLoc = loc;
3310
+ if (auto tloc = tracebackToLocation (ctx->get ()))
3311
+ mlirLoc = *tloc;
3244
3312
MlirModule module = mlirModuleCreateEmpty (loc);
3245
3313
return PyModule::forModule (module ).releaseObject ();
3246
3314
},
@@ -3467,9 +3535,15 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3467
3535
}
3468
3536
}
3469
3537
3538
+ PyMlirContextRef ctx = ___location->getContext ();
3539
+ if (auto loc = tracebackToLocation (ctx->get ())) {
3540
+ return PyOperation::create (name, results, mlirOperands,
3541
+ attributes, successors, regions,
3542
+ {ctx, *loc}, maybeIp, inferType);
3543
+ }
3470
3544
return PyOperation::create (name, results, mlirOperands, attributes,
3471
- successors, regions, ___location, maybeIp ,
3472
- inferType);
3545
+ successors, regions, * ___location. get () ,
3546
+ maybeIp, inferType);
3473
3547
},
3474
3548
nb::arg (" name" ), nb::arg (" results" ).none () = nb::none (),
3475
3549
nb::arg (" operands" ).none () = nb::none (),
@@ -3514,10 +3588,19 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3514
3588
std::optional<std::vector<PyBlock *>> successors,
3515
3589
std::optional<int > regions, DefaultingPyLocation ___location,
3516
3590
const nb::object &maybeIp) {
3517
- new (self) PyOpView (PyOpView::buildGeneric (
3518
- name, opRegionSpec, operandSegmentSpecObj,
3519
- resultSegmentSpecObj, resultTypeList, operandList,
3520
- attributes, successors, regions, ___location, maybeIp));
3591
+ PyMlirContextRef ctx = ___location->getContext ();
3592
+ if (auto loc = tracebackToLocation (ctx->get ())) {
3593
+ new (self) PyOpView (PyOpView::buildGeneric (
3594
+ name, opRegionSpec, operandSegmentSpecObj,
3595
+ resultSegmentSpecObj, resultTypeList, operandList,
3596
+ attributes, successors, regions, {ctx, *loc}, maybeIp));
3597
+ } else {
3598
+ new (self) PyOpView (PyOpView::buildGeneric (
3599
+ name, opRegionSpec, operandSegmentSpecObj,
3600
+ resultSegmentSpecObj, resultTypeList, operandList,
3601
+ attributes, successors, regions, *___location.get (),
3602
+ maybeIp));
3603
+ }
3521
3604
},
3522
3605
nb::arg (" name" ), nb::arg (" opRegionSpec" ),
3523
3606
nb::arg (" operandSegmentSpecObj" ).none () = nb::none (),
@@ -3558,10 +3641,18 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3558
3641
nb::cast<std::tuple<int , bool >>(cls.attr (" _ODS_REGIONS" ));
3559
3642
nb::object operandSegmentSpec = cls.attr (" _ODS_OPERAND_SEGMENTS" );
3560
3643
nb::object resultSegmentSpec = cls.attr (" _ODS_RESULT_SEGMENTS" );
3644
+
3645
+ PyMlirContextRef ctx = ___location->getContext ();
3646
+ if (auto loc = tracebackToLocation (ctx->get ())) {
3647
+ return PyOpView::buildGeneric (name, opRegionSpec, operandSegmentSpec,
3648
+ resultSegmentSpec, resultTypeList,
3649
+ operandList, attributes, successors,
3650
+ regions, {ctx, *loc}, maybeIp);
3651
+ }
3561
3652
return PyOpView::buildGeneric (name, opRegionSpec, operandSegmentSpec,
3562
3653
resultSegmentSpec, resultTypeList,
3563
3654
operandList, attributes, successors,
3564
- regions, ___location, maybeIp);
3655
+ regions, * ___location. get () , maybeIp);
3565
3656
},
3566
3657
nb::arg (" cls" ), nb::arg (" results" ).none () = nb::none (),
3567
3658
nb::arg (" operands" ).none () = nb::none (),
0 commit comments