@@ -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,94 @@ class PyOpAttributeMap {
2789
2789
PyOperationRef operation;
2790
2790
};
2791
2791
2792
+ // bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1
2793
+ #if PY_VERSION_HEX < 0x030b00b1 && !defined(PYPY_VERSION)
2794
+ int PyFrame_GetLasti (PyFrameObject *frame) {
2795
+ #if PY_VERSION_HEX >= 0x030a00a7
2796
+ // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset,
2797
+ // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes)
2798
+ // instructions.
2799
+ if (frame->f_lasti < 0 ) {
2800
+ return -1 ;
2801
+ }
2802
+ return frame->f_lasti * 2 ;
2803
+ #else
2804
+ return frame->f_lasti ;
2805
+ #endif
2806
+ }
2807
+ #endif
2808
+
2809
+ std::optional<MlirLocation> tracebackToLocation (MlirContext ctx) {
2810
+ size_t framesLimit = PyGlobals::get ().locTracebackFramesLimit ();
2811
+ // We use a thread_local here mostly to avoid requiring a large amount of
2812
+ // space.
2813
+ thread_local std::vector<MlirLocation> frames;
2814
+ frames.reserve (framesLimit);
2815
+ size_t count = 0 ;
2816
+
2817
+ assert (PyGILState_Check ());
2818
+
2819
+ if (!PyGlobals::get ().locTracebacksEnabled ())
2820
+ return std::nullopt;
2821
+
2822
+ PyThreadState *tstate = PyThreadState_GET ();
2823
+
2824
+ PyFrameObject *next;
2825
+ for (PyFrameObject *pyFrame = PyThreadState_GetFrame (tstate);
2826
+ pyFrame != nullptr && count < framesLimit; pyFrame = next) {
2827
+ PyCodeObject *code = PyFrame_GetCode (pyFrame);
2828
+ auto fileNameStr =
2829
+ nb::cast<std::string>(nb::borrow<nb::str>(code->co_filename ));
2830
+ llvm::StringRef fileName (fileNameStr);
2831
+ if (!PyGlobals::get ().isUserTracebackFilename (fileName))
2832
+ continue ;
2833
+
2834
+ #if PY_VERSION_HEX < 0x030b00f0
2835
+ std::string name =
2836
+ nb::cast<std::string>(nb::borrow<nb::str>(code->co_name ));
2837
+ llvm::StringRef funcName (name);
2838
+ int startLine = PyFrame_GetLineNumber (pyFrame);
2839
+ MlirLocation loc =
2840
+ mlirLocationFileLineColGet (ctx, wrap (fileName), startLine, 0 );
2841
+ #else
2842
+ // co_qualname added in py3.11
2843
+ std::string name =
2844
+ nb::cast<std::string>(nb::borrow<nb::str>(code->co_qualname ));
2845
+ llvm::StringRef funcName (name);
2846
+ int startLine, startCol, endLine, endCol;
2847
+ int lasti = PyFrame_GetLasti (pyFrame);
2848
+ if (!PyCode_Addr2Location (code, lasti, &startLine, &startCol, &endLine,
2849
+ &endCol)) {
2850
+ throw nb::python_error ();
2851
+ }
2852
+ MlirLocation loc = mlirLocationFileLineColRangeGet (
2853
+ ctx, wrap (fileName), startCol, startCol, endLine, endCol);
2854
+ #endif
2855
+
2856
+ frames.push_back (mlirLocationNameGet (ctx, wrap (funcName), loc));
2857
+ ++count;
2858
+ next = PyFrame_GetBack (pyFrame);
2859
+ Py_XDECREF (pyFrame);
2860
+
2861
+ if (frames.size () > framesLimit)
2862
+ break ;
2863
+ }
2864
+
2865
+ if (frames.empty ())
2866
+ return mlirLocationUnknownGet (ctx);
2867
+ if (frames.size () == 1 )
2868
+ return frames.front ();
2869
+
2870
+ MlirLocation callee = frames.front ();
2871
+ frames.erase (frames.begin ());
2872
+ MlirLocation caller = frames.back ();
2873
+ for (const MlirLocation &frame :
2874
+ llvm::reverse (llvm::ArrayRef (frames).drop_back ()))
2875
+ caller = mlirLocationCallSiteGet (frame, caller);
2876
+
2877
+ return mlirLocationCallSiteGet (callee, caller);
2878
+ }
2879
+
2792
2880
} // namespace
2793
2881
2794
2882
// ------------------------------------------------------------------------------
@@ -3241,7 +3329,11 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3241
3329
.def_static (
3242
3330
" create" ,
3243
3331
[](DefaultingPyLocation loc) {
3244
- MlirModule module = mlirModuleCreateEmpty (loc);
3332
+ PyMlirContextRef ctx = loc->getContext ();
3333
+ MlirLocation mlirLoc = loc;
3334
+ if (auto tloc = tracebackToLocation (ctx->get ()))
3335
+ mlirLoc = *tloc;
3336
+ MlirModule module = mlirModuleCreateEmpty (mlirLoc);
3245
3337
return PyModule::forModule (module ).releaseObject ();
3246
3338
},
3247
3339
nb::arg (" loc" ).none () = nb::none (), " Creates an empty module" )
@@ -3467,9 +3559,15 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3467
3559
}
3468
3560
}
3469
3561
3562
+ PyMlirContextRef ctx = ___location->getContext ();
3563
+ if (auto loc = tracebackToLocation (ctx->get ())) {
3564
+ return PyOperation::create (name, results, mlirOperands,
3565
+ attributes, successors, regions,
3566
+ {ctx, *loc}, maybeIp, inferType);
3567
+ }
3470
3568
return PyOperation::create (name, results, mlirOperands, attributes,
3471
- successors, regions, ___location, maybeIp ,
3472
- inferType);
3569
+ successors, regions, * ___location. get () ,
3570
+ maybeIp, inferType);
3473
3571
},
3474
3572
nb::arg (" name" ), nb::arg (" results" ).none () = nb::none (),
3475
3573
nb::arg (" operands" ).none () = nb::none (),
@@ -3514,10 +3612,19 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3514
3612
std::optional<std::vector<PyBlock *>> successors,
3515
3613
std::optional<int > regions, DefaultingPyLocation ___location,
3516
3614
const nb::object &maybeIp) {
3517
- new (self) PyOpView (PyOpView::buildGeneric (
3518
- name, opRegionSpec, operandSegmentSpecObj,
3519
- resultSegmentSpecObj, resultTypeList, operandList,
3520
- attributes, successors, regions, ___location, maybeIp));
3615
+ PyMlirContextRef ctx = ___location->getContext ();
3616
+ if (auto loc = tracebackToLocation (ctx->get ())) {
3617
+ new (self) PyOpView (PyOpView::buildGeneric (
3618
+ name, opRegionSpec, operandSegmentSpecObj,
3619
+ resultSegmentSpecObj, resultTypeList, operandList,
3620
+ attributes, successors, regions, {ctx, *loc}, maybeIp));
3621
+ } else {
3622
+ new (self) PyOpView (PyOpView::buildGeneric (
3623
+ name, opRegionSpec, operandSegmentSpecObj,
3624
+ resultSegmentSpecObj, resultTypeList, operandList,
3625
+ attributes, successors, regions, *___location.get (),
3626
+ maybeIp));
3627
+ }
3521
3628
},
3522
3629
nb::arg (" name" ), nb::arg (" opRegionSpec" ),
3523
3630
nb::arg (" operandSegmentSpecObj" ).none () = nb::none (),
@@ -3558,10 +3665,18 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3558
3665
nb::cast<std::tuple<int , bool >>(cls.attr (" _ODS_REGIONS" ));
3559
3666
nb::object operandSegmentSpec = cls.attr (" _ODS_OPERAND_SEGMENTS" );
3560
3667
nb::object resultSegmentSpec = cls.attr (" _ODS_RESULT_SEGMENTS" );
3668
+
3669
+ PyMlirContextRef ctx = ___location->getContext ();
3670
+ if (auto loc = tracebackToLocation (ctx->get ())) {
3671
+ return PyOpView::buildGeneric (name, opRegionSpec, operandSegmentSpec,
3672
+ resultSegmentSpec, resultTypeList,
3673
+ operandList, attributes, successors,
3674
+ regions, {ctx, *loc}, maybeIp);
3675
+ }
3561
3676
return PyOpView::buildGeneric (name, opRegionSpec, operandSegmentSpec,
3562
3677
resultSegmentSpec, resultTypeList,
3563
3678
operandList, attributes, successors,
3564
- regions, ___location, maybeIp);
3679
+ regions, * ___location. get () , maybeIp);
3565
3680
},
3566
3681
nb::arg (" cls" ), nb::arg (" results" ).none () = nb::none (),
3567
3682
nb::arg (" operands" ).none () = nb::none (),
0 commit comments