1 | //===- DialectLLVM.cpp - Pybind module for LLVM dialect API support -------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "mlir-c/Dialect/LLVM.h" |
10 | #include "mlir-c/IR.h" |
11 | #include "mlir-c/Support.h" |
12 | #include "mlir/Bindings/Python/PybindAdaptors.h" |
13 | #include <string> |
14 | |
15 | namespace py = pybind11; |
16 | using namespace llvm; |
17 | using namespace mlir; |
18 | using namespace mlir::python; |
19 | using namespace mlir::python::adaptors; |
20 | |
21 | void populateDialectLLVMSubmodule(const pybind11::module &m) { |
22 | |
23 | //===--------------------------------------------------------------------===// |
24 | // StructType |
25 | //===--------------------------------------------------------------------===// |
26 | |
27 | auto llvmStructType = |
28 | mlir_type_subclass(m, "StructType" , mlirTypeIsALLVMStructType); |
29 | |
30 | llvmStructType.def_classmethod( |
31 | "get_literal" , |
32 | [](py::object cls, const std::vector<MlirType> &elements, bool packed, |
33 | MlirLocation loc) { |
34 | CollectDiagnosticsToStringScope scope(mlirLocationGetContext(loc)); |
35 | |
36 | MlirType type = mlirLLVMStructTypeLiteralGetChecked( |
37 | loc, elements.size(), elements.data(), packed); |
38 | if (mlirTypeIsNull(type)) { |
39 | throw py::value_error(scope.takeMessage()); |
40 | } |
41 | return cls(type); |
42 | }, |
43 | "cls"_a , "elements"_a , py::kw_only(), "packed"_a = false, |
44 | "loc"_a = py::none()); |
45 | |
46 | llvmStructType.def_classmethod( |
47 | "get_identified" , |
48 | [](py::object cls, const std::string &name, MlirContext context) { |
49 | return cls(mlirLLVMStructTypeIdentifiedGet( |
50 | context, mlirStringRefCreate(name.data(), name.size()))); |
51 | }, |
52 | "cls"_a , "name"_a , py::kw_only(), "context"_a = py::none()); |
53 | |
54 | llvmStructType.def_classmethod( |
55 | "get_opaque" , |
56 | [](py::object cls, const std::string &name, MlirContext context) { |
57 | return cls(mlirLLVMStructTypeOpaqueGet( |
58 | context, mlirStringRefCreate(name.data(), name.size()))); |
59 | }, |
60 | "cls"_a , "name"_a , "context"_a = py::none()); |
61 | |
62 | llvmStructType.def( |
63 | "set_body" , |
64 | [](MlirType self, const std::vector<MlirType> &elements, bool packed) { |
65 | MlirLogicalResult result = mlirLLVMStructTypeSetBody( |
66 | self, elements.size(), elements.data(), packed); |
67 | if (!mlirLogicalResultIsSuccess(result)) { |
68 | throw py::value_error( |
69 | "Struct body already set to different content." ); |
70 | } |
71 | }, |
72 | "elements"_a , py::kw_only(), "packed"_a = false); |
73 | |
74 | llvmStructType.def_classmethod( |
75 | "new_identified" , |
76 | [](py::object cls, const std::string &name, |
77 | const std::vector<MlirType> &elements, bool packed, MlirContext ctx) { |
78 | return cls(mlirLLVMStructTypeIdentifiedNewGet( |
79 | ctx, mlirStringRefCreate(name.data(), name.length()), |
80 | elements.size(), elements.data(), packed)); |
81 | }, |
82 | "cls"_a , "name"_a , "elements"_a , py::kw_only(), "packed"_a = false, |
83 | "context"_a = py::none()); |
84 | |
85 | llvmStructType.def_property_readonly( |
86 | "name" , [](MlirType type) -> std::optional<std::string> { |
87 | if (mlirLLVMStructTypeIsLiteral(type)) |
88 | return std::nullopt; |
89 | |
90 | MlirStringRef stringRef = mlirLLVMStructTypeGetIdentifier(type); |
91 | return StringRef(stringRef.data, stringRef.length).str(); |
92 | }); |
93 | |
94 | llvmStructType.def_property_readonly("body" , [](MlirType type) -> py::object { |
95 | // Don't crash in absence of a body. |
96 | if (mlirLLVMStructTypeIsOpaque(type)) |
97 | return py::none(); |
98 | |
99 | py::list body; |
100 | for (intptr_t i = 0, e = mlirLLVMStructTypeGetNumElementTypes(type); i < e; |
101 | ++i) { |
102 | body.append(mlirLLVMStructTypeGetElementType(type, i)); |
103 | } |
104 | return body; |
105 | }); |
106 | |
107 | llvmStructType.def_property_readonly( |
108 | "packed" , [](MlirType type) { return mlirLLVMStructTypeIsPacked(type); }); |
109 | |
110 | llvmStructType.def_property_readonly( |
111 | "opaque" , [](MlirType type) { return mlirLLVMStructTypeIsOpaque(type); }); |
112 | |
113 | //===--------------------------------------------------------------------===// |
114 | // PointerType |
115 | //===--------------------------------------------------------------------===// |
116 | |
117 | mlir_type_subclass(m, "PointerType" , mlirTypeIsALLVMPointerType) |
118 | .def_classmethod( |
119 | "get" , |
120 | [](py::object cls, std::optional<unsigned> addressSpace, |
121 | MlirContext context) { |
122 | CollectDiagnosticsToStringScope scope(context); |
123 | MlirType type = mlirLLVMPointerTypeGet( |
124 | context, addressSpace.has_value() ? *addressSpace : 0); |
125 | if (mlirTypeIsNull(type)) { |
126 | throw py::value_error(scope.takeMessage()); |
127 | } |
128 | return cls(type); |
129 | }, |
130 | "cls"_a , "address_space"_a = py::none(), py::kw_only(), |
131 | "context"_a = py::none()) |
132 | .def_property_readonly("address_space" , [](MlirType type) { |
133 | return mlirLLVMPointerTypeGetAddressSpace(type); |
134 | }); |
135 | } |
136 | |
137 | PYBIND11_MODULE(_mlirDialectsLLVM, m) { |
138 | m.doc() = "MLIR LLVM Dialect" ; |
139 | |
140 | populateDialectLLVMSubmodule(m); |
141 | } |
142 | |